X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=blobdiff_plain;f=package%2Fath9k%2Fsrc%2Fdrivers%2Fnet%2Fwireless%2Fath9k%2Fmain.c;h=9549524630f7f26209b012b51697ffe0895dece7;hp=670a5165a7c2bbb26dbd24565c004c58db9f8a42;hb=a31b8515c5d1bce262cc14a5386b26d1aa71c775;hpb=3e53b85806fc5b2faf08535421705f6cf2c020a7 diff --git a/package/ath9k/src/drivers/net/wireless/ath9k/main.c b/package/ath9k/src/drivers/net/wireless/ath9k/main.c index 670a5165a7..9549524630 100644 --- a/package/ath9k/src/drivers/net/wireless/ath9k/main.c +++ b/package/ath9k/src/drivers/net/wireless/ath9k/main.c @@ -41,44 +41,60 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = { { 0 } }; -static int test_update_chan(enum ieee80211_band band, - const struct hal_channel *chan, - struct ath_softc *sc) +static int ath_get_channel(struct ath_softc *sc, + struct ieee80211_channel *chan) { int i; - for (i = 0; i < sc->sbands[band].n_channels; i++) { - if (sc->channels[band][i].center_freq == chan->channel) - return 1; + for (i = 0; i < sc->sc_ah->ah_nchan; i++) { + if (sc->sc_ah->ah_channels[i].channel == chan->center_freq) + return i; } - return 0; + return -1; } -static int ath_check_chanflags(struct ieee80211_channel *chan, - u_int32_t mode, - struct ath_softc *sc) +static u32 ath_get_extchanmode(struct ath_softc *sc, + struct ieee80211_channel *chan) { - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_supported_band *band; - struct ieee80211_channel *band_channel; - int i; - - band = hw->wiphy->bands[chan->band]; - - for (i = 0; i < band->n_channels; i++) { - band_channel = &band->channels[i]; - - if ((band_channel->center_freq == chan->center_freq) && - ((band_channel->hw_value & mode) == mode)) - return 1; + u32 chanmode = 0; + u8 ext_chan_offset = sc->sc_ht_info.ext_chan_offset; + enum ath9k_ht_macmode tx_chan_width = sc->sc_ht_info.tx_chan_width; + + switch (chan->band) { + case IEEE80211_BAND_2GHZ: + if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) && + (tx_chan_width == ATH9K_HT_MACMODE_20)) + chanmode = CHANNEL_G_HT20; + if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) && + (tx_chan_width == ATH9K_HT_MACMODE_2040)) + chanmode = CHANNEL_G_HT40PLUS; + if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) && + (tx_chan_width == ATH9K_HT_MACMODE_2040)) + chanmode = CHANNEL_G_HT40MINUS; + break; + case IEEE80211_BAND_5GHZ: + if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) && + (tx_chan_width == ATH9K_HT_MACMODE_20)) + chanmode = CHANNEL_A_HT20; + if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) && + (tx_chan_width == ATH9K_HT_MACMODE_2040)) + chanmode = CHANNEL_A_HT40PLUS; + if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) && + (tx_chan_width == ATH9K_HT_MACMODE_2040)) + chanmode = CHANNEL_A_HT40MINUS; + break; + default: + break; } - return 0; + + return chanmode; } + static int ath_setkey_tkip(struct ath_softc *sc, struct ieee80211_key_conf *key, - struct hal_keyval *hk, + struct ath9k_keyval *hk, const u8 *addr) { u8 *key_rxmic = NULL; @@ -108,7 +124,7 @@ static int ath_setkey_tkip(struct ath_softc *sc, memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); if (!ath_keyset(sc, key->keyidx, hk, NULL)) { /* Txmic entry failed. No need to proceed further */ - DPRINTF(sc, ATH_DEBUG_KEYCACHE, + DPRINTF(sc, ATH_DBG_KEYCACHE, "%s Setting TX MIC Key Failed\n", __func__); return 0; } @@ -123,7 +139,7 @@ static int ath_key_config(struct ath_softc *sc, struct ieee80211_key_conf *key) { struct ieee80211_vif *vif; - struct hal_keyval hk; + struct ath9k_keyval hk; const u8 *mac = NULL; int ret = 0; enum ieee80211_if_types opmode; @@ -132,13 +148,13 @@ static int ath_key_config(struct ath_softc *sc, switch (key->alg) { case ALG_WEP: - hk.kv_type = HAL_CIPHER_WEP; + hk.kv_type = ATH9K_CIPHER_WEP; break; case ALG_TKIP: - hk.kv_type = HAL_CIPHER_TKIP; + hk.kv_type = ATH9K_CIPHER_TKIP; break; case ALG_CCMP: - hk.kv_type = HAL_CIPHER_AES_CCM; + hk.kv_type = ATH9K_CIPHER_AES_CCM; break; default: return -EINVAL; @@ -266,10 +282,11 @@ static void ath9k_rx_prepare(struct ath_softc *sc, rx_status->mactime = status->tsf; rx_status->band = curchan->band; rx_status->freq = curchan->center_freq; - rx_status->signal = (status->rssi * 64) / 100; rx_status->noise = ATH_DEFAULT_NOISE_FLOOR; + rx_status->signal = rx_status->noise + status->rssi; rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100)); rx_status->antenna = status->antenna; + rx_status->qual = status->rssi * 100 / 64; if (status->flags & ATH_RX_MIC_ERROR) rx_status->flag |= RX_FLAG_MMIC_ERROR; @@ -279,66 +296,7 @@ static void ath9k_rx_prepare(struct ath_softc *sc, rx_status->flag |= RX_FLAG_TSFT; } -/* - * Update all associated nodes and VAPs - * - * Called when local channel width changed. e.g. if AP mode, - * update all associated STAs when the AP's channel width changes. - */ -static void cwm_rate_updateallnodes(struct ath_softc *sc) -{ - int flags = 0, error; - struct ieee80211_vif *vif; - enum ieee80211_if_types opmode; - struct ieee80211_hw *hw = sc->hw; - - if (sc->sc_vaps[0]) { - vif = sc->sc_vaps[0]->av_if_data; - opmode = vif->type; - switch (opmode) { - case IEEE80211_IF_TYPE_STA: - /* sync with next received beacon */ - flags |= ATH_IF_BEACON_SYNC; - if (hw->conf.ht_conf.ht_supported) - flags |= ATH_IF_HT; - error = ath_vap_up(sc, 0, - /* sc->sc_vaps[i]->av_btxctl->if_id, FIX ME if_id */ - /* sc->sc_vaps[i]->bssid, FIX ME bssid */ - sc->sc_curbssid, - sc->sc_curaid, - flags); - if (error)/* FIX ME if_id */ - DPRINTF(sc, ATH_DEBUG_CWM, - "%s: Unable to up vap: " - "%d\n", __func__, 0); - else - DPRINTF(sc, ATH_DEBUG_CWM, - "%s: VAP up for id: " - "%d\n", __func__, 0); - break; - case IEEE80211_IF_TYPE_IBSS: - case IEEE80211_IF_TYPE_AP: - /* FIXME */ - break; - default: - break; - } - } -} - -/* Action: switch MAC from 40 to 20 (OR) 20 to 40 based on ch_width arg */ -static void cwm_action_mac_change_chwidth(struct ath_softc *sc, - enum hal_ht_macmode ch_width) -{ - ath_set_macmode(sc, ch_width); - - /* notify rate control of new mode (select new rate table) */ - cwm_rate_updateallnodes(sc); - - /* XXX: all virtual APs - send ch width action management frame */ -} - -static u_int8_t parse_mpdudensity(u_int8_t mpdudensity) +static u8 parse_mpdudensity(u8 mpdudensity) { /* * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": @@ -377,21 +335,26 @@ static int ath9k_start(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; struct ieee80211_channel *curchan = hw->conf.channel; - struct hal_channel hchan; - int error = 0; + int error = 0, pos; - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: Starting driver with " + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with " "initial channel: %d MHz\n", __func__, curchan->center_freq); /* setup initial channel */ - hchan.channel = curchan->center_freq; - hchan.channelFlags = ath_chan2flags(curchan, sc); + pos = ath_get_channel(sc, curchan); + if (pos == -1) { + DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); + return -EINVAL; + } + + sc->sc_ah->ah_channels[pos].chanmode = + (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; /* open ath_dev */ - error = ath_open(sc, &hchan); + error = ath_open(sc, &sc->sc_ah->ah_channels[pos]); if (error) { - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to complete ath_open\n", __func__); return error; } @@ -416,12 +379,12 @@ static int ath9k_tx(struct ieee80211_hw *hw, memmove(skb->data, skb->data + padsize, hdrlen); } - DPRINTF(sc, ATH_DEBUG_XMIT, "%s: transmitting packet, skb: %p\n", + DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting packet, skb: %p\n", __func__, skb); if (ath_tx_start(sc, skb) != 0) { - DPRINTF(sc, ATH_DEBUG_XMIT, "%s: TX failed\n", __func__); + DPRINTF(sc, ATH_DBG_XMIT, "%s: TX failed\n", __func__); dev_kfree_skb_any(skb); /* FIXME: Check for proper return value from ATH_DEV */ return 0; @@ -430,26 +393,16 @@ static int ath9k_tx(struct ieee80211_hw *hw, return 0; } -static int ath9k_beacon_update(struct ieee80211_hw *hw, - struct sk_buff *skb) - -{ - struct ath_softc *sc = hw->priv; - - DPRINTF(sc, ATH_DEBUG_BEACON, "%s: Update Beacon\n", __func__); - return ath9k_tx(hw, skb); -} - static void ath9k_stop(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; int error; - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: Driver halt\n", __func__); + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__); error = ath_suspend(sc); if (error) - DPRINTF(sc, ATH_DEBUG_CONFIG, + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Device is no longer present\n", __func__); ieee80211_stop_queues(hw); @@ -464,50 +417,74 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, /* Support only vap for now */ if (sc->sc_nvaps) - return -1; + return -ENOBUFS; switch (conf->type) { case IEEE80211_IF_TYPE_STA: - ic_opmode = HAL_M_STA; - default: + ic_opmode = ATH9K_M_STA; + break; + case IEEE80211_IF_TYPE_IBSS: + ic_opmode = ATH9K_M_IBSS; break; + default: + DPRINTF(sc, ATH_DBG_FATAL, + "%s: Only STA and IBSS are supported currently\n", + __func__); + return -EOPNOTSUPP; } - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: Attach a VAP of type: %d\n", + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a VAP of type: %d\n", __func__, ic_opmode); - error = ath_vap_attach(sc, 0, conf->vif, ic_opmode, ic_opmode, 0); + error = ath_vap_attach(sc, 0, conf->vif, ic_opmode); if (error) { - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to attach vap, error: %d\n", __func__, error); - goto bad; + return error; } return 0; -bad: - return -1; } static void ath9k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct ath_softc *sc = hw->priv; - int error, flags = 0; + struct ath_vap *avp; + int error; - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: Detach VAP\n", __func__); + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach VAP\n", __func__); - flags |= ATH_IF_HW_OFF; + avp = sc->sc_vaps[0]; + if (avp == NULL) { + DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n", + __func__); + return; + } - error = ath_vap_down(sc, 0, flags); - if (error) - DPRINTF(sc, ATH_DEBUG_FATAL, - "%s: Unable to down vap, error: %d\n", __func__, error); +#ifdef CONFIG_SLOW_ANT_DIV + ath_slow_ant_div_stop(&sc->sc_antdiv); +#endif + + /* Update ratectrl */ + ath_rate_newstate(sc, avp); + + /* Reclaim beacon resources */ + if (sc->sc_opmode == ATH9K_M_HOSTAP || sc->sc_opmode == ATH9K_M_IBSS) { + ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); + ath_beacon_return(sc, avp); + } + + /* Set interrupt mask */ + sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); + ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL); + sc->sc_beacons = 0; error = ath_vap_detach(sc, 0); if (error) - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to detach vap, error: %d\n", __func__, error); } @@ -517,19 +494,25 @@ static int ath9k_config(struct ieee80211_hw *hw, { struct ath_softc *sc = hw->priv; struct ieee80211_channel *curchan = hw->conf.channel; - struct hal_channel hchan; + int pos; - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: Set channel: %d MHz\n", + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", __func__, curchan->center_freq); - hchan.channel = curchan->center_freq; - hchan.channelFlags = ath_chan2flags(curchan, sc); + pos = ath_get_channel(sc, curchan); + if (pos == -1) { + DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); + return -EINVAL; + } + + sc->sc_ah->ah_channels[pos].chanmode = + (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; sc->sc_config.txpowlimit = 2 * conf->power_level; /* set h/w channel */ - if (ath_set_channel(sc, &hchan) < 0) - DPRINTF(sc, ATH_DEBUG_FATAL, "%s: Unable to set channel\n", + if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to set channel\n", __func__); return 0; @@ -540,42 +523,102 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, struct ieee80211_if_conf *conf) { struct ath_softc *sc = hw->priv; - int error = 0, flags = 0; - struct sk_buff *beacon; + struct ath_vap *avp; + u32 rfilt = 0; + int error, i; + DECLARE_MAC_BUF(mac); - if (!conf->bssid) - return 0; + avp = sc->sc_vaps[0]; + if (avp == NULL) { + DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n", + __func__); + return -EINVAL; + } - switch (vif->type) { - case IEEE80211_IF_TYPE_STA: - /* XXX: Handle (conf->changed & IEEE80211_IFCC_SSID) */ - flags |= ATH_IF_HW_ON; - /* sync with next received beacon */ - flags |= ATH_IF_BEACON_SYNC; - - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: Bring up VAP: %d\n", - __func__, 0); - - error = ath_vap_up(sc, 0, conf->bssid, 0, flags); - if (error) { - DPRINTF(sc, ATH_DEBUG_FATAL, - "%s: Unable to bring up VAP: %d, error: %d\n", - __func__, 0, error); - return -1; - } + if ((conf->changed & IEEE80211_IFCC_BSSID) && + !is_zero_ether_addr(conf->bssid)) { + switch (vif->type) { + case IEEE80211_IF_TYPE_STA: + case IEEE80211_IF_TYPE_IBSS: + /* Update ratectrl about the new state */ + ath_rate_newstate(sc, avp); + + /* Set rx filter */ + rfilt = ath_calcrxfilter(sc); + ath9k_hw_setrxfilter(sc->sc_ah, rfilt); + + /* Set BSSID */ + memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN); + sc->sc_curaid = 0; + ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid, + sc->sc_curaid); + + /* Set aggregation protection mode parameters */ + sc->sc_config.ath_aggr_prot = 0; + + /* + * Reset our TSF so that its value is lower than the + * beacon that we are trying to catch. + * Only then hw will update its TSF register with the + * new beacon. Reset the TSF before setting the BSSID + * to avoid allowing in any frames that would update + * our TSF only to have us clear it + * immediately thereafter. + */ + ath9k_hw_reset_tsf(sc->sc_ah); + + /* Disable BMISS interrupt when we're not associated */ + ath9k_hw_set_interrupts(sc->sc_ah, + sc->sc_imask & + ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS)); + sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); + + DPRINTF(sc, ATH_DBG_CONFIG, + "%s: RX filter 0x%x bssid %s aid 0x%x\n", + __func__, rfilt, + print_mac(mac, sc->sc_curbssid), sc->sc_curaid); + + /* need to reconfigure the beacon */ + sc->sc_beacons = 0; - break; - case IEEE80211_IF_TYPE_IBSS: - if (!(conf->changed & IEEE80211_IFCC_BEACON)) break; - beacon = ieee80211_beacon_get(hw, vif); - if (!beacon) - return -ENOMEM; - ath9k_beacon_update(hw, beacon); - default: - break; + default: + break; + } } + if ((conf->changed & IEEE80211_IFCC_BEACON) && + (vif->type == IEEE80211_IF_TYPE_IBSS)) { + /* + * Allocate and setup the beacon frame. + * + * Stop any previous beacon DMA. This may be + * necessary, for example, when an ibss merge + * causes reconfiguration; we may be called + * with beacon transmission active. + */ + ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); + + error = ath_beacon_alloc(sc, 0); + if (error != 0) + return error; + + ath_beacon_sync(sc, 0); + } + + /* Check for WLAN_CAPABILITY_PRIVACY ? */ + if ((avp->av_opmode != IEEE80211_IF_TYPE_STA)) { + for (i = 0; i < IEEE80211_WEP_NKID; i++) + if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) + ath9k_hw_keysetmac(sc->sc_ah, + (u16)i, + sc->sc_curbssid); + } + + /* Only legacy IBSS for now */ + if (vif->type == IEEE80211_IF_TYPE_IBSS) + ath_update_chainmask(sc, 0); + return 0; } @@ -627,7 +670,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, spin_lock_irqsave(&sc->node_lock, flags); if (!an) { ath_node_attach(sc, (u8 *)addr, 0); - DPRINTF(sc, ATH_DEBUG_NODE, "%s: Attach a node: %s\n", + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n", __func__, print_mac(mac, addr)); } else { @@ -637,12 +680,12 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, break; case STA_NOTIFY_REMOVE: if (!an) - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: Removal of a non-existent node\n", __func__); else { ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT); - DPRINTF(sc, ATH_DEBUG_NODE, "%s: Put a node: %s\n", + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n", __func__, print_mac(mac, addr)); } @@ -657,7 +700,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params) { struct ath_softc *sc = hw->priv; - struct hal_txq_info qi; + struct ath9k_txq_info qi; int ret = 0, qnum; if (queue >= WME_NUM_AC) @@ -669,7 +712,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, qi.tqi_burstTime = params->txop; qnum = ath_get_hal_qnum(queue, sc); - DPRINTF(sc, ATH_DEBUG_CONFIG, + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Configure tx [queue/halq] [%d/%d], " "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", __func__, @@ -682,7 +725,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, ret = ath_txq_update(sc, qnum, &qi); if (ret) - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: TXQ Update failed\n", __func__); return ret; @@ -697,7 +740,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, struct ath_softc *sc = hw->priv; int ret = 0; - DPRINTF(sc, ATH_DEBUG_KEYCACHE, " %s: Set HW Key\n", __func__); + DPRINTF(sc, ATH_DBG_KEYCACHE, " %s: Set HW Key\n", __func__); switch (cmd) { case SET_KEY: @@ -713,7 +756,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, case DISABLE_KEY: ath_key_delete(sc, key); clear_bit(key->keyidx, sc->sc_keymap); - sc->sc_keytype = HAL_CIPHER_CLR; + sc->sc_keytype = ATH9K_CIPHER_CLR; break; default: ret = -EINVAL; @@ -737,11 +780,11 @@ static void ath9k_ht_conf(struct ath_softc *sc, IEEE80211_HT_CAP_40MHZ_INTOLERANT) && (bss_conf->ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH)) - ht_info->tx_chan_width = HAL_HT_MACMODE_2040; + ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040; else - ht_info->tx_chan_width = HAL_HT_MACMODE_20; + ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; - cwm_action_mac_change_chwidth(sc, ht_info->tx_chan_width); + ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + bss_conf->ht_conf->ampdu_factor); ht_info->mpdudensity = @@ -757,30 +800,77 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, { struct ieee80211_hw *hw = sc->hw; struct ieee80211_channel *curchan = hw->conf.channel; - struct hal_channel hchan; + struct ath_vap *avp; + int pos; + DECLARE_MAC_BUF(mac); if (bss_conf->assoc) { - /* FIXME : Do we need any other info - * which is part of association */ - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: Bss Info ASSOC %d\n", + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n", __func__, bss_conf->aid); - sc->sc_curaid = bss_conf->aid; - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: Set channel: %d MHz\n", + avp = sc->sc_vaps[0]; + if (avp == NULL) { + DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n", + __func__); + return; + } + + /* New association, store aid */ + if (avp->av_opmode == ATH9K_M_STA) { + sc->sc_curaid = bss_conf->aid; + ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid, + sc->sc_curaid); + } + + /* Configure the beacon */ + ath_beacon_config(sc, 0); + sc->sc_beacons = 1; + + /* Reset rssi stats */ + sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; + sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; + sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; + sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; + + /* Update chainmask */ + ath_update_chainmask(sc, bss_conf->assoc_ht); + + DPRINTF(sc, ATH_DBG_CONFIG, + "%s: bssid %s aid 0x%x\n", + __func__, + print_mac(mac, sc->sc_curbssid), sc->sc_curaid); + + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", __func__, curchan->center_freq); - hchan.channel = curchan->center_freq; - hchan.channelFlags = ath_chan2flags(curchan, sc); + pos = ath_get_channel(sc, curchan); + if (pos == -1) { + DPRINTF(sc, ATH_DBG_FATAL, + "%s: Invalid channel\n", __func__); + return; + } + + if (hw->conf.ht_conf.ht_supported) + sc->sc_ah->ah_channels[pos].chanmode = + ath_get_extchanmode(sc, curchan); + else + sc->sc_ah->ah_channels[pos].chanmode = + (curchan->band == IEEE80211_BAND_2GHZ) ? + CHANNEL_G : CHANNEL_A; /* set h/w channel */ - if (ath_set_channel(sc, &hchan) < 0) - DPRINTF(sc, ATH_DEBUG_FATAL, + if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to set channel\n", __func__); + + ath_rate_newstate(sc, avp); + /* Update ratectrl about the new state */ + ath_rc_node_update(hw, avp->rc_node); } else { - DPRINTF(sc, ATH_DEBUG_CONFIG, + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info DISSOC\n", __func__); sc->sc_curaid = 0; } @@ -794,7 +884,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, struct ath_softc *sc = hw->priv; if (changed & BSS_CHANGED_ERP_PREAMBLE) { - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: BSS Changed PREAMBLE %d\n", + DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed PREAMBLE %d\n", __func__, bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) @@ -804,7 +894,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ERP_CTS_PROT) { - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: BSS Changed CTS PROT %d\n", + DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed CTS PROT %d\n", __func__, bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && @@ -815,14 +905,14 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_HT) { - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: BSS Changed HT %d\n", + DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n", __func__, bss_conf->assoc_ht); ath9k_ht_conf(sc, bss_conf); } if (changed & BSS_CHANGED_ASSOC) { - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: BSS Changed ASSOC %d\n", + DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n", __func__, bss_conf->assoc); ath9k_bss_assoc_info(sc, bss_conf); @@ -831,7 +921,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, static u64 ath9k_get_tsf(struct ieee80211_hw *hw) { - u_int64_t tsf; + u64 tsf; struct ath_softc *sc = hw->priv; struct ath_hal *ah = sc->sc_ah; @@ -861,21 +951,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_START: ret = ath_rx_aggr_start(sc, addr, tid, ssn); if (ret < 0) - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to start RX aggregation\n", __func__); break; case IEEE80211_AMPDU_RX_STOP: ret = ath_rx_aggr_stop(sc, addr, tid); if (ret < 0) - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to stop RX aggregation\n", __func__); break; case IEEE80211_AMPDU_TX_START: ret = ath_tx_aggr_start(sc, addr, tid, ssn); if (ret < 0) - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to start TX aggregation\n", __func__); else @@ -884,14 +974,14 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_STOP: ret = ath_tx_aggr_stop(sc, addr, tid); if (ret < 0) - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to stop TX aggregation\n", __func__); ieee80211_stop_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid); break; default: - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unknown AMPDU action\n", __func__); } @@ -925,143 +1015,6 @@ static struct ieee80211_ops ath9k_ops = { .ampdu_action = ath9k_ampdu_action }; -u_int32_t ath_chan2flags(struct ieee80211_channel *chan, - struct ath_softc *sc) -{ - struct ieee80211_hw *hw = sc->hw; - struct ath_ht_info *ht_info = &sc->sc_ht_info; - - if (sc->sc_scanning) { - if (chan->band == IEEE80211_BAND_5GHZ) { - if (ath_check_chanflags(chan, CHANNEL_A_HT20, sc)) - return CHANNEL_A_HT20; - else - return CHANNEL_A; - } else { - if (ath_check_chanflags(chan, CHANNEL_G_HT20, sc)) - return CHANNEL_G_HT20; - else if (ath_check_chanflags(chan, CHANNEL_G, sc)) - return CHANNEL_G; - else - return CHANNEL_B; - } - } else { - if (chan->band == IEEE80211_BAND_2GHZ) { - if (!hw->conf.ht_conf.ht_supported) { - if (ath_check_chanflags(chan, CHANNEL_G, sc)) - return CHANNEL_G; - else - return CHANNEL_B; - } - if ((ht_info->ext_chan_offset == - IEEE80211_HT_IE_CHA_SEC_NONE) && - (ht_info->tx_chan_width == HAL_HT_MACMODE_20)) - return CHANNEL_G_HT20; - if ((ht_info->ext_chan_offset == - IEEE80211_HT_IE_CHA_SEC_ABOVE) && - (ht_info->tx_chan_width == HAL_HT_MACMODE_2040)) - return CHANNEL_G_HT40PLUS; - if ((ht_info->ext_chan_offset == - IEEE80211_HT_IE_CHA_SEC_BELOW) && - (ht_info->tx_chan_width == HAL_HT_MACMODE_2040)) - return CHANNEL_G_HT40MINUS; - return CHANNEL_B; - } else { - if (!hw->conf.ht_conf.ht_supported) - return CHANNEL_A; - if ((ht_info->ext_chan_offset == - IEEE80211_HT_IE_CHA_SEC_NONE) && - (ht_info->tx_chan_width == HAL_HT_MACMODE_20)) - return CHANNEL_A_HT20; - if ((ht_info->ext_chan_offset == - IEEE80211_HT_IE_CHA_SEC_ABOVE) && - (ht_info->tx_chan_width == HAL_HT_MACMODE_2040)) - return CHANNEL_A_HT40PLUS; - if ((ht_info->ext_chan_offset == - IEEE80211_HT_IE_CHA_SEC_BELOW) && - (ht_info->tx_chan_width == HAL_HT_MACMODE_2040)) - return CHANNEL_A_HT40MINUS; - return CHANNEL_A; - } - } -} - -void ath_setup_channel_list(struct ath_softc *sc, - enum ieee80211_clist_cmd cmd, - const struct hal_channel *chans, - int nchan, - const u_int8_t *regclassids, - u_int nregclass, - int countrycode) -{ - const struct hal_channel *c; - int i, a = 0, b = 0, flags; - - if (countrycode == CTRY_DEFAULT) { - for (i = 0; i < nchan; i++) { - c = &chans[i]; - flags = 0; - /* XXX: Ah! make more readable, and - * idententation friendly */ - if (IS_CHAN_2GHZ(c) && - !test_update_chan(IEEE80211_BAND_2GHZ, c, sc)) { - sc->channels[IEEE80211_BAND_2GHZ][a].band = - IEEE80211_BAND_2GHZ; - sc->channels[IEEE80211_BAND_2GHZ][a]. - center_freq = - c->channel; - sc->channels[IEEE80211_BAND_2GHZ][a].max_power = - c->maxTxPower; - sc->channels[IEEE80211_BAND_2GHZ][a].hw_value = - c->channelFlags; - - if (c->privFlags & CHANNEL_DISALLOW_ADHOC) - flags |= IEEE80211_CHAN_NO_IBSS; - if (IS_CHAN_PASSIVE(c)) - flags |= IEEE80211_CHAN_PASSIVE_SCAN; - - sc->channels[IEEE80211_BAND_2GHZ][a].flags = - flags; - sc->sbands[IEEE80211_BAND_2GHZ].n_channels++; - a++; - DPRINTF(sc, ATH_DEBUG_CONFIG, - "%s: 2MHz channel: %d, " - "channelFlags: 0x%x\n", - __func__, - c->channel, - c->channelFlags); - } else if (IS_CHAN_5GHZ(c) && - !test_update_chan(IEEE80211_BAND_5GHZ, c, sc)) { - sc->channels[IEEE80211_BAND_5GHZ][b].band = - IEEE80211_BAND_5GHZ; - sc->channels[IEEE80211_BAND_5GHZ][b]. - center_freq = - c->channel; - sc->channels[IEEE80211_BAND_5GHZ][b].max_power = - c->maxTxPower; - sc->channels[IEEE80211_BAND_5GHZ][b].hw_value = - c->channelFlags; - - if (c->privFlags & CHANNEL_DISALLOW_ADHOC) - flags |= IEEE80211_CHAN_NO_IBSS; - if (IS_CHAN_PASSIVE(c)) - flags |= IEEE80211_CHAN_PASSIVE_SCAN; - - sc->channels[IEEE80211_BAND_5GHZ][b]. - flags = flags; - sc->sbands[IEEE80211_BAND_5GHZ].n_channels++; - b++; - DPRINTF(sc, ATH_DEBUG_CONFIG, - "%s: 5MHz channel: %d, " - "channelFlags: 0x%x\n", - __func__, - c->channel, - c->channelFlags); - } - } - } -} - void ath_get_beaconconfig(struct ath_softc *sc, int if_id, struct ath_beacon_config *conf) @@ -1076,14 +1029,6 @@ void ath_get_beaconconfig(struct ath_softc *sc, conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; } -struct sk_buff *ath_get_beacon(struct ath_softc *sc, - int if_id, - struct ath_beacon_offset *bo, - struct ath_tx_control *txctl) -{ - return NULL; -} - int ath_update_beacon(struct ath_softc *sc, int if_id, struct ath_beacon_offset *bo, @@ -1099,7 +1044,7 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, struct ieee80211_hw *hw = sc->hw; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - DPRINTF(sc, ATH_DEBUG_XMIT, + DPRINTF(sc, ATH_DBG_XMIT, "%s: TX complete: skb: %p\n", __func__, skb); if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || @@ -1127,7 +1072,7 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, int ath__rx_indicate(struct ath_softc *sc, struct sk_buff *skb, struct ath_recv_status *status, - u_int16_t keyix) + u16 keyix) { struct ieee80211_hw *hw = sc->hw; struct ath_node *an = NULL; @@ -1150,7 +1095,7 @@ int ath__rx_indicate(struct ath_softc *sc, /* Prepare rx status */ ath9k_rx_prepare(sc, skb, status, &rx_status); - if (!(keyix == HAL_RXKEYIX_INVALID) && + if (!(keyix == ATH9K_RXKEYIX_INVALID) && !(status->flags & ATH_RX_DECRYPT_ERROR)) { rx_status.flag |= RX_FLAG_DECRYPTED; } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) @@ -1195,7 +1140,7 @@ int ath_rx_subframe(struct ath_node *an, return 0; } -enum hal_ht_macmode ath_cwm_macmode(struct ath_softc *sc) +enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc) { return sc->sc_ht_info.tx_chan_width; } @@ -1203,7 +1148,7 @@ enum hal_ht_macmode ath_cwm_macmode(struct ath_softc *sc) void ath_setup_rate(struct ath_softc *sc, enum wireless_mode wMode, enum RATE_TYPE type, - const struct hal_rate_table *rt) + const struct ath9k_rate_table *rt) { int i, maxrates, a = 0, b = 0; struct ieee80211_supported_band *band_2ghz; @@ -1225,7 +1170,7 @@ void ath_setup_rate(struct ath_softc *sc, maxrates = rt->rateCount; if ((band_2ghz->n_bitrates != 0) && (band_5ghz->n_bitrates != 0)) { - DPRINTF(sc, ATH_DEBUG_CONFIG, + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Rates already setup\n", __func__); return; } @@ -1252,7 +1197,7 @@ void ath_setup_rate(struct ath_softc *sc, if (band_2ghz->n_bitrates) { for (i = 0; i < band_2ghz->n_bitrates; i++) { - DPRINTF(sc, ATH_DEBUG_CONFIG, + DPRINTF(sc, ATH_DBG_CONFIG, "%s: 2GHz Rate: %2dMbps, ratecode: %2d\n", __func__, rates_2ghz[i].bitrate / 10, @@ -1260,7 +1205,7 @@ void ath_setup_rate(struct ath_softc *sc, } } else if (band_5ghz->n_bitrates) { for (i = 0; i < band_5ghz->n_bitrates; i++) { - DPRINTF(sc, ATH_DEBUG_CONFIG, + DPRINTF(sc, ATH_DBG_CONFIG, "%s: 5Ghz Rate: %2dMbps, ratecode: %2d\n", __func__, rates_5ghz[i].bitrate / 10, @@ -1273,7 +1218,7 @@ static int ath_detach(struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: Detach ATH hw\n", __func__); + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); /* Unregister hw */ @@ -1294,13 +1239,13 @@ static int ath_detach(struct ath_softc *sc) return 0; } -static int ath_attach(u_int16_t devid, +static int ath_attach(u16 devid, struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; int error = 0; - DPRINTF(sc, ATH_DEBUG_CONFIG, "%s: Attach ATH hw\n", __func__); + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__); error = ath_init(devid, sc); if (error != 0) @@ -1323,7 +1268,7 @@ static int ath_attach(u_int16_t devid, sc->rates[IEEE80211_BAND_2GHZ]; sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; - if (sc->sc_hashtsupport) + if (sc->sc_ah->ah_caps.halHTSupport) /* Setup HT capabilities for 2.4Ghz*/ setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info); @@ -1338,7 +1283,7 @@ static int ath_attach(u_int16_t devid, sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; - if (sc->sc_hashtsupport) + if (sc->sc_ah->ah_caps.halHTSupport) /* Setup HT capabilities for 5Ghz*/ setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info); @@ -1355,7 +1300,7 @@ static int ath_attach(u_int16_t devid, hw->rate_control_algorithm = "ath9k_rate_control"; error = ath_rate_control_register(); if (error != 0) { - DPRINTF(sc, ATH_DEBUG_FATAL, + DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to register rate control " "algorithm:%d\n", __func__, error); ath_rate_control_unregister(); @@ -1385,33 +1330,13 @@ bad: return error; } -static irqreturn_t ath_isr(int irq, void *dev_id) -{ - struct ath_softc *sc = dev_id; - int sched; - - /* always acknowledge the interrupt */ - sched = ath_intr(sc); - - switch (sched) { - case ATH_ISR_NOSCHED: - return IRQ_HANDLED; - case ATH_ISR_NOTMINE: - return IRQ_NONE; - default: - tasklet_schedule(&sc->intr_tq); - return IRQ_HANDLED; - - } -} - static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { void __iomem *mem; struct ath_softc *sc; struct ieee80211_hw *hw; const char *athname; - u_int8_t csz; + u8 csz; u32 val; int ret = 0; @@ -1438,7 +1363,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) * DMA to work so force a reasonable value here if it * comes up zero. */ - csz = L1_CACHE_BYTES / sizeof(u_int32_t); + csz = L1_CACHE_BYTES / sizeof(u32); pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); } /* @@ -1478,6 +1403,9 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto bad2; } + hw->flags = IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_NOISE_DBM; + SET_IEEE80211_DEV(hw, &pdev->dev); pci_set_drvdata(pdev, hw);