aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorMichael Wu <flamingice@sourmilk.net>2007-09-24 18:10:25 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:53:10 -0400
commitd703e29a88c91f015aa691a195e8fd4426c4ec73 (patch)
treeb45be14eb891166f5968984c53d27d20ee339ee0 /drivers/net/wireless
parentf6ac0adf54ed3fc7fa47e66b92defcbdf37b44ab (diff)
[PATCH] adm8211: Pass all TXed frames to tx_status_irqsafe
ieee80211_tx_status_irqsafe can handle the freeing of all TXed frames. Also, set excessive_retries for failed frames. Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/adm8211.c27
1 files changed, 13 insertions, 14 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index e950a7d55711..95c8315d71ec 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -299,6 +299,7 @@ static void adm8211_interrupt_tci(struct ieee80211_hw *dev)
299 for (dirty_tx = priv->dirty_tx; priv->cur_tx - dirty_tx; dirty_tx++) { 299 for (dirty_tx = priv->dirty_tx; priv->cur_tx - dirty_tx; dirty_tx++) {
300 unsigned int entry = dirty_tx % priv->tx_ring_size; 300 unsigned int entry = dirty_tx % priv->tx_ring_size;
301 u32 status = le32_to_cpu(priv->tx_ring[entry].status); 301 u32 status = le32_to_cpu(priv->tx_ring[entry].status);
302 struct ieee80211_tx_status tx_status;
302 struct adm8211_tx_ring_info *info; 303 struct adm8211_tx_ring_info *info;
303 struct sk_buff *skb; 304 struct sk_buff *skb;
304 305
@@ -314,21 +315,19 @@ static void adm8211_interrupt_tci(struct ieee80211_hw *dev)
314 pci_unmap_single(priv->pdev, info->mapping, 315 pci_unmap_single(priv->pdev, info->mapping,
315 info->skb->len, PCI_DMA_TODEVICE); 316 info->skb->len, PCI_DMA_TODEVICE);
316 317
317 if (info->tx_control.flags & IEEE80211_TXCTL_REQ_TX_STATUS) { 318 memset(&tx_status, 0, sizeof(tx_status));
318 struct ieee80211_tx_status tx_status = {{0}}; 319 skb_pull(skb, sizeof(struct adm8211_tx_hdr));
319 struct ieee80211_hdr *hdr; 320 memcpy(skb_push(skb, info->hdrlen), skb->cb, info->hdrlen);
320 size_t hdrlen = info->hdrlen; 321 memcpy(&tx_status.control, &info->tx_control,
321 322 sizeof(tx_status.control));
322 skb_pull(skb, sizeof(struct adm8211_tx_hdr)); 323 if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
323 hdr = (struct ieee80211_hdr *)skb_push(skb, hdrlen); 324 if (status & TDES0_STATUS_ES)
324 memcpy(hdr, skb->cb, hdrlen); 325 tx_status.excessive_retries = 1;
325 memcpy(&tx_status.control, &info->tx_control, 326 else
326 sizeof(tx_status.control));
327 if (!(status & TDES0_STATUS_ES))
328 tx_status.flags |= IEEE80211_TX_STATUS_ACK; 327 tx_status.flags |= IEEE80211_TX_STATUS_ACK;
329 ieee80211_tx_status_irqsafe(dev, skb, &tx_status); 328 }
330 } else 329 ieee80211_tx_status_irqsafe(dev, skb, &tx_status);
331 dev_kfree_skb_irq(skb); 330
332 info->skb = NULL; 331 info->skb = NULL;
333 } 332 }
334 333