if_iwn.c (293179) | if_iwn.c (293716) |
---|---|
1/*- 2 * Copyright (c) 2007-2009 Damien Bergamini <damien.bergamini@free.fr> 3 * Copyright (c) 2008 Benjamin Close <benjsc@FreeBSD.org> 4 * Copyright (c) 2008 Sam Leffler, Errno Consulting 5 * Copyright (c) 2011 Intel Corporation 6 * Copyright (c) 2013 Cedric GROSS <c.gross@kreiz-it.fr> 7 * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 8 * --- 11 unchanged lines hidden (view full) --- 20 */ 21 22/* 23 * Driver for Intel WiFi Link 4965 and 1000/5000/6000 Series 802.11 network 24 * adapters. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2007-2009 Damien Bergamini <damien.bergamini@free.fr> 3 * Copyright (c) 2008 Benjamin Close <benjsc@FreeBSD.org> 4 * Copyright (c) 2008 Sam Leffler, Errno Consulting 5 * Copyright (c) 2011 Intel Corporation 6 * Copyright (c) 2013 Cedric GROSS <c.gross@kreiz-it.fr> 7 * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 8 * --- 11 unchanged lines hidden (view full) --- 20 */ 21 22/* 23 * Driver for Intel WiFi Link 4965 and 1000/5000/6000 Series 802.11 network 24 * adapters. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/dev/iwn/if_iwn.c 293179 2016-01-04 21:11:27Z avos $"); | 28__FBSDID("$FreeBSD: head/sys/dev/iwn/if_iwn.c 293716 2016-01-12 00:24:40Z avos $"); |
29 30#include "opt_wlan.h" 31#include "opt_iwn.h" 32 33#include <sys/param.h> 34#include <sys/sockio.h> 35#include <sys/sysctl.h> 36#include <sys/mbuf.h> --- 135 unchanged lines hidden (view full) --- 172static int iwn_read_eeprom(struct iwn_softc *, 173 uint8_t macaddr[IEEE80211_ADDR_LEN]); 174static void iwn4965_read_eeprom(struct iwn_softc *); 175#ifdef IWN_DEBUG 176static void iwn4965_print_power_group(struct iwn_softc *, int); 177#endif 178static void iwn5000_read_eeprom(struct iwn_softc *); 179static uint32_t iwn_eeprom_channel_flags(struct iwn_eeprom_chan *); | 29 30#include "opt_wlan.h" 31#include "opt_iwn.h" 32 33#include <sys/param.h> 34#include <sys/sockio.h> 35#include <sys/sysctl.h> 36#include <sys/mbuf.h> --- 135 unchanged lines hidden (view full) --- 172static int iwn_read_eeprom(struct iwn_softc *, 173 uint8_t macaddr[IEEE80211_ADDR_LEN]); 174static void iwn4965_read_eeprom(struct iwn_softc *); 175#ifdef IWN_DEBUG 176static void iwn4965_print_power_group(struct iwn_softc *, int); 177#endif 178static void iwn5000_read_eeprom(struct iwn_softc *); 179static uint32_t iwn_eeprom_channel_flags(struct iwn_eeprom_chan *); |
180static void iwn_read_eeprom_band(struct iwn_softc *, int); 181static void iwn_read_eeprom_ht40(struct iwn_softc *, int); | 180static void iwn_read_eeprom_band(struct iwn_softc *, int, int, int *, 181 struct ieee80211_channel[]); 182static void iwn_read_eeprom_ht40(struct iwn_softc *, int, int, int *, 183 struct ieee80211_channel[]); |
182static void iwn_read_eeprom_channels(struct iwn_softc *, int, uint32_t); 183static struct iwn_eeprom_chan *iwn_find_eeprom_channel(struct iwn_softc *, 184 struct ieee80211_channel *); | 184static void iwn_read_eeprom_channels(struct iwn_softc *, int, uint32_t); 185static struct iwn_eeprom_chan *iwn_find_eeprom_channel(struct iwn_softc *, 186 struct ieee80211_channel *); |
187static void iwn_getradiocaps(struct ieee80211com *, int, int *, 188 struct ieee80211_channel[]); |
|
185static int iwn_setregdomain(struct ieee80211com *, 186 struct ieee80211_regdomain *, int, 187 struct ieee80211_channel[]); 188static void iwn_read_eeprom_enhinfo(struct iwn_softc *); 189static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *, 190 const uint8_t mac[IEEE80211_ADDR_LEN]); 191static void iwn_newassoc(struct ieee80211_node *, int); 192static int iwn_media_change(struct ifnet *); --- 468 unchanged lines hidden (view full) --- 661 ic->ic_newassoc = iwn_newassoc; 662 ic->ic_wme.wme_update = iwn_updateedca; 663 ic->ic_update_mcast = iwn_update_mcast; 664 ic->ic_scan_start = iwn_scan_start; 665 ic->ic_scan_end = iwn_scan_end; 666 ic->ic_set_channel = iwn_set_channel; 667 ic->ic_scan_curchan = iwn_scan_curchan; 668 ic->ic_scan_mindwell = iwn_scan_mindwell; | 189static int iwn_setregdomain(struct ieee80211com *, 190 struct ieee80211_regdomain *, int, 191 struct ieee80211_channel[]); 192static void iwn_read_eeprom_enhinfo(struct iwn_softc *); 193static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *, 194 const uint8_t mac[IEEE80211_ADDR_LEN]); 195static void iwn_newassoc(struct ieee80211_node *, int); 196static int iwn_media_change(struct ifnet *); --- 468 unchanged lines hidden (view full) --- 665 ic->ic_newassoc = iwn_newassoc; 666 ic->ic_wme.wme_update = iwn_updateedca; 667 ic->ic_update_mcast = iwn_update_mcast; 668 ic->ic_scan_start = iwn_scan_start; 669 ic->ic_scan_end = iwn_scan_end; 670 ic->ic_set_channel = iwn_set_channel; 671 ic->ic_scan_curchan = iwn_scan_curchan; 672 ic->ic_scan_mindwell = iwn_scan_mindwell; |
673 ic->ic_getradiocaps = iwn_getradiocaps; |
|
669 ic->ic_setregdomain = iwn_setregdomain; 670 671 iwn_radiotap_attach(sc); 672 673 callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0); 674 callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0); 675 TASK_INIT(&sc->sc_reinit_task, 0, iwn_hw_reset, sc); 676 TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc); --- 1689 unchanged lines hidden (view full) --- 2366 /* XXX apparently IBSS may still be marked */ 2367 nflags |= IEEE80211_CHAN_NOADHOC; 2368 } 2369 2370 return nflags; 2371} 2372 2373static void | 674 ic->ic_setregdomain = iwn_setregdomain; 675 676 iwn_radiotap_attach(sc); 677 678 callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0); 679 callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0); 680 TASK_INIT(&sc->sc_reinit_task, 0, iwn_hw_reset, sc); 681 TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc); --- 1689 unchanged lines hidden (view full) --- 2371 /* XXX apparently IBSS may still be marked */ 2372 nflags |= IEEE80211_CHAN_NOADHOC; 2373 } 2374 2375 return nflags; 2376} 2377 2378static void |
2374iwn_read_eeprom_band(struct iwn_softc *sc, int n) | 2379iwn_read_eeprom_band(struct iwn_softc *sc, int n, int maxchans, int *nchans, 2380 struct ieee80211_channel chans[]) |
2375{ | 2381{ |
2376 struct ieee80211com *ic = &sc->sc_ic; | |
2377 struct iwn_eeprom_chan *channels = sc->eeprom_channels[n]; 2378 const struct iwn_chan_band *band = &iwn_bands[n]; 2379 struct ieee80211_channel *c; 2380 uint8_t chan; 2381 int i, nflags; 2382 2383 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); 2384 2385 for (i = 0; i < band->nchan; i++) { 2386 if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID)) { 2387 DPRINTF(sc, IWN_DEBUG_RESET, 2388 "skip chan %d flags 0x%x maxpwr %d\n", 2389 band->chan[i], channels[i].flags, 2390 channels[i].maxpwr); 2391 continue; 2392 } | 2382 struct iwn_eeprom_chan *channels = sc->eeprom_channels[n]; 2383 const struct iwn_chan_band *band = &iwn_bands[n]; 2384 struct ieee80211_channel *c; 2385 uint8_t chan; 2386 int i, nflags; 2387 2388 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); 2389 2390 for (i = 0; i < band->nchan; i++) { 2391 if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID)) { 2392 DPRINTF(sc, IWN_DEBUG_RESET, 2393 "skip chan %d flags 0x%x maxpwr %d\n", 2394 band->chan[i], channels[i].flags, 2395 channels[i].maxpwr); 2396 continue; 2397 } |
2398 2399 if (*nchans >= maxchans) 2400 break; 2401 |
|
2393 chan = band->chan[i]; 2394 nflags = iwn_eeprom_channel_flags(&channels[i]); 2395 | 2402 chan = band->chan[i]; 2403 nflags = iwn_eeprom_channel_flags(&channels[i]); 2404 |
2396 c = &ic->ic_channels[ic->ic_nchans++]; | 2405 c = &chans[(*nchans)++]; |
2397 c->ic_ieee = chan; 2398 c->ic_maxregpower = channels[i].maxpwr; 2399 c->ic_maxpower = 2*c->ic_maxregpower; 2400 2401 if (n == 0) { /* 2GHz band */ 2402 c->ic_freq = ieee80211_ieee2mhz(chan, IEEE80211_CHAN_G); 2403 /* G =>'s B is supported */ 2404 c->ic_flags = IEEE80211_CHAN_B | nflags; | 2406 c->ic_ieee = chan; 2407 c->ic_maxregpower = channels[i].maxpwr; 2408 c->ic_maxpower = 2*c->ic_maxregpower; 2409 2410 if (n == 0) { /* 2GHz band */ 2411 c->ic_freq = ieee80211_ieee2mhz(chan, IEEE80211_CHAN_G); 2412 /* G =>'s B is supported */ 2413 c->ic_flags = IEEE80211_CHAN_B | nflags; |
2405 c = &ic->ic_channels[ic->ic_nchans++]; | 2414 2415 if (*nchans >= maxchans) 2416 break; 2417 2418 c = &chans[(*nchans)++]; |
2406 c[0] = c[-1]; 2407 c->ic_flags = IEEE80211_CHAN_G | nflags; 2408 } else { /* 5GHz band */ 2409 c->ic_freq = ieee80211_ieee2mhz(chan, IEEE80211_CHAN_A); 2410 c->ic_flags = IEEE80211_CHAN_A | nflags; 2411 } 2412 2413 /* Save maximum allowed TX power for this channel. */ 2414 sc->maxpwr[chan] = channels[i].maxpwr; 2415 2416 DPRINTF(sc, IWN_DEBUG_RESET, 2417 "add chan %d flags 0x%x maxpwr %d\n", chan, 2418 channels[i].flags, channels[i].maxpwr); 2419 2420 if (sc->sc_flags & IWN_FLAG_HAS_11N) { | 2419 c[0] = c[-1]; 2420 c->ic_flags = IEEE80211_CHAN_G | nflags; 2421 } else { /* 5GHz band */ 2422 c->ic_freq = ieee80211_ieee2mhz(chan, IEEE80211_CHAN_A); 2423 c->ic_flags = IEEE80211_CHAN_A | nflags; 2424 } 2425 2426 /* Save maximum allowed TX power for this channel. */ 2427 sc->maxpwr[chan] = channels[i].maxpwr; 2428 2429 DPRINTF(sc, IWN_DEBUG_RESET, 2430 "add chan %d flags 0x%x maxpwr %d\n", chan, 2431 channels[i].flags, channels[i].maxpwr); 2432 2433 if (sc->sc_flags & IWN_FLAG_HAS_11N) { |
2434 if (*nchans >= maxchans) 2435 break; 2436 |
|
2421 /* add HT20, HT40 added separately */ | 2437 /* add HT20, HT40 added separately */ |
2422 c = &ic->ic_channels[ic->ic_nchans++]; | 2438 c = &chans[(*nchans)++]; |
2423 c[0] = c[-1]; 2424 c->ic_flags |= IEEE80211_CHAN_HT20; 2425 } 2426 } 2427 2428 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__); 2429 2430} 2431 2432static void | 2439 c[0] = c[-1]; 2440 c->ic_flags |= IEEE80211_CHAN_HT20; 2441 } 2442 } 2443 2444 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__); 2445 2446} 2447 2448static void |
2433iwn_read_eeprom_ht40(struct iwn_softc *sc, int n) | 2449iwn_read_eeprom_ht40(struct iwn_softc *sc, int n, int maxchans, int *nchans, 2450 struct ieee80211_channel chans[]) |
2434{ 2435 struct ieee80211com *ic = &sc->sc_ic; 2436 struct iwn_eeprom_chan *channels = sc->eeprom_channels[n]; 2437 const struct iwn_chan_band *band = &iwn_bands[n]; 2438 struct ieee80211_channel *c, *cent, *extc; 2439 uint8_t chan; 2440 int i, nflags; 2441 --- 7 unchanged lines hidden (view full) --- 2449 for (i = 0; i < band->nchan; i++) { 2450 if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID)) { 2451 DPRINTF(sc, IWN_DEBUG_RESET, 2452 "skip chan %d flags 0x%x maxpwr %d\n", 2453 band->chan[i], channels[i].flags, 2454 channels[i].maxpwr); 2455 continue; 2456 } | 2451{ 2452 struct ieee80211com *ic = &sc->sc_ic; 2453 struct iwn_eeprom_chan *channels = sc->eeprom_channels[n]; 2454 const struct iwn_chan_band *band = &iwn_bands[n]; 2455 struct ieee80211_channel *c, *cent, *extc; 2456 uint8_t chan; 2457 int i, nflags; 2458 --- 7 unchanged lines hidden (view full) --- 2466 for (i = 0; i < band->nchan; i++) { 2467 if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID)) { 2468 DPRINTF(sc, IWN_DEBUG_RESET, 2469 "skip chan %d flags 0x%x maxpwr %d\n", 2470 band->chan[i], channels[i].flags, 2471 channels[i].maxpwr); 2472 continue; 2473 } |
2474 2475 if (*nchans + 1 >= maxchans) 2476 break; 2477 |
|
2457 chan = band->chan[i]; 2458 nflags = iwn_eeprom_channel_flags(&channels[i]); 2459 2460 /* 2461 * Each entry defines an HT40 channel pair; find the 2462 * center channel, then the extension channel above. 2463 */ 2464 cent = ieee80211_find_channel_byieee(ic, chan, --- 11 unchanged lines hidden (view full) --- 2476 __func__, chan); 2477 continue; 2478 } 2479 2480 DPRINTF(sc, IWN_DEBUG_RESET, 2481 "add ht40 chan %d flags 0x%x maxpwr %d\n", 2482 chan, channels[i].flags, channels[i].maxpwr); 2483 | 2478 chan = band->chan[i]; 2479 nflags = iwn_eeprom_channel_flags(&channels[i]); 2480 2481 /* 2482 * Each entry defines an HT40 channel pair; find the 2483 * center channel, then the extension channel above. 2484 */ 2485 cent = ieee80211_find_channel_byieee(ic, chan, --- 11 unchanged lines hidden (view full) --- 2497 __func__, chan); 2498 continue; 2499 } 2500 2501 DPRINTF(sc, IWN_DEBUG_RESET, 2502 "add ht40 chan %d flags 0x%x maxpwr %d\n", 2503 chan, channels[i].flags, channels[i].maxpwr); 2504 |
2484 c = &ic->ic_channels[ic->ic_nchans++]; | 2505 c = &chans[(*nchans)++]; |
2485 c[0] = cent[0]; 2486 c->ic_extieee = extc->ic_ieee; 2487 c->ic_flags &= ~IEEE80211_CHAN_HT; 2488 c->ic_flags |= IEEE80211_CHAN_HT40U | nflags; | 2506 c[0] = cent[0]; 2507 c->ic_extieee = extc->ic_ieee; 2508 c->ic_flags &= ~IEEE80211_CHAN_HT; 2509 c->ic_flags |= IEEE80211_CHAN_HT40U | nflags; |
2489 c = &ic->ic_channels[ic->ic_nchans++]; | 2510 c = &chans[(*nchans)++]; |
2490 c[0] = extc[0]; 2491 c->ic_extieee = cent->ic_ieee; 2492 c->ic_flags &= ~IEEE80211_CHAN_HT; 2493 c->ic_flags |= IEEE80211_CHAN_HT40D | nflags; 2494 } 2495 2496 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__); 2497 2498} 2499 2500static void 2501iwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr) 2502{ 2503 struct ieee80211com *ic = &sc->sc_ic; 2504 2505 iwn_read_prom_data(sc, addr, &sc->eeprom_channels[n], 2506 iwn_bands[n].nchan * sizeof (struct iwn_eeprom_chan)); 2507 | 2511 c[0] = extc[0]; 2512 c->ic_extieee = cent->ic_ieee; 2513 c->ic_flags &= ~IEEE80211_CHAN_HT; 2514 c->ic_flags |= IEEE80211_CHAN_HT40D | nflags; 2515 } 2516 2517 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__); 2518 2519} 2520 2521static void 2522iwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr) 2523{ 2524 struct ieee80211com *ic = &sc->sc_ic; 2525 2526 iwn_read_prom_data(sc, addr, &sc->eeprom_channels[n], 2527 iwn_bands[n].nchan * sizeof (struct iwn_eeprom_chan)); 2528 |
2508 if (n < 5) 2509 iwn_read_eeprom_band(sc, n); 2510 else 2511 iwn_read_eeprom_ht40(sc, n); | 2529 if (n < 5) { 2530 iwn_read_eeprom_band(sc, n, IEEE80211_CHAN_MAX, &ic->ic_nchans, 2531 ic->ic_channels); 2532 } else { 2533 iwn_read_eeprom_ht40(sc, n, IEEE80211_CHAN_MAX, &ic->ic_nchans, 2534 ic->ic_channels); 2535 } |
2512 ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans); 2513} 2514 2515static struct iwn_eeprom_chan * 2516iwn_find_eeprom_channel(struct iwn_softc *sc, struct ieee80211_channel *c) 2517{ 2518 int band, chan, i, j; 2519 --- 13 unchanged lines hidden (view full) --- 2533 if (iwn_bands[j].chan[i] == c->ic_ieee) 2534 return &sc->eeprom_channels[j][i]; 2535 } 2536 } 2537 } 2538 return NULL; 2539} 2540 | 2536 ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans); 2537} 2538 2539static struct iwn_eeprom_chan * 2540iwn_find_eeprom_channel(struct iwn_softc *sc, struct ieee80211_channel *c) 2541{ 2542 int band, chan, i, j; 2543 --- 13 unchanged lines hidden (view full) --- 2557 if (iwn_bands[j].chan[i] == c->ic_ieee) 2558 return &sc->eeprom_channels[j][i]; 2559 } 2560 } 2561 } 2562 return NULL; 2563} 2564 |
2565static void 2566iwn_getradiocaps(struct ieee80211com *ic, 2567 int maxchans, int *nchans, struct ieee80211_channel chans[]) 2568{ 2569 struct iwn_softc *sc = ic->ic_softc; 2570 int i; 2571 2572 /* Parse the list of authorized channels. */ 2573 for (i = 0; i < 5 && *nchans < maxchans; i++) 2574 iwn_read_eeprom_band(sc, i, maxchans, nchans, chans); 2575 for (i = 5; i < IWN_NBANDS - 1 && *nchans < maxchans; i++) 2576 iwn_read_eeprom_ht40(sc, i, maxchans, nchans, chans); 2577} 2578 |
|
2541/* 2542 * Enforce flags read from EEPROM. 2543 */ 2544static int 2545iwn_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd, 2546 int nchan, struct ieee80211_channel chans[]) 2547{ 2548 struct iwn_softc *sc = ic->ic_softc; --- 6435 unchanged lines hidden --- | 2579/* 2580 * Enforce flags read from EEPROM. 2581 */ 2582static int 2583iwn_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd, 2584 int nchan, struct ieee80211_channel chans[]) 2585{ 2586 struct iwn_softc *sc = ic->ic_softc; --- 6435 unchanged lines hidden --- |