| .. | .. |
|---|
| 106 | 106 | |
|---|
| 107 | 107 | switch (qnum) { |
|---|
| 108 | 108 | case 0: |
|---|
| 109 | | - TX_QSTAT_INC(IEEE80211_AC_VO); |
|---|
| 109 | + TX_QSTAT_INC(priv, IEEE80211_AC_VO); |
|---|
| 110 | 110 | epid = priv->data_vo_ep; |
|---|
| 111 | 111 | break; |
|---|
| 112 | 112 | case 1: |
|---|
| 113 | | - TX_QSTAT_INC(IEEE80211_AC_VI); |
|---|
| 113 | + TX_QSTAT_INC(priv, IEEE80211_AC_VI); |
|---|
| 114 | 114 | epid = priv->data_vi_ep; |
|---|
| 115 | 115 | break; |
|---|
| 116 | 116 | case 2: |
|---|
| 117 | | - TX_QSTAT_INC(IEEE80211_AC_BE); |
|---|
| 117 | + TX_QSTAT_INC(priv, IEEE80211_AC_BE); |
|---|
| 118 | 118 | epid = priv->data_be_ep; |
|---|
| 119 | 119 | break; |
|---|
| 120 | 120 | case 3: |
|---|
| 121 | 121 | default: |
|---|
| 122 | | - TX_QSTAT_INC(IEEE80211_AC_BK); |
|---|
| 122 | + TX_QSTAT_INC(priv, IEEE80211_AC_BK); |
|---|
| 123 | 123 | epid = priv->data_bk_ep; |
|---|
| 124 | 124 | break; |
|---|
| 125 | 125 | } |
|---|
| .. | .. |
|---|
| 323 | 323 | memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); |
|---|
| 324 | 324 | |
|---|
| 325 | 325 | if (is_cab) { |
|---|
| 326 | | - CAB_STAT_INC; |
|---|
| 326 | + CAB_STAT_INC(priv); |
|---|
| 327 | 327 | tx_ctl->epid = priv->cab_ep; |
|---|
| 328 | 328 | return; |
|---|
| 329 | 329 | } |
|---|
| .. | .. |
|---|
| 570 | 570 | spin_unlock_bh(&priv->tx.tx_lock); |
|---|
| 571 | 571 | } |
|---|
| 572 | 572 | |
|---|
| 573 | | -void ath9k_tx_failed_tasklet(unsigned long data) |
|---|
| 573 | +void ath9k_tx_failed_tasklet(struct tasklet_struct *t) |
|---|
| 574 | 574 | { |
|---|
| 575 | | - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; |
|---|
| 575 | + struct ath9k_htc_priv *priv = from_tasklet(priv, t, tx_failed_tasklet); |
|---|
| 576 | 576 | |
|---|
| 577 | | - spin_lock_bh(&priv->tx.tx_lock); |
|---|
| 577 | + spin_lock(&priv->tx.tx_lock); |
|---|
| 578 | 578 | if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { |
|---|
| 579 | | - spin_unlock_bh(&priv->tx.tx_lock); |
|---|
| 579 | + spin_unlock(&priv->tx.tx_lock); |
|---|
| 580 | 580 | return; |
|---|
| 581 | 581 | } |
|---|
| 582 | | - spin_unlock_bh(&priv->tx.tx_lock); |
|---|
| 582 | + spin_unlock(&priv->tx.tx_lock); |
|---|
| 583 | 583 | |
|---|
| 584 | 584 | ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); |
|---|
| 585 | 585 | } |
|---|
| .. | .. |
|---|
| 808 | 808 | skb_queue_head_init(&priv->tx.data_vi_queue); |
|---|
| 809 | 809 | skb_queue_head_init(&priv->tx.data_vo_queue); |
|---|
| 810 | 810 | skb_queue_head_init(&priv->tx.tx_failed); |
|---|
| 811 | + |
|---|
| 812 | + /* Allow ath9k_wmi_event_tasklet(WMI_TXSTATUS_EVENTID) to operate. */ |
|---|
| 813 | + smp_wmb(); |
|---|
| 814 | + priv->tx.initialized = true; |
|---|
| 815 | + |
|---|
| 811 | 816 | return 0; |
|---|
| 812 | 817 | } |
|---|
| 813 | 818 | |
|---|
| .. | .. |
|---|
| 893 | 898 | if (priv->rxfilter & FIF_PSPOLL) |
|---|
| 894 | 899 | rfilt |= ATH9K_RX_FILTER_PSPOLL; |
|---|
| 895 | 900 | |
|---|
| 896 | | - if (priv->nvifs > 1 || priv->rxfilter & FIF_OTHER_BSS) |
|---|
| 901 | + if (priv->nvifs > 1 || |
|---|
| 902 | + priv->rxfilter & (FIF_OTHER_BSS | FIF_MCAST_ACTION)) |
|---|
| 897 | 903 | rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; |
|---|
| 898 | 904 | |
|---|
| 899 | 905 | return rfilt; |
|---|
| .. | .. |
|---|
| 1005 | 1011 | goto rx_next; |
|---|
| 1006 | 1012 | } |
|---|
| 1007 | 1013 | |
|---|
| 1014 | + if (rxstatus->rs_keyix >= ATH_KEYMAX && |
|---|
| 1015 | + rxstatus->rs_keyix != ATH9K_RXKEYIX_INVALID) { |
|---|
| 1016 | + ath_dbg(common, ANY, |
|---|
| 1017 | + "Invalid keyix, dropping (keyix: %d)\n", |
|---|
| 1018 | + rxstatus->rs_keyix); |
|---|
| 1019 | + goto rx_next; |
|---|
| 1020 | + } |
|---|
| 1021 | + |
|---|
| 1008 | 1022 | /* Get the RX status information */ |
|---|
| 1009 | 1023 | |
|---|
| 1010 | 1024 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); |
|---|
| .. | .. |
|---|
| 1061 | 1075 | /* |
|---|
| 1062 | 1076 | * FIXME: Handle FLUSH later on. |
|---|
| 1063 | 1077 | */ |
|---|
| 1064 | | -void ath9k_rx_tasklet(unsigned long data) |
|---|
| 1078 | +void ath9k_rx_tasklet(struct tasklet_struct *t) |
|---|
| 1065 | 1079 | { |
|---|
| 1066 | | - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; |
|---|
| 1080 | + struct ath9k_htc_priv *priv = from_tasklet(priv, t, rx_tasklet); |
|---|
| 1067 | 1081 | struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; |
|---|
| 1068 | 1082 | struct ieee80211_rx_status rx_status; |
|---|
| 1069 | 1083 | struct sk_buff *skb; |
|---|
| .. | .. |
|---|
| 1124 | 1138 | struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; |
|---|
| 1125 | 1139 | unsigned long flags; |
|---|
| 1126 | 1140 | |
|---|
| 1141 | + /* Check if ath9k_rx_init() completed. */ |
|---|
| 1142 | + if (!data_race(priv->rx.initialized)) |
|---|
| 1143 | + goto err; |
|---|
| 1144 | + |
|---|
| 1127 | 1145 | spin_lock_irqsave(&priv->rx.rxbuflock, flags); |
|---|
| 1128 | 1146 | list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { |
|---|
| 1129 | 1147 | if (!tmp_buf->in_process) { |
|---|
| .. | .. |
|---|
| 1179 | 1197 | list_add_tail(&rxbuf->list, &priv->rx.rxbuf); |
|---|
| 1180 | 1198 | } |
|---|
| 1181 | 1199 | |
|---|
| 1200 | + /* Allow ath9k_htc_rxep() to operate. */ |
|---|
| 1201 | + smp_wmb(); |
|---|
| 1202 | + priv->rx.initialized = true; |
|---|
| 1203 | + |
|---|
| 1182 | 1204 | return 0; |
|---|
| 1183 | 1205 | |
|---|
| 1184 | 1206 | err: |
|---|