.. | .. |
---|
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: |
---|