aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-12-08 16:23:31 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-08 16:23:31 -0500
commit393934c6b5c8d00f9d1ae20670d4a770f07a418a (patch)
treedad33cd2e4fc0e3d3b28dcbc36cfb44178cb046c /drivers/net/wireless/ath/ath9k
parent69f4aab1157d2a386e7ea4de77cc253629d1b4f2 (diff)
parent0a54917c3fc295cb61f3fb52373c173fd3b69f48 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
Conflicts: drivers/net/wireless/ath/ath9k/ath9k.h drivers/net/wireless/ath/ath9k/main.c drivers/net/wireless/ath/ath9k/xmit.c
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c26
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c19
10 files changed, 52 insertions, 39 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 4210a9306955..9b5501f90010 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -311,7 +311,7 @@ void ath_rx_cleanup(struct ath_softc *sc);
311int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); 311int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
312struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); 312struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
313void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); 313void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
314void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); 314bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
315void ath_draintxq(struct ath_softc *sc, 315void ath_draintxq(struct ath_softc *sc,
316 struct ath_txq *txq, bool retry_tx); 316 struct ath_txq *txq, bool retry_tx);
317void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); 317void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index c2b4bba7410c..5bfa031545f4 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -1063,15 +1063,19 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
1063 case 1: 1063 case 1:
1064 break; 1064 break;
1065 case 2: 1065 case 2:
1066 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; 1066 if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
1067 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
1068 else
1069 scaledPower = 0;
1067 break; 1070 break;
1068 case 3: 1071 case 3:
1069 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; 1072 if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
1073 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
1074 else
1075 scaledPower = 0;
1070 break; 1076 break;
1071 } 1077 }
1072 1078
1073 scaledPower = max((u16)0, scaledPower);
1074
1075 if (IS_CHAN_2GHZ(chan)) { 1079 if (IS_CHAN_2GHZ(chan)) {
1076 numCtlModes = ARRAY_SIZE(ctlModesFor11g) - 1080 numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
1077 SUB_NUM_CTL_MODES_AT_2G_40; 1081 SUB_NUM_CTL_MODES_AT_2G_40;
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 45d4b2403a52..d0918bd23b8e 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -1015,6 +1015,13 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface,
1015{ 1015{
1016 struct hif_device_usb *hif_dev = usb_get_intfdata(interface); 1016 struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
1017 1017
1018 /*
1019 * The device has to be set to FULLSLEEP mode in case no
1020 * interface is up.
1021 */
1022 if (!(hif_dev->flags & HIF_USB_START))
1023 ath9k_htc_suspend(hif_dev->htc_handle);
1024
1018 ath9k_hif_usb_dealloc_urbs(hif_dev); 1025 ath9k_hif_usb_dealloc_urbs(hif_dev);
1019 1026
1020 return 0; 1027 return 0;
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index afe39a911906..fdf9d5fe8cc0 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -455,6 +455,8 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv);
455void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv); 455void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv);
456void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv); 456void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv);
457void ath9k_ps_work(struct work_struct *work); 457void ath9k_ps_work(struct work_struct *work);
458bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
459 enum ath9k_power_mode mode);
458 460
459void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); 461void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
460void ath9k_init_leds(struct ath9k_htc_priv *priv); 462void 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,
464 u16 devid, char *product, u32 drv_info); 466 u16 devid, char *product, u32 drv_info);
465void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); 467void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug);
466#ifdef CONFIG_PM 468#ifdef CONFIG_PM
469void ath9k_htc_suspend(struct htc_target *htc_handle);
467int ath9k_htc_resume(struct htc_target *htc_handle); 470int ath9k_htc_resume(struct htc_target *htc_handle);
468#endif 471#endif
469#ifdef CONFIG_ATH9K_HTC_DEBUGFS 472#ifdef CONFIG_ATH9K_HTC_DEBUGFS
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 93f3f615218b..0f6be350fd3c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -882,6 +882,12 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
882} 882}
883 883
884#ifdef CONFIG_PM 884#ifdef CONFIG_PM
885
886void ath9k_htc_suspend(struct htc_target *htc_handle)
887{
888 ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
889}
890
885int ath9k_htc_resume(struct htc_target *htc_handle) 891int ath9k_htc_resume(struct htc_target *htc_handle)
886{ 892{
887 struct ath9k_htc_priv *priv = htc_handle->drv_priv; 893 struct ath9k_htc_priv *priv = htc_handle->drv_priv;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index fe82e5e30d82..20ea75a44e52 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -63,8 +63,8 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
63 return mode; 63 return mode;
64} 64}
65 65
66static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, 66bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
67 enum ath9k_power_mode mode) 67 enum ath9k_power_mode mode)
68{ 68{
69 bool ret; 69 bool ret;
70 70
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index f05462ace4e8..e3d2ebf00e2e 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -698,8 +698,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
698 rs->rs_phyerr = phyerr; 698 rs->rs_phyerr = phyerr;
699 } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) 699 } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
700 rs->rs_status |= ATH9K_RXERR_DECRYPT; 700 rs->rs_status |= ATH9K_RXERR_DECRYPT;
701 else if ((ads.ds_rxstatus8 & AR_MichaelErr) && 701 else if (ads.ds_rxstatus8 & AR_MichaelErr)
702 rs->rs_keyix != ATH9K_RXKEYIX_INVALID)
703 rs->rs_status |= ATH9K_RXERR_MIC; 702 rs->rs_status |= ATH9K_RXERR_MIC;
704 else if (ads.ds_rxstatus8 & AR_KeyMiss) 703 else if (ads.ds_rxstatus8 & AR_KeyMiss)
705 rs->rs_status |= ATH9K_RXERR_DECRYPT; 704 rs->rs_status |= ATH9K_RXERR_DECRYPT;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 41a312a3d401..daa3c9feca66 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -246,9 +246,10 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
246 * the relevant bits of the h/w. 246 * the relevant bits of the h/w.
247 */ 247 */
248 ath9k_hw_disable_interrupts(ah); 248 ath9k_hw_disable_interrupts(ah);
249 ath_drain_all_txq(sc, false); 249 stopped = ath_drain_all_txq(sc, false);
250 250
251 stopped = ath_stoprecv(sc); 251 if (!ath_stoprecv(sc))
252 stopped = false;
252 253
253 /* XXX: do not flush receive queue here. We don't want 254 /* XXX: do not flush receive queue here. We don't want
254 * to flush data frames already in queue because of 255 * to flush data frames already in queue because of
@@ -1434,8 +1435,6 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
1434 struct ath_softc *sc = aphy->sc; 1435 struct ath_softc *sc = aphy->sc;
1435 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 1436 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1436 struct ath_vif *avp = (void *)vif->drv_priv; 1437 struct ath_vif *avp = (void *)vif->drv_priv;
1437 bool bs_valid = false;
1438 int i;
1439 1438
1440 ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); 1439 ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
1441 1440
@@ -1449,26 +1448,21 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
1449 if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || 1448 if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
1450 (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || 1449 (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
1451 (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { 1450 (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
1451 /* Disable SWBA interrupt */
1452 sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
1452 ath9k_ps_wakeup(sc); 1453 ath9k_ps_wakeup(sc);
1454 ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
1453 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); 1455 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
1454 ath9k_ps_restore(sc); 1456 ath9k_ps_restore(sc);
1457 tasklet_kill(&sc->bcon_tasklet);
1455 } 1458 }
1456 1459
1457 ath_beacon_return(sc, avp); 1460 ath_beacon_return(sc, avp);
1458 sc->sc_flags &= ~SC_OP_BEACONS; 1461 sc->sc_flags &= ~SC_OP_BEACONS;
1459 1462
1460 for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { 1463 if (sc->nbcnvifs) {
1461 if (sc->beacon.bslot[i] == vif) { 1464 /* Re-enable SWBA interrupt */
1462 printk(KERN_DEBUG "%s: vif had allocated beacon " 1465 sc->sc_ah->imask |= ATH9K_INT_SWBA;
1463 "slot\n", __func__);
1464 sc->beacon.bslot[i] = NULL;
1465 sc->beacon.bslot_aphy[i] = NULL;
1466 } else if (sc->beacon.bslot[i])
1467 bs_valid = true;
1468 }
1469 if (!bs_valid && (sc->sc_ah->imask & ATH9K_INT_SWBA)) {
1470 /* Disable SWBA interrupt */
1471 sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
1472 ath9k_ps_wakeup(sc); 1466 ath9k_ps_wakeup(sc);
1473 ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); 1467 ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
1474 ath9k_ps_restore(sc); 1468 ath9k_ps_restore(sc);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index c3129db7828f..00ebed3f9158 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -841,6 +841,10 @@ static bool ath9k_rx_accept(struct ath_common *common,
841 struct ath_rx_status *rx_stats, 841 struct ath_rx_status *rx_stats,
842 bool *decrypt_error) 842 bool *decrypt_error)
843{ 843{
844#define is_mc_or_valid_tkip_keyix ((is_mc || \
845 (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
846 test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
847
844 struct ath_hw *ah = common->ah; 848 struct ath_hw *ah = common->ah;
845 __le16 fc; 849 __le16 fc;
846 u8 rx_status_len = ah->caps.rx_status_len; 850 u8 rx_status_len = ah->caps.rx_status_len;
@@ -882,15 +886,18 @@ static bool ath9k_rx_accept(struct ath_common *common,
882 if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { 886 if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
883 *decrypt_error = true; 887 *decrypt_error = true;
884 } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { 888 } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
889 bool is_mc;
885 /* 890 /*
886 * The MIC error bit is only valid if the frame 891 * The MIC error bit is only valid if the frame
887 * is not a control frame or fragment, and it was 892 * is not a control frame or fragment, and it was
888 * decrypted using a valid TKIP key. 893 * decrypted using a valid TKIP key.
889 */ 894 */
895 is_mc = !!is_multicast_ether_addr(hdr->addr1);
896
890 if (!ieee80211_is_ctl(fc) && 897 if (!ieee80211_is_ctl(fc) &&
891 !ieee80211_has_morefrags(fc) && 898 !ieee80211_has_morefrags(fc) &&
892 !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && 899 !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
893 test_bit(rx_stats->rs_keyix, common->tkip_keymap)) 900 is_mc_or_valid_tkip_keyix)
894 rxs->flag |= RX_FLAG_MMIC_ERROR; 901 rxs->flag |= RX_FLAG_MMIC_ERROR;
895 else 902 else
896 rx_stats->rs_status &= ~ATH9K_RXERR_MIC; 903 rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index bce313e85cff..43c0109f202c 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1171,7 +1171,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
1171 } 1171 }
1172} 1172}
1173 1173
1174void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) 1174bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
1175{ 1175{
1176 struct ath_hw *ah = sc->sc_ah; 1176 struct ath_hw *ah = sc->sc_ah;
1177 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 1177 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -1179,7 +1179,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
1179 int i, npend = 0; 1179 int i, npend = 0;
1180 1180
1181 if (sc->sc_flags & SC_OP_INVALID) 1181 if (sc->sc_flags & SC_OP_INVALID)
1182 return; 1182 return true;
1183 1183
1184 /* Stop beacon queue */ 1184 /* Stop beacon queue */
1185 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); 1185 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
@@ -1193,22 +1193,15 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
1193 } 1193 }
1194 } 1194 }
1195 1195
1196 if (npend) { 1196 if (npend)
1197 int r; 1197 ath_err(common, "Failed to stop TX DMA!\n");
1198
1199 ath_err(common, "Failed to stop TX DMA. Resetting hardware!\n");
1200
1201 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
1202 if (r)
1203 ath_err(common,
1204 "Unable to reset hardware; reset status %d\n",
1205 r);
1206 }
1207 1198
1208 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { 1199 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
1209 if (ATH_TXQ_SETUP(sc, i)) 1200 if (ATH_TXQ_SETUP(sc, i))
1210 ath_draintxq(sc, &sc->tx.txq[i], retry_tx); 1201 ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
1211 } 1202 }
1203
1204 return !npend;
1212} 1205}
1213 1206
1214void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) 1207void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)