aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <Sujith.Manoharan@atheros.com>2011-04-13 01:55:47 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-13 15:23:57 -0400
commit2c5d57f004673a9c8658e20b1fa3f992b5a10f70 (patch)
tree93576651f009819fa7b1160c9a2d567ee4284e94
parent729bd3ab460d3bb8236cc8f6fd0289201124112d (diff)
ath9k_htc: Add TX slots
Maintain a bitmap of slots for transmission and update the cookie field for every packet with the slot value. This value would be used for matching packets when TX completion processing is added. Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h5
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c14
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c51
4 files changed, 73 insertions, 14 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 0831ca3de95c..45cf75579438 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -271,6 +271,7 @@ struct ath9k_htc_tx {
271 u8 flags; 271 u8 flags;
272 int queued_cnt; 272 int queued_cnt;
273 struct sk_buff_head tx_queue; 273 struct sk_buff_head tx_queue;
274 DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM);
274 spinlock_t tx_lock; 275 spinlock_t tx_lock;
275}; 276};
276 277
@@ -532,7 +533,7 @@ void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);
532int ath9k_tx_init(struct ath9k_htc_priv *priv); 533int ath9k_tx_init(struct ath9k_htc_priv *priv);
533void ath9k_tx_tasklet(unsigned long data); 534void ath9k_tx_tasklet(unsigned long data);
534int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, 535int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
535 struct sk_buff *skb, bool is_cab); 536 struct sk_buff *skb, u8 slot, bool is_cab);
536void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); 537void ath9k_tx_cleanup(struct ath9k_htc_priv *priv);
537bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); 538bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype);
538int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); 539int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv);
@@ -541,6 +542,8 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
541 struct ath9k_tx_queue_info *qinfo); 542 struct ath9k_tx_queue_info *qinfo);
542void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv); 543void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv);
543void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv); 544void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv);
545int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv);
546void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot);
544 547
545int ath9k_rx_init(struct ath9k_htc_priv *priv); 548int ath9k_rx_init(struct ath9k_htc_priv *priv);
546void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); 549void ath9k_rx_cleanup(struct ath9k_htc_priv *priv);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index 97b116fb4e11..bf7ef1b7eb3f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -299,7 +299,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv,
299 struct ieee80211_vif *vif; 299 struct ieee80211_vif *vif;
300 struct sk_buff *skb; 300 struct sk_buff *skb;
301 struct ieee80211_hdr *hdr; 301 struct ieee80211_hdr *hdr;
302 int padpos, padsize, ret; 302 int padpos, padsize, ret, tx_slot;
303 303
304 spin_lock_bh(&priv->beacon_lock); 304 spin_lock_bh(&priv->beacon_lock);
305 305
@@ -321,11 +321,20 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv,
321 memmove(skb->data, skb->data + padsize, padpos); 321 memmove(skb->data, skb->data + padsize, padpos);
322 } 322 }
323 323
324 ret = ath9k_htc_tx_start(priv, skb, true); 324 tx_slot = ath9k_htc_tx_get_slot(priv);
325 if (tx_slot != 0) {
326 ath_dbg(common, ATH_DBG_XMIT, "No free CAB slot\n");
327 dev_kfree_skb_any(skb);
328 goto next;
329 }
330
331 ret = ath9k_htc_tx_start(priv, skb, tx_slot, true);
325 if (ret != 0) { 332 if (ret != 0) {
326 ath_dbg(common, ATH_DBG_FATAL, 333 ath9k_htc_tx_clear_slot(priv, tx_slot);
327 "Failed to send CAB frame\n");
328 dev_kfree_skb_any(skb); 334 dev_kfree_skb_any(skb);
335
336 ath_dbg(common, ATH_DBG_XMIT,
337 "Failed to send CAB frame\n");
329 } else { 338 } else {
330 spin_lock_bh(&priv->tx.tx_lock); 339 spin_lock_bh(&priv->tx.tx_lock);
331 priv->tx.queued_cnt++; 340 priv->tx.queued_cnt++;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 690113673d25..c7e056b40e1d 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -834,7 +834,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
834 struct ieee80211_hdr *hdr; 834 struct ieee80211_hdr *hdr;
835 struct ath9k_htc_priv *priv = hw->priv; 835 struct ath9k_htc_priv *priv = hw->priv;
836 struct ath_common *common = ath9k_hw_common(priv->ah); 836 struct ath_common *common = ath9k_hw_common(priv->ah);
837 int padpos, padsize, ret; 837 int padpos, padsize, ret, slot;
838 838
839 hdr = (struct ieee80211_hdr *) skb->data; 839 hdr = (struct ieee80211_hdr *) skb->data;
840 840
@@ -850,16 +850,24 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
850 memmove(skb->data, skb->data + padsize, padpos); 850 memmove(skb->data, skb->data + padsize, padpos);
851 } 851 }
852 852
853 ret = ath9k_htc_tx_start(priv, skb, false); 853 slot = ath9k_htc_tx_get_slot(priv);
854 if (slot < 0) {
855 ath_dbg(common, ATH_DBG_XMIT, "No free TX slot\n");
856 goto fail_tx;
857 }
858
859 ret = ath9k_htc_tx_start(priv, skb, slot, false);
854 if (ret != 0) { 860 if (ret != 0) {
855 ath_dbg(common, ATH_DBG_XMIT, "Tx failed\n"); 861 ath_dbg(common, ATH_DBG_XMIT, "Tx failed\n");
856 goto fail_tx; 862 goto clear_slot;
857 } 863 }
858 864
859 ath9k_htc_check_stop_queues(priv); 865 ath9k_htc_check_stop_queues(priv);
860 866
861 return; 867 return;
862 868
869clear_slot:
870 ath9k_htc_tx_clear_slot(priv, slot);
863fail_tx: 871fail_tx:
864 dev_kfree_skb_any(skb); 872 dev_kfree_skb_any(skb);
865} 873}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 7b218dad55d9..ee5b3e281cd3 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -76,6 +76,29 @@ void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv)
76 spin_unlock_bh(&priv->tx.tx_lock); 76 spin_unlock_bh(&priv->tx.tx_lock);
77} 77}
78 78
79int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv)
80{
81 int slot;
82
83 spin_lock_bh(&priv->tx.tx_lock);
84 slot = find_first_zero_bit(priv->tx.tx_slot, MAX_TX_BUF_NUM);
85 if (slot >= MAX_TX_BUF_NUM) {
86 spin_unlock_bh(&priv->tx.tx_lock);
87 return -ENOBUFS;
88 }
89 __set_bit(slot, priv->tx.tx_slot);
90 spin_unlock_bh(&priv->tx.tx_lock);
91
92 return slot;
93}
94
95void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot)
96{
97 spin_lock_bh(&priv->tx.tx_lock);
98 __clear_bit(slot, priv->tx.tx_slot);
99 spin_unlock_bh(&priv->tx.tx_lock);
100}
101
79static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, 102static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
80 u16 qnum) 103 u16 qnum)
81{ 104{
@@ -104,28 +127,38 @@ static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
104 return epid; 127 return epid;
105} 128}
106 129
130/*
131 * Removes the driver header and returns the TX slot number
132 */
107static inline int strip_drv_header(struct ath9k_htc_priv *priv, 133static inline int strip_drv_header(struct ath9k_htc_priv *priv,
108 struct sk_buff *skb) 134 struct sk_buff *skb)
109{ 135{
110 struct ath_common *common = ath9k_hw_common(priv->ah); 136 struct ath_common *common = ath9k_hw_common(priv->ah);
111 struct ath9k_htc_tx_ctl *tx_ctl; 137 struct ath9k_htc_tx_ctl *tx_ctl;
138 int slot;
112 139
113 tx_ctl = HTC_SKB_CB(skb); 140 tx_ctl = HTC_SKB_CB(skb);
114 141
115 if (tx_ctl->epid == priv->mgmt_ep) { 142 if (tx_ctl->epid == priv->mgmt_ep) {
143 struct tx_mgmt_hdr *tx_mhdr =
144 (struct tx_mgmt_hdr *)skb->data;
145 slot = tx_mhdr->cookie;
116 skb_pull(skb, sizeof(struct tx_mgmt_hdr)); 146 skb_pull(skb, sizeof(struct tx_mgmt_hdr));
117 } else if ((tx_ctl->epid == priv->data_bk_ep) || 147 } else if ((tx_ctl->epid == priv->data_bk_ep) ||
118 (tx_ctl->epid == priv->data_be_ep) || 148 (tx_ctl->epid == priv->data_be_ep) ||
119 (tx_ctl->epid == priv->data_vi_ep) || 149 (tx_ctl->epid == priv->data_vi_ep) ||
120 (tx_ctl->epid == priv->data_vo_ep) || 150 (tx_ctl->epid == priv->data_vo_ep) ||
121 (tx_ctl->epid == priv->cab_ep)) { 151 (tx_ctl->epid == priv->cab_ep)) {
152 struct tx_frame_hdr *tx_fhdr =
153 (struct tx_frame_hdr *)skb->data;
154 slot = tx_fhdr->cookie;
122 skb_pull(skb, sizeof(struct tx_frame_hdr)); 155 skb_pull(skb, sizeof(struct tx_frame_hdr));
123 } else { 156 } else {
124 ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid); 157 ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid);
125 return -EINVAL; 158 slot = -EINVAL;
126 } 159 }
127 160
128 return 0; 161 return slot;
129} 162}
130 163
131int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, 164int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
@@ -155,7 +188,8 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
155} 188}
156 189
157int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, 190int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
158 struct sk_buff *skb, bool is_cab) 191 struct sk_buff *skb,
192 u8 slot, bool is_cab)
159{ 193{
160 struct ieee80211_hdr *hdr; 194 struct ieee80211_hdr *hdr;
161 struct ieee80211_mgmt *mgmt; 195 struct ieee80211_mgmt *mgmt;
@@ -212,6 +246,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
212 246
213 tx_hdr.node_idx = sta_idx; 247 tx_hdr.node_idx = sta_idx;
214 tx_hdr.vif_idx = vif_idx; 248 tx_hdr.vif_idx = vif_idx;
249 tx_hdr.cookie = slot;
215 250
216 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { 251 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
217 tx_ctl->type = ATH9K_HTC_AMPDU; 252 tx_ctl->type = ATH9K_HTC_AMPDU;
@@ -274,6 +309,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
274 mgmt_hdr.vif_idx = vif_idx; 309 mgmt_hdr.vif_idx = vif_idx;
275 mgmt_hdr.tidno = 0; 310 mgmt_hdr.tidno = 0;
276 mgmt_hdr.flags = 0; 311 mgmt_hdr.flags = 0;
312 mgmt_hdr.cookie = slot;
277 313
278 mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); 314 mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
279 if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) 315 if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR)
@@ -313,10 +349,12 @@ void ath9k_tx_tasklet(unsigned long data)
313 struct sk_buff *skb = NULL; 349 struct sk_buff *skb = NULL;
314 __le16 fc; 350 __le16 fc;
315 bool txok; 351 bool txok;
352 int slot;
316 353
317 while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { 354 while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) {
318 355
319 if (strip_drv_header(priv, skb) < 0) { 356 slot = strip_drv_header(priv, skb);
357 if (slot < 0) {
320 dev_kfree_skb_any(skb); 358 dev_kfree_skb_any(skb);
321 continue; 359 continue;
322 } 360 }
@@ -347,8 +385,7 @@ void ath9k_tx_tasklet(unsigned long data)
347 sta = ieee80211_find_sta(vif, hdr->addr1); 385 sta = ieee80211_find_sta(vif, hdr->addr1);
348 if (!sta) { 386 if (!sta) {
349 rcu_read_unlock(); 387 rcu_read_unlock();
350 ieee80211_tx_status(priv->hw, skb); 388 goto send_mac80211;
351 continue;
352 } 389 }
353 390
354 /* Check if we need to start aggregation */ 391 /* Check if we need to start aggregation */
@@ -380,6 +417,8 @@ void ath9k_tx_tasklet(unsigned long data)
380 priv->tx.queued_cnt = 0; 417 priv->tx.queued_cnt = 0;
381 spin_unlock_bh(&priv->tx.tx_lock); 418 spin_unlock_bh(&priv->tx.tx_lock);
382 419
420 ath9k_htc_tx_clear_slot(priv, slot);
421
383 /* Send status to mac80211 */ 422 /* Send status to mac80211 */
384 ieee80211_tx_status(priv->hw, skb); 423 ieee80211_tx_status(priv->hw, skb);
385 } 424 }