📄 if_ath.c.svn-base
字号:
MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability. Default is 0.");#ifdef ATH_CAP_TPCMODULE_PARM_DESC(hal_tpc, "Disables manual per-packet transmit power control and " "lets this be managed by the HAL. Default is OFF.");#endifMODULE_PARM_DESC(autocreate, "Create ath device in " "[sta|ap|wds|adhoc|ahdemo|monitor] mode. defaults to sta, use " "'none' to disable");MODULE_PARM_DESC(ratectl, "Rate control algorithm [amrr|minstrel|onoe|sample], " "defaults to '" DEF_RATE_CTL "'");MODULE_PARM_DESC(intmit, "Enable interference mitigation by default. Default is 0.");static int ath_debug = 0;#ifdef AR_DEBUG#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))MODULE_PARM(ath_debug, "i");#elsemodule_param(ath_debug, int, 0600);#endifMODULE_PARM_DESC(ath_debug, "Load-time driver debug output enable");static void ath_printrxbuf(const struct ath_buf *, int);static void ath_printtxbuf(const struct ath_buf *, int);#endif /* defined(AR_DEBUG) */static int ieee80211_debug = 0;#ifdef AR_DEBUG#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))MODULE_PARM(ieee80211_debug, "i");#elsemodule_param(ieee80211_debug, int, 0600);#endifMODULE_PARM_DESC(ieee80211_debug, "Load-time 802.11 debug output enable");#endif /* defined(AR_DEBUG) */#define ATH_SETUP_XR_VAP(sc,vap,rfilt) \ do { \ if (sc->sc_curchan.privFlags & CHANNEL_4MS_LIMIT) \ vap->iv_fragthreshold = XR_4MS_FRAG_THRESHOLD; \ else \ vap->iv_fragthreshold = vap->iv_xrvap->iv_fragthreshold;\ if (!sc->sc_xrgrppoll) { \ ath_grppoll_txq_setup(sc, HAL_TX_QUEUE_DATA, \ GRP_POLL_PERIOD_NO_XR_STA(sc)); \ ath_grppoll_start(vap, sc->sc_xrpollcount); \ ath_hal_setrxfilter(sc->sc_ah, \ rfilt|HAL_RX_FILTER_XRPOLL); \ } \ } while (0)/* * Define the scheme that we select MAC address for multiple BSS on the same radio. * The very first VAP will just use the MAC address from the EEPROM. * For the next 3 VAPs, we set the U/L bit (bit 1) in MAC address, * and use the higher bits as the index of the VAP. */#define ATH_SET_VAP_BSSID_MASK(bssid_mask) \ ((bssid_mask)[0] &= ~(((ath_maxvaps-1) << 2) | 0x02))#define ATH_GET_VAP_ID(bssid) ((bssid)[0] >> 2)#define ATH_SET_VAP_BSSID(bssid, id) \ do { \ if (id) \ (bssid)[0] |= (((id) << 2) | 0x02); \ } while (0)/* Initialize ath_softc structure */intath_attach(u_int16_t devid, struct net_device *dev, HAL_BUS_TAG tag){ struct ath_softc *sc = netdev_priv(dev); struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap; struct ath_hal *ah; HAL_STATUS status; int error = 0; unsigned int i; int autocreatemode = IEEE80211_M_STA; u_int8_t csz; sc->devid = devid; ath_debug_global = (ath_debug & ATH_DEBUG_GLOBAL); sc->sc_debug = (ath_debug & ~ATH_DEBUG_GLOBAL); DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid); /* Allocate space for dynamically determined maximum VAP count */ sc->sc_bslot = kzalloc(ath_maxvaps * sizeof(struct ieee80211vap), GFP_KERNEL); /* * Cache line size is used to size and align various * structures used to communicate with the hardware. */ bus_read_cachesize(sc, &csz); /* XXX assert csz is non-zero */ sc->sc_cachelsz = csz << 2; /* convert to bytes */ ATH_LOCK_INIT(sc); ATH_HAL_LOCK_INIT(sc); ATH_TXBUF_LOCK_INIT(sc); ATH_RXBUF_LOCK_INIT(sc); ATH_BBUF_LOCK_INIT(sc); ATH_GBUF_LOCK_INIT(sc); atomic_set(&sc->sc_txbuf_counter, 0); ATH_INIT_TQUEUE(&sc->sc_rxtq, ath_rx_tasklet, dev); ATH_INIT_TQUEUE(&sc->sc_txtq, ath_tx_tasklet, dev); ATH_INIT_TQUEUE(&sc->sc_bmisstq, ath_bmiss_tasklet, dev); ATH_INIT_TQUEUE(&sc->sc_bstucktq, ath_bstuck_tasklet, dev); ATH_INIT_TQUEUE(&sc->sc_rxorntq, ath_rxorn_tasklet, dev); ATH_INIT_TQUEUE(&sc->sc_fataltq, ath_fatal_tasklet, dev); /* * Attach the HAL and verify ABI compatibility by checking * the HAL's ABI signature against the one the driver was * compiled with. A mismatch indicates the driver was * built with an ah.h that does not correspond to the HAL * module loaded in the kernel. */ ah = _ath_hal_attach(devid, sc, tag, sc->sc_iobase, &status); if (ah == NULL) { printk(KERN_ERR "%s: unable to attach hardware: '%s' " "(HAL status %u)\n", DEV_NAME(dev), ath_get_hal_status_desc(status), status); error = ENXIO; goto bad; } if (ah->ah_abi != HAL_ABI_VERSION) { printk(KERN_ERR "%s: HAL ABI mismatch; " "driver expects 0x%x, HAL reports 0x%x\n", DEV_NAME(dev), HAL_ABI_VERSION, ah->ah_abi); error = ENXIO; /* XXX */ goto bad; } sc->sc_ah = ah; /* * TPC support can be done either with a global cap or * per-packet support. The latter is not available on * all parts. We're a bit pedantic here as all parts * support a global cap. */#ifdef ATH_CAP_TPC sc->sc_hastpc = ath_hal_hastpc(ah); if (hal_tpc && !sc->sc_hastpc) { WPRINTF(sc, "HAL managed transmit power control (TPC) " "was requested, but is not " "supported by the HAL.\n"); hal_tpc = 0; } DPRINTF(sc, ATH_DEBUG_ANY, "HAL managed transmit power control (TPC) " "%s.\n", hal_tpc ? "enabled" : "disabled"); ath_hal_settpc(ah, hal_tpc);#else sc->sc_hastpc = 0; hal_tpc = 0; /* TPC is always zero, when compiled without ATH_CAP_TPC */#endif /* * Init ic_caps prior to queue init, since WME cap setting * depends on queue setup. */ ic->ic_caps = 0; if (ath_hal_hastxpowlimit(ah)) { ic->ic_caps |= IEEE80211_C_TXPMGT; } /* Interference mitigation/ambient noise immunity (ANI). * In modes other than HAL_M_STA, it causes receive sensitivity * problems for OFDM. */ sc->sc_hasintmit = ath_hal_hasintmit(ah); sc->sc_useintmit = (intmit && sc->sc_hasintmit); if (!sc->sc_hasintmit && intmit) { WPRINTF(sc, "Interference mitigation was requested, but is not" "supported by the HAL/hardware.\n"); intmit = 0; /* Stop use in future ath_attach(). */ }#if 0 else { ath_hal_setintmit(ah, sc->sc_useintmit); DPRINTF(sc, ATH_DEBUG_ANY, "Interference mitigation is " "supported. Currently %s.\n", (sc->sc_useintmit ? "enabled" : "disabled")); }#endif sc->sc_dmasize_stomp = 0; /* * Check if the MAC has multi-rate retry support. * We do this by trying to setup a fake extended * descriptor. MACs that don't have support will * return false w/o doing anything. MACs that do * support it will return true w/o doing anything. */ sc->sc_mrretry = ath_hal_setupxtxdesc(ah, NULL, 0,0, 0,0, 0,0); /* * Check if the device has hardware counters for PHY * errors. If so we need to enable the MIB interrupt * so we can act on stat triggers. */ sc->sc_needmib = ath_hal_hwphycounters(ah) && sc->sc_hasintmit && sc->sc_useintmit; /* * Get the hardware key cache size. */ sc->sc_keymax = ath_hal_keycachesize(ah); if (sc->sc_keymax > ATH_KEYMAX) { WPRINTF(sc, "Using only %u entries in %u key cache.\n", ATH_KEYMAX, sc->sc_keymax); sc->sc_keymax = ATH_KEYMAX; } /* * Reset the key cache since some parts do not * reset the contents on initial power up. */ for (i = 0; i < sc->sc_keymax; i++) ath_hal_keyreset(ah, i); /* * Collect the channel list using the default country * code and including outdoor channels. The 802.11 layer * is responsible for filtering this list based on settings * like the phy mode. */ if (countrycode != -1) ath_countrycode = countrycode; if (maxvaps != -1) { ath_maxvaps = maxvaps; if (ath_maxvaps < ATH_MAXVAPS_MIN) ath_maxvaps = ATH_MAXVAPS_MIN; else if (ath_maxvaps > ATH_MAXVAPS_MAX) ath_maxvaps = ATH_MAXVAPS_MAX; } if (outdoor != -1) ath_outdoor = outdoor; if (xchanmode != -1) ath_xchanmode = xchanmode; error = ath_getchannels(dev, ath_countrycode, ath_outdoor, ath_xchanmode); if (error != 0) goto bad; ic->ic_country_code = ath_countrycode; ic->ic_country_outdoor = ath_outdoor; IPRINTF(sc, "Switching rfkill capability %s.\n", rfkill ? "on" : "off"); ath_hal_setrfsilent(ah, rfkill); /* * Setup rate tables for all potential media types. */ ath_rate_setup(dev, IEEE80211_MODE_11A); ath_rate_setup(dev, IEEE80211_MODE_11B); ath_rate_setup(dev, IEEE80211_MODE_11G); ath_rate_setup(dev, IEEE80211_MODE_TURBO_A); ath_rate_setup(dev, IEEE80211_MODE_TURBO_G); /* Setup for half/quarter rates */ ath_setup_subrates(dev); /* NB: setup here so ath_rate_update is happy */ ath_setcurmode(sc, IEEE80211_MODE_11A); /* * Allocate tx+rx descriptors and populate the lists. */ error = ath_desc_alloc(sc); if (error != 0) { EPRINTF(sc, "Failed to allocate descriptors. Error %d.\n", error); goto bad; } /* * Allocate hardware transmit queues: one queue for * beacon frames and one data queue for each QoS * priority. Note that the HAL handles resetting * these queues at the needed time. * * XXX PS-Poll */ sc->sc_bhalq = ath_beaconq_setup(sc); if (sc->sc_bhalq == (u_int) -1) { EPRINTF(sc, "Unable to setup a beacon xmit queue!\n"); error = EIO; goto bad2; } /* CAB: Crap After Beacon - a beacon gated queue */ sc->sc_cabq = ath_txq_setup(sc, HAL_TX_QUEUE_CAB, 0); if (sc->sc_cabq == NULL) { EPRINTF(sc, "Unable to setup CAB transmit queue!\n"); error = EIO; goto bad2; } /* NB: ensure BK queue is the lowest priority h/w queue */ if (!ath_tx_setup(sc, WME_AC_BK, HAL_WME_AC_BK)) { EPRINTF(sc, "Unable to setup transmit queue for %s traffic!\n", ieee80211_wme_acnames[WME_AC_BK]); error = EIO; goto bad2; } if (!ath_tx_setup(sc, WME_AC_BE, HAL_WME_AC_BE) || !ath_tx_setup(sc, WME_AC_VI, HAL_WME_AC_VI) || !ath_tx_setup(sc, WME_AC_VO, HAL_WME_AC_VO)) { /* * Not enough hardware tx queues to properly do WME; * just punt and assign them all to the same h/w queue. * We could do a better job of this if, for example, * we allocate queues when we switch from station to * AP mode. */ if (sc->sc_ac2q[WME_AC_VI] != NULL) ath_tx_cleanupq(sc, sc->sc_ac2q[WME_AC_VI]); if (sc->sc_ac2q[WME_AC_BE] != NULL) ath_tx_cleanupq(sc, sc->sc_ac2q[WME_AC_BE]); sc->sc_ac2q[WME_AC_BE] = sc->sc_ac2q[WME_AC_BK]; sc->sc_ac2q[WME_AC_VI] = sc->sc_ac2q[WME_AC_BK]; sc->sc_ac2q[WME_AC_VO] = sc->sc_ac2q[WME_AC_BK]; } else { /* * Mark WME capability since we have sufficient * hardware queues to do proper priority scheduling. */ ic->ic_caps |= IEEE80211_C_WME; sc->sc_uapsdq = ath_txq_setup(sc, HAL_TX_QUEUE_UAPSD, 0); if (sc->sc_uapsdq == NULL) DPRINTF(sc, ATH_DEBUG_UAPSD, "Unable to setup UAPSD transmit queue!\n"); else { ic->ic_caps |= IEEE80211_C_UAPSD; /* * default UAPSD on if HW capable */ IEEE80211_COM_UAPSD_ENABLE(ic); } }#ifdef ATH_SUPERG_XR ath_xr_rate_setup(dev); sc->sc_xrpollint = XR_DEFAULT_POLL_INTERVAL; sc->sc_xrpollcount = XR_DEFAULT_POLL_COUNT; strcpy(sc->sc_grppoll_str, XR_DEFAULT_GRPPOLL_RATE_STR); sc->sc_grpplq.axq_qnum = -1; sc->sc_xrtxq = ath_txq_setup(sc, HAL_TX_QUEUE_DATA, HAL_XR_DATA);#endif sc->sc_calinterval_sec = ATH_SHORT_CALINTERVAL_SECS; sc->sc_lastcal = jiffies; /* * Special case certain configurations. Note the * CAB queue is handled by these specially so don't * include them when checking the txq setup mask. */ switch (sc->sc_txqsetup & ~((1 << sc->sc_cabq->axq_qnum) | (sc->sc_uapsdq ? (1 << sc->sc_uapsdq->axq_qnum) : 0))) { case 0x01: ATH_INIT_TQUEUE(&sc->sc_txtq, ath_tx_tasklet_q0, dev); break; case 0x0f: ATH_INIT_TQUEUE(&sc->sc_txtq, ath_tx_tasklet_q0123, dev); break; } sc->sc_setdefantenna = ath_setdefantenna; sc->sc_rc = ieee80211_rate_attach(sc, ratectl); if (sc->sc_rc == NULL) { error = EIO; goto bad2; } init_timer(&sc->sc_cal_ch); sc->sc_cal_ch.function = ath_calibrate; sc->sc_cal_ch.data = (unsigned long) dev; /* initialize DFS related variables */ sc->sc_dfswait = 0; sc->sc_dfs_cac = 0; sc->sc_dfs_testmode = 0; init_timer(&sc->sc_dfs_cac_timer); sc->sc_dfs_cac_timer.function = ath_dfs_cac_completed; sc->sc_dfs_cac_timer.data = (unsigned long) sc ; sc->sc_dfs_cac_period = ATH_DFS_WAIT_MIN_PERIOD; sc->sc_dfs_excl_period = ATH_DFS_AVOID_MIN_PERIOD; /* initialize radar stuff */ ath_rp_init(sc);#ifdef ATH_SUPERG_DYNTURBO init_timer(&sc->sc_dturbo_switch_mode); sc->sc_dturbo_switch_mode.function = ath_turbo_switch_mode; sc->sc_dturbo_switch_mode.data = (unsigned long) dev;#endif sc->sc_blinking = 0; sc->sc_ledstate = 1; sc->sc_ledon = 0; /* low true */ sc->sc_ledidle = msecs_to_jiffies(2700); /* 2.7 sec */ init_timer(&sc->sc_ledtimer); sc->sc_ledtimer.data = (unsigned long) sc; if (sc->sc_softled) { ath_hal_gpioCfgOutput(ah, sc->sc_ledpin);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -