diff options
author | Michael Wu <flamingice@sourmilk.net> | 2007-09-24 18:10:25 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:53:10 -0400 |
commit | d703e29a88c91f015aa691a195e8fd4426c4ec73 (patch) | |
tree | b45be14eb891166f5968984c53d27d20ee339ee0 /drivers/net/wireless/adm8211.c | |
parent | f6ac0adf54ed3fc7fa47e66b92defcbdf37b44ab (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/adm8211.c')
-rw-r--r-- | drivers/net/wireless/adm8211.c | 27 |
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 | ||