From: David S. Miller Date: Wed, 1 Oct 2008 13:12:56 +0000 (-0700) Subject: Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 X-Git-Tag: v2.6.28-rc1~717^2~161 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=b262e60309e1b0eb25d300c7e739427d5316abb1;p=linux-2.6-omap-h63xx.git Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 Conflicts: drivers/net/wireless/ath9k/core.c drivers/net/wireless/ath9k/main.c net/core/dev.c --- b262e60309e1b0eb25d300c7e739427d5316abb1 diff --cc drivers/net/wireless/ath9k/core.c index 690f7c56af3,87e37bc3914..6c433a4d003 --- a/drivers/net/wireless/ath9k/core.c +++ b/drivers/net/wireless/ath9k/core.c @@@ -683,9 -806,9 +689,10 @@@ int ath_open(struct ath_softc *sc, stru * Note we only do this (at the moment) for station mode. */ if (ath9k_hw_phycounters(ah) && - ((sc->sc_opmode == ATH9K_M_STA) || (sc->sc_opmode == ATH9K_M_IBSS))) + ((sc->sc_ah->ah_opmode == ATH9K_M_STA) || + (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))) sc->sc_imask |= ATH9K_INT_MIB; + #endif /* * Some hardware processes the TIM IE and fires an * interrupt when the TIM bit is set. For hardware @@@ -1184,8 -1341,10 +1191,10 @@@ void ath_deinit(struct ath_softc *sc DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__); + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); ath_stop(sc); - if (!sc->sc_invalid) + if (!(sc->sc_flags & SC_OP_INVALID)) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); ath_rate_detach(sc->sc_rc); /* cleanup tx queues */ diff --cc drivers/net/wireless/ath9k/main.c index 1ba18006f47,acebdf1d20a..2caba440316 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@@ -1368,292 -1149,145 +1366,291 @@@ static int ath9k_config_interface(struc return 0; } -int ath_rx_subframe(struct ath_node *an, - struct sk_buff *skb, - struct ath_recv_status *status) +#define SUPPORTED_FILTERS \ + (FIF_PROMISC_IN_BSS | \ + FIF_ALLMULTI | \ + FIF_CONTROL | \ + FIF_OTHER_BSS | \ + FIF_BCN_PRBRESP_PROMISC | \ + FIF_FCSFAIL) + +/* FIXME: sc->sc_full_reset ? */ +static void ath9k_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_mc_list *mclist) { - struct ath_softc *sc = an->an_sc; - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_rx_status rx_status; + struct ath_softc *sc = hw->priv; + u32 rfilt; - /* Prepare rx status */ - ath9k_rx_prepare(sc, skb, status, &rx_status); - if (!(status->flags & ATH_RX_DECRYPT_ERROR)) - rx_status.flag |= RX_FLAG_DECRYPTED; + changed_flags &= SUPPORTED_FILTERS; + *total_flags &= SUPPORTED_FILTERS; - __ieee80211_rx(hw, skb, &rx_status); + sc->rx_filter = *total_flags; + rfilt = ath_calcrxfilter(sc); + ath9k_hw_setrxfilter(sc->sc_ah, rfilt); - return 0; -} + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { + if (*total_flags & FIF_BCN_PRBRESP_PROMISC) + ath9k_hw_write_associd(sc->sc_ah, ath_bcast_mac, 0); + } -enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc) -{ - return sc->sc_ht_info.tx_chan_width; + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set HW RX filter: 0x%x\n", + __func__, sc->rx_filter); } -static int ath_detach(struct ath_softc *sc) +static void ath9k_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) { - struct ieee80211_hw *hw = sc->hw; - - DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); + struct ath_softc *sc = hw->priv; + struct ath_node *an; + unsigned long flags; + DECLARE_MAC_BUF(mac); - /* Unregister hw */ + spin_lock_irqsave(&sc->node_lock, flags); + an = ath_node_find(sc, sta->addr); + spin_unlock_irqrestore(&sc->node_lock, flags); - ieee80211_unregister_hw(hw); + switch (cmd) { + case STA_NOTIFY_ADD: + spin_lock_irqsave(&sc->node_lock, flags); + if (!an) { + ath_node_attach(sc, sta->addr, 0); + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n", + __func__, print_mac(mac, sta->addr)); + } else { + ath_node_get(sc, sta->addr); + } + spin_unlock_irqrestore(&sc->node_lock, flags); + break; + case STA_NOTIFY_REMOVE: + if (!an) + 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_DBG_CONFIG, "%s: Put a node: %s\n", + __func__, + print_mac(mac, sta->addr)); + } + break; + default: + break; + } +} - /* unregister Rate control */ - ath_rate_control_unregister(); +static int ath9k_conf_tx(struct ieee80211_hw *hw, + u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct ath_softc *sc = hw->priv; + struct ath9k_tx_queue_info qi; + int ret = 0, qnum; - /* tx/rx cleanup */ + if (queue >= WME_NUM_AC) + return 0; - ath_rx_cleanup(sc); - ath_tx_cleanup(sc); + qi.tqi_aifs = params->aifs; + qi.tqi_cwmin = params->cw_min; + qi.tqi_cwmax = params->cw_max; + qi.tqi_burstTime = params->txop; + qnum = ath_get_hal_qnum(queue, sc); - /* Deinit */ + DPRINTF(sc, ATH_DBG_CONFIG, + "%s: Configure tx [queue/halq] [%d/%d], " + "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", + __func__, + queue, + qnum, + params->aifs, + params->cw_min, + params->cw_max, + params->txop); - ath_deinit(sc); + ret = ath_txq_update(sc, qnum, &qi); + if (ret) + DPRINTF(sc, ATH_DBG_FATAL, + "%s: TXQ Update failed\n", __func__); - return 0; + return ret; } -static int ath_attach(u16 devid, - struct ath_softc *sc) +static int ath9k_set_key(struct ieee80211_hw *hw, + enum set_key_cmd cmd, + const u8 *local_addr, + const u8 *addr, + struct ieee80211_key_conf *key) { - struct ieee80211_hw *hw = sc->hw; - int error = 0; + struct ath_softc *sc = hw->priv; + int ret = 0; - DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__); + DPRINTF(sc, ATH_DBG_KEYCACHE, " %s: Set HW Key\n", __func__); - error = ath_init(devid, sc); - if (error != 0) - return error; + switch (cmd) { + case SET_KEY: + ret = ath_key_config(sc, addr, key); + if (!ret) { + set_bit(key->keyidx, sc->sc_keymap); + key->hw_key_idx = key->keyidx; + /* push IV and Michael MIC generation to stack */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + if (key->alg == ALG_TKIP) + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + } + break; + case DISABLE_KEY: + ath_key_delete(sc, key); + clear_bit(key->keyidx, sc->sc_keymap); - sc->sc_keytype = ATH9K_CIPHER_CLR; + break; + default: + ret = -EINVAL; + } - /* Init nodes */ + return ret; +} - INIT_LIST_HEAD(&sc->node_list); - spin_lock_init(&sc->node_lock); +static void ath9k_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changed) +{ + struct ath_softc *sc = hw->priv; - /* get mac address from hardware and set in mac80211 */ + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed PREAMBLE %d\n", + __func__, + bss_conf->use_short_preamble); + if (bss_conf->use_short_preamble) + sc->sc_flags |= SC_OP_PREAMBLE_SHORT; + else + sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT; + } - SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr); + if (changed & BSS_CHANGED_ERP_CTS_PROT) { + DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed CTS PROT %d\n", + __func__, + bss_conf->use_cts_prot); + if (bss_conf->use_cts_prot && + hw->conf.channel->band != IEEE80211_BAND_5GHZ) + sc->sc_flags |= SC_OP_PROTECT_ENABLE; + else + sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; + } - /* setup channels and rates */ + if (changed & BSS_CHANGED_HT) { + DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n", + __func__, + bss_conf->assoc_ht); + ath9k_ht_conf(sc, bss_conf); + } - sc->sbands[IEEE80211_BAND_2GHZ].channels = - sc->channels[IEEE80211_BAND_2GHZ]; - sc->sbands[IEEE80211_BAND_2GHZ].bitrates = - sc->rates[IEEE80211_BAND_2GHZ]; - sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; + if (changed & BSS_CHANGED_ASSOC) { + DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n", + __func__, + bss_conf->assoc); + ath9k_bss_assoc_info(sc, bss_conf); + } +} - if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) - /* Setup HT capabilities for 2.4Ghz*/ - setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info); +static u64 ath9k_get_tsf(struct ieee80211_hw *hw) +{ + u64 tsf; + struct ath_softc *sc = hw->priv; + struct ath_hal *ah = sc->sc_ah; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &sc->sbands[IEEE80211_BAND_2GHZ]; + tsf = ath9k_hw_gettsf64(ah); - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_5GHZ].channels = - sc->channels[IEEE80211_BAND_5GHZ]; - sc->sbands[IEEE80211_BAND_5GHZ].bitrates = - sc->rates[IEEE80211_BAND_5GHZ]; - sc->sbands[IEEE80211_BAND_5GHZ].band = - IEEE80211_BAND_5GHZ; + return tsf; +} - if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) - /* Setup HT capabilities for 5Ghz*/ - setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info); +static void ath9k_reset_tsf(struct ieee80211_hw *hw) +{ + struct ath_softc *sc = hw->priv; + struct ath_hal *ah = sc->sc_ah; - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &sc->sbands[IEEE80211_BAND_5GHZ]; - } + ath9k_hw_reset_tsf(ah); +} - /* FIXME: Have to figure out proper hw init values later */ +static int ath9k_ampdu_action(struct ieee80211_hw *hw, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, + u16 tid, u16 *ssn) +{ + struct ath_softc *sc = hw->priv; + int ret = 0; - hw->queues = 4; - hw->ampdu_queues = 1; + switch (action) { + case IEEE80211_AMPDU_RX_START: + ret = ath_rx_aggr_start(sc, sta->addr, tid, ssn); + if (ret < 0) + 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, sta->addr, tid); + if (ret < 0) + 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, sta->addr, tid, ssn); + if (ret < 0) + DPRINTF(sc, ATH_DBG_FATAL, + "%s: Unable to start TX aggregation\n", + __func__); + else + ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_STOP: + ret = ath_tx_aggr_stop(sc, sta->addr, tid); + if (ret < 0) + DPRINTF(sc, ATH_DBG_FATAL, + "%s: Unable to stop TX aggregation\n", + __func__); - /* Register rate control */ - hw->rate_control_algorithm = "ath9k_rate_control"; - error = ath_rate_control_register(); - if (error != 0) { + ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); + break; + default: DPRINTF(sc, ATH_DBG_FATAL, - "%s: Unable to register rate control " - "algorithm:%d\n", __func__, error); - ath_rate_control_unregister(); - goto bad; - } - - error = ieee80211_register_hw(hw); - if (error != 0) { - ath_rate_control_unregister(); - goto bad; + "%s: Unknown AMPDU action\n", __func__); } - /* initialize tx/rx engine */ - - error = ath_tx_init(sc, ATH_TXBUF); - if (error != 0) - goto bad1; - - error = ath_rx_init(sc, ATH_RXBUF); - if (error != 0) - goto bad1; - - return 0; -bad1: - ath_detach(sc); -bad: - return error; + return ret; } +static struct ieee80211_ops ath9k_ops = { + .tx = ath9k_tx, + .start = ath9k_start, + .stop = ath9k_stop, + .add_interface = ath9k_add_interface, + .remove_interface = ath9k_remove_interface, + .config = ath9k_config, + .config_interface = ath9k_config_interface, + .configure_filter = ath9k_configure_filter, + .get_stats = NULL, + .sta_notify = ath9k_sta_notify, + .conf_tx = ath9k_conf_tx, + .get_tx_stats = NULL, + .bss_info_changed = ath9k_bss_info_changed, + .set_tim = NULL, + .set_key = ath9k_set_key, + .hw_scan = NULL, + .get_tkip_seq = NULL, + .set_rts_threshold = NULL, + .set_frag_threshold = NULL, + .set_retry_limit = NULL, + .get_tsf = ath9k_get_tsf, + .reset_tsf = ath9k_reset_tsf, + .tx_last_beacon = NULL, + .ampdu_action = ath9k_ampdu_action +}; + static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { void __iomem *mem; @@@ -1784,10 -1411,17 +1781,17 @@@ static void ath_pci_remove(struct pci_d { struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_softc *sc = hw->priv; + enum ath9k_int status; - if (pdev->irq) + if (pdev->irq) { + ath9k_hw_set_interrupts(sc->sc_ah, 0); + /* clear the ISR */ + ath9k_hw_getisr(sc->sc_ah, &status); - sc->sc_invalid = 1; ++ sc->sc_flags |= SC_OP_INVALID; free_irq(pdev->irq, sc); + } ath_detach(sc); + pci_iounmap(pdev, sc->mem); pci_release_region(pdev, 0); pci_disable_device(pdev); diff --cc net/core/dev.c index 2cc258b7acc,e8eb2b47834..7091040e32a --- a/net/core/dev.c +++ b/net/core/dev.c @@@ -1706,8 -1676,9 +1707,9 @@@ static u16 simple_tx_hash(struct net_de } switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): - ip_proto = ip_hdr(skb)->protocol; + if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))) + ip_proto = ip_hdr(skb)->protocol; addr1 = ip_hdr(skb)->saddr; addr2 = ip_hdr(skb)->daddr; ihl = ip_hdr(skb)->ihl;