Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorDavid S. Miller <davem@davemloft.net>
Fri, 10 Dec 2010 20:51:02 +0000 (12:51 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 10 Dec 2010 20:51:02 +0000 (12:51 -0800)
16 files changed:
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/orinoco/main.c
drivers/net/wireless/orinoco/orinoco_cs.c
drivers/net/wireless/orinoco/spectrum_cs.c
drivers/net/wireless/orinoco/wext.c
net/mac80211/tx.c

index 8251946842e6186bddcd1cac303dbaea74664410..42ed923cdb1aad9479be7ed5f68a2b40c665ffcb 100644 (file)
@@ -1917,7 +1917,8 @@ ath5k_beacon_send(struct ath5k_softc *sc)
                sc->bmisscount = 0;
        }
 
-       if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+       if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) ||
+                       sc->opmode == NL80211_IFTYPE_MESH_POINT) {
                u64 tsf = ath5k_hw_get_tsf64(ah);
                u32 tsftu = TSF_TO_TU(tsf);
                int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval;
@@ -1949,8 +1950,9 @@ ath5k_beacon_send(struct ath5k_softc *sc)
                /* NB: hw still stops DMA, so proceed */
        }
 
-       /* refresh the beacon for AP mode */
-       if (sc->opmode == NL80211_IFTYPE_AP)
+       /* refresh the beacon for AP or MESH mode */
+       if (sc->opmode == NL80211_IFTYPE_AP ||
+                       sc->opmode == NL80211_IFTYPE_MESH_POINT)
                ath5k_beacon_update(sc->hw, vif);
 
        ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
@@ -2851,7 +2853,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
 
        /* Assign the vap/adhoc to a beacon xmit slot. */
        if ((avf->opmode == NL80211_IFTYPE_AP) ||
-           (avf->opmode == NL80211_IFTYPE_ADHOC)) {
+           (avf->opmode == NL80211_IFTYPE_ADHOC) ||
+           (avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
                int slot;
 
                WARN_ON(list_empty(&sc->bcbuf));
@@ -2870,7 +2873,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
                sc->bslot[avf->bslot] = vif;
                if (avf->opmode == NL80211_IFTYPE_AP)
                        sc->num_ap_vifs++;
-               else
+               else if (avf->opmode == NL80211_IFTYPE_ADHOC)
                        sc->num_adhoc_vifs++;
        }
 
index 0d0bec3628ececb4fa29663dbffb3fdb9d20b3bb..0963071e8f908c15ebec8131c84b792d931e56d9 100644 (file)
@@ -329,7 +329,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
 struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
 int ath_tx_setup(struct ath_softc *sc, int haltype);
-void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
+bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
 void ath_draintxq(struct ath_softc *sc,
                     struct ath_txq *txq, bool retry_tx);
 void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
index 526d7c933f7fe56edf4fac310af8b5426e18e0b2..a3ccb1b9638d7b8b44f32ba651d519d042b806ec 100644 (file)
@@ -1063,15 +1063,19 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
        case 1:
                break;
        case 2:
-               scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        case 3:
-               scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        }
 
-       scaledPower = max((u16)0, scaledPower);
-
        if (IS_CHAN_2GHZ(chan)) {
                numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
                        SUB_NUM_CTL_MODES_AT_2G_40;
index dfb6560dab9205c7502cc0a546c3549635d696f2..0de3c3d3c245c2ad5f71f0a419a7ba4fab96e60c 100644 (file)
@@ -1024,6 +1024,13 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface,
        struct hif_device_usb *hif_dev =
                (struct hif_device_usb *) usb_get_intfdata(interface);
 
+       /*
+        * The device has to be set to FULLSLEEP mode in case no
+        * interface is up.
+        */
+       if (!(hif_dev->flags & HIF_USB_START))
+               ath9k_htc_suspend(hif_dev->htc_handle);
+
        ath9k_hif_usb_dealloc_urbs(hif_dev);
 
        return 0;
index 75ecf6a30d25c6ac68d346c5ac862a0255ba4be1..c3b561daa6c1035a68f4b27da92914ba4e601399 100644 (file)
@@ -455,6 +455,8 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv);
 void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv);
 void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv);
 void ath9k_ps_work(struct work_struct *work);
+bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
+                       enum ath9k_power_mode mode);
 
 void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
 void ath9k_init_leds(struct ath9k_htc_priv *priv);
@@ -464,6 +466,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
                           u16 devid, char *product);
 void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug);
 #ifdef CONFIG_PM
+void ath9k_htc_suspend(struct htc_target *htc_handle);
 int ath9k_htc_resume(struct htc_target *htc_handle);
 #endif
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
index 7c8a38d04561c26754147bea9e447724a9e8eb42..8776f49ffd41bf2a40f080798fe6c5173b80c9b4 100644 (file)
@@ -891,6 +891,12 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
 }
 
 #ifdef CONFIG_PM
+
+void ath9k_htc_suspend(struct htc_target *htc_handle)
+{
+       ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
+}
+
 int ath9k_htc_resume(struct htc_target *htc_handle)
 {
        int ret;
index 9a3be8da755d2f7181ada323e5ec9054b58a0a9e..51977caca47fd6d456e521cff4511e1079f2e09a 100644 (file)
@@ -63,8 +63,8 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
        return mode;
 }
 
-static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
-                              enum ath9k_power_mode mode)
+bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
+                       enum ath9k_power_mode mode)
 {
        bool ret;
 
index 8c13479b17cd9d418f7d7f496b01dbf7445ba202..c996963ab33927c027f3fb019200261c0ac07d18 100644 (file)
@@ -703,8 +703,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
                        rs->rs_phyerr = phyerr;
                } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
                        rs->rs_status |= ATH9K_RXERR_DECRYPT;
-               else if ((ads.ds_rxstatus8 & AR_MichaelErr) &&
-                        rs->rs_keyix != ATH9K_RXKEYIX_INVALID)
+               else if (ads.ds_rxstatus8 & AR_MichaelErr)
                        rs->rs_status |= ATH9K_RXERR_MIC;
                else if (ads.ds_rxstatus8 & AR_KeyMiss)
                        rs->rs_status |= ATH9K_RXERR_DECRYPT;
index dace215b693eb553bbb713a3ce1cdada28148683..c0c3464d3a861162e1142a0e2931a73aedae1fab 100644 (file)
@@ -244,11 +244,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
         * the relevant bits of the h/w.
         */
        ath9k_hw_set_interrupts(ah, 0);
-       ath_drain_all_txq(sc, false);
+       stopped = ath_drain_all_txq(sc, false);
 
        spin_lock_bh(&sc->rx.pcu_lock);
 
-       stopped = ath_stoprecv(sc);
+       if (!ath_stoprecv(sc))
+               stopped = false;
 
        /* XXX: do not flush receive queue here. We don't want
         * to flush data frames already in queue because of
@@ -1519,8 +1520,6 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        struct ath_softc *sc = aphy->sc;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_vif *avp = (void *)vif->drv_priv;
-       bool bs_valid = false;
-       int i;
 
        ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
@@ -1534,26 +1533,21 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
            (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
            (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
+               /* Disable SWBA interrupt */
+               sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
                ath9k_ps_wakeup(sc);
+               ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
                ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
                ath9k_ps_restore(sc);
+               tasklet_kill(&sc->bcon_tasklet);
        }
 
        ath_beacon_return(sc, avp);
        sc->sc_flags &= ~SC_OP_BEACONS;
 
-       for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
-               if (sc->beacon.bslot[i] == vif) {
-                       printk(KERN_DEBUG "%s: vif had allocated beacon "
-                              "slot\n", __func__);
-                       sc->beacon.bslot[i] = NULL;
-                       sc->beacon.bslot_aphy[i] = NULL;
-               } else if (sc->beacon.bslot[i])
-                       bs_valid = true;
-       }
-       if (!bs_valid && (sc->sc_ah->imask & ATH9K_INT_SWBA)) {
-               /* Disable SWBA interrupt */
-               sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
+       if (sc->nbcnvifs) {
+               /* Re-enable SWBA interrupt */
+               sc->sc_ah->imask |= ATH9K_INT_SWBA;
                ath9k_ps_wakeup(sc);
                ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
                ath9k_ps_restore(sc);
index 1a62e351ec77c217598a46fae7bdbcc84c1c6050..fdc2ec52b42fcd5647df2c967598e94bcfc13c9a 100644 (file)
@@ -838,6 +838,10 @@ static bool ath9k_rx_accept(struct ath_common *common,
                            struct ath_rx_status *rx_stats,
                            bool *decrypt_error)
 {
+#define is_mc_or_valid_tkip_keyix ((is_mc ||                   \
+               (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
+               test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
+
        struct ath_hw *ah = common->ah;
        __le16 fc;
        u8 rx_status_len = ah->caps.rx_status_len;
@@ -879,15 +883,18 @@ static bool ath9k_rx_accept(struct ath_common *common,
                if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
                        *decrypt_error = true;
                } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
+                       bool is_mc;
                        /*
                         * The MIC error bit is only valid if the frame
                         * is not a control frame or fragment, and it was
                         * decrypted using a valid TKIP key.
                         */
+                       is_mc = !!is_multicast_ether_addr(hdr->addr1);
+
                        if (!ieee80211_is_ctl(fc) &&
                            !ieee80211_has_morefrags(fc) &&
                            !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-                           test_bit(rx_stats->rs_keyix, common->tkip_keymap))
+                           is_mc_or_valid_tkip_keyix)
                                rxs->flag |= RX_FLAG_MMIC_ERROR;
                        else
                                rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
index f2ade2402ce27709e1da385941b9adbaece96b1e..aff04789f794ee805bf50f1f13d28783f79851d3 100644 (file)
@@ -1120,7 +1120,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
        }
 }
 
-void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
+bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
 {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -1128,7 +1128,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
        int i, npend = 0;
 
        if (sc->sc_flags & SC_OP_INVALID)
-               return;
+               return true;
 
        /* Stop beacon queue */
        ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
@@ -1142,25 +1142,15 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
                }
        }
 
-       if (npend) {
-               int r;
-
-               ath_print(common, ATH_DBG_FATAL,
-                         "Failed to stop TX DMA. Resetting hardware!\n");
-
-               spin_lock_bh(&sc->sc_resetlock);
-               r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
-               if (r)
-                       ath_print(common, ATH_DBG_FATAL,
-                                 "Unable to reset hardware; reset status %d\n",
-                                 r);
-               spin_unlock_bh(&sc->sc_resetlock);
-       }
+       if (npend)
+               ath_print(common, ATH_DBG_FATAL, "Failed to stop TX DMA!\n");
 
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
                if (ATH_TXQ_SETUP(sc, i))
                        ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
        }
+
+       return !npend;
 }
 
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
index fa0cf744958fc2f21d1d61f842bd9e2214ba0b7f..f3d396e7544b9d1d0f7848bc1cabb74bce75b8de 100644 (file)
@@ -1811,6 +1811,12 @@ static int __orinoco_commit(struct orinoco_private *priv)
        struct net_device *dev = priv->ndev;
        int err = 0;
 
+       /* If we've called commit, we are reconfiguring or bringing the
+        * interface up. Maintaining countermeasures across this would
+        * be confusing, so note that we've disabled them. The port will
+        * be enabled later in orinoco_commit or __orinoco_up. */
+       priv->tkip_cm_active = 0;
+
        err = orinoco_hw_program_rids(priv);
 
        /* FIXME: what about netif_tx_lock */
index 71b3d68b9403a8c4c142b776179c1edef9328ebd..32954c4b243a9dc70bbb0fd350c6c79ff67875d3 100644 (file)
@@ -151,20 +151,20 @@ orinoco_cs_config(struct pcmcia_device *link)
                goto failed;
        }
 
-       ret = pcmcia_request_irq(link, orinoco_interrupt);
-       if (ret)
-               goto failed;
-
-       /* We initialize the hermes structure before completing PCMCIA
-        * configuration just in case the interrupt handler gets
-        * called. */
        mem = ioport_map(link->resource[0]->start,
                        resource_size(link->resource[0]));
        if (!mem)
                goto failed;
 
+       /* We initialize the hermes structure before completing PCMCIA
+        * configuration just in case the interrupt handler gets
+        * called. */
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
 
+       ret = pcmcia_request_irq(link, orinoco_interrupt);
+       if (ret)
+               goto failed;
+
        ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
index fb859a5ad2eb8a5c2e02f349cf4002caac32fc49..db34c282e59b39340a9bf7c6c51f529bf020a1c0 100644 (file)
@@ -214,21 +214,21 @@ spectrum_cs_config(struct pcmcia_device *link)
                goto failed;
        }
 
-       ret = pcmcia_request_irq(link, orinoco_interrupt);
-       if (ret)
-               goto failed;
-
-       /* We initialize the hermes structure before completing PCMCIA
-        * configuration just in case the interrupt handler gets
-        * called. */
        mem = ioport_map(link->resource[0]->start,
                        resource_size(link->resource[0]));
        if (!mem)
                goto failed;
 
+       /* We initialize the hermes structure before completing PCMCIA
+        * configuration just in case the interrupt handler gets
+        * called. */
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
        hw->eeprom_pda = true;
 
+       ret = pcmcia_request_irq(link, orinoco_interrupt);
+       if (ret)
+               goto failed;
+
        ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
index 93505f93bf97711019e86bbe27f39f4f727bce01..e5afabee60d1834b898193479cf710c3bb3eed22 100644 (file)
@@ -911,10 +911,10 @@ static int orinoco_ioctl_set_auth(struct net_device *dev,
                 */
                if (param->value) {
                        priv->tkip_cm_active = 1;
-                       ret = hermes_enable_port(hw, 0);
+                       ret = hermes_disable_port(hw, 0);
                } else {
                        priv->tkip_cm_active = 0;
-                       ret = hermes_disable_port(hw, 0);
+                       ret = hermes_enable_port(hw, 0);
                }
                break;
 
index df6aac523532c5d5bb8940d4d98fa91b48e0e4b2..7a637b80a62ef7a8d00d49285d9d6995b4083d9e 100644 (file)
@@ -1737,15 +1737,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        int nh_pos, h_pos;
        struct sta_info *sta = NULL;
        u32 sta_flags = 0;
+       struct sk_buff *tmp_skb;
 
        if (unlikely(skb->len < ETH_HLEN)) {
                ret = NETDEV_TX_OK;
                goto fail;
        }
 
-       nh_pos = skb_network_header(skb) - skb->data;
-       h_pos = skb_transport_header(skb) - skb->data;
-
        /* convert Ethernet header to proper 802.11 header (based on
         * operation mode) */
        ethertype = (skb->data[12] << 8) | skb->data[13];
@@ -1918,6 +1916,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                goto fail;
        }
 
+       /*
+        * If the skb is shared we need to obtain our own copy.
+        */
+       if (skb_shared(skb)) {
+               tmp_skb = skb;
+               skb = skb_copy(skb, GFP_ATOMIC);
+               kfree_skb(tmp_skb);
+
+               if (!skb) {
+                       ret = NETDEV_TX_OK;
+                       goto fail;
+               }
+       }
+
        hdr.frame_control = fc;
        hdr.duration_id = 0;
        hdr.seq_ctrl = 0;
@@ -1936,6 +1948,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                encaps_len = 0;
        }
 
+       nh_pos = skb_network_header(skb) - skb->data;
+       h_pos = skb_transport_header(skb) - skb->data;
+
        skb_pull(skb, skip_header_bytes);
        nh_pos -= skip_header_bytes;
        h_pos -= skip_header_bytes;