aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHerton Ronaldo Krzesinski <herton@mandriva.com.br>2008-11-13 10:39:16 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-11-25 16:41:33 -0500
commit3517afdefc3ad335b276eb5f8691841f48097abf (patch)
tree150fb2ea5e8dcfe8f07523316a32dc45b94fba79 /drivers
parentb4572a9264312fecdb530a3416b8c8336a3bb9a9 (diff)
rtl8187: feedback transmitted packets using tx close descriptor for 8187B
Realtek 8187B has a receive command queue to feedback beacon interrupt and transmitted packet status. Use it to feedback mac80211 about status of transmitted packets. Unfortunately in the course of testing I found that the sequence number reported by hardware includes entire sequence control in a 12 bit only field, so a workaround is done to check only lowest bits. Tested-by: Larry Finger <Larry.Finger@lwfinger.net> Tested-by: Hin-Tak Leung <htl10@users.sourceforge.net> Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187.h5
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c135
2 files changed, 136 insertions, 4 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
index f09872eec3d5..c385407a9941 100644
--- a/drivers/net/wireless/rtl818x/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187.h
@@ -113,6 +113,11 @@ struct rtl8187_priv {
113 u8 noise; 113 u8 noise;
114 u8 slot_time; 114 u8 slot_time;
115 u8 aifsn[4]; 115 u8 aifsn[4];
116 struct {
117 __le64 buf;
118 struct urb *urb;
119 struct sk_buff_head queue;
120 } b_tx_status;
116}; 121};
117 122
118void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); 123void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index cb5bcefd1c3e..876d4f93d310 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -176,8 +176,27 @@ static void rtl8187_tx_cb(struct urb *urb)
176 skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : 176 skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
177 sizeof(struct rtl8187_tx_hdr)); 177 sizeof(struct rtl8187_tx_hdr));
178 ieee80211_tx_info_clear_status(info); 178 ieee80211_tx_info_clear_status(info);
179 info->flags |= IEEE80211_TX_STAT_ACK; 179
180 ieee80211_tx_status_irqsafe(hw, skb); 180 if (!urb->status &&
181 !(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
182 priv->is_rtl8187b) {
183 skb_queue_tail(&priv->b_tx_status.queue, skb);
184
185 /* queue is "full", discard last items */
186 while (skb_queue_len(&priv->b_tx_status.queue) > 5) {
187 struct sk_buff *old_skb;
188
189 dev_dbg(&priv->udev->dev,
190 "transmit status queue full\n");
191
192 old_skb = skb_dequeue(&priv->b_tx_status.queue);
193 ieee80211_tx_status_irqsafe(hw, old_skb);
194 }
195 } else {
196 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !urb->status)
197 info->flags |= IEEE80211_TX_STAT_ACK;
198 ieee80211_tx_status_irqsafe(hw, skb);
199 }
181} 200}
182 201
183static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) 202static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
@@ -219,7 +238,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
219 hdr->flags = cpu_to_le32(flags); 238 hdr->flags = cpu_to_le32(flags);
220 hdr->len = 0; 239 hdr->len = 0;
221 hdr->rts_duration = rts_dur; 240 hdr->rts_duration = rts_dur;
222 hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); 241 hdr->retry = cpu_to_le32(info->control.rates[0].count << 8);
223 buf = hdr; 242 buf = hdr;
224 243
225 ep = 2; 244 ep = 2;
@@ -237,7 +256,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
237 memset(hdr, 0, sizeof(*hdr)); 256 memset(hdr, 0, sizeof(*hdr));
238 hdr->flags = cpu_to_le32(flags); 257 hdr->flags = cpu_to_le32(flags);
239 hdr->rts_duration = rts_dur; 258 hdr->rts_duration = rts_dur;
240 hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); 259 hdr->retry = cpu_to_le32(info->control.rates[0].count << 8);
241 hdr->tx_duration = 260 hdr->tx_duration =
242 ieee80211_generic_frame_duration(dev, priv->vif, 261 ieee80211_generic_frame_duration(dev, priv->vif,
243 skb->len, txrate); 262 skb->len, txrate);
@@ -403,6 +422,109 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
403 return 0; 422 return 0;
404} 423}
405 424
425static void rtl8187b_status_cb(struct urb *urb)
426{
427 struct ieee80211_hw *hw = (struct ieee80211_hw *)urb->context;
428 struct rtl8187_priv *priv = hw->priv;
429 u64 val;
430 unsigned int cmd_type;
431
432 if (unlikely(urb->status)) {
433 usb_free_urb(urb);
434 return;
435 }
436
437 /*
438 * Read from status buffer:
439 *
440 * bits [30:31] = cmd type:
441 * - 0 indicates tx beacon interrupt
442 * - 1 indicates tx close descriptor
443 *
444 * In the case of tx beacon interrupt:
445 * [0:9] = Last Beacon CW
446 * [10:29] = reserved
447 * [30:31] = 00b
448 * [32:63] = Last Beacon TSF
449 *
450 * If it's tx close descriptor:
451 * [0:7] = Packet Retry Count
452 * [8:14] = RTS Retry Count
453 * [15] = TOK
454 * [16:27] = Sequence No
455 * [28] = LS
456 * [29] = FS
457 * [30:31] = 01b
458 * [32:47] = unused (reserved?)
459 * [48:63] = MAC Used Time
460 */
461 val = le64_to_cpu(priv->b_tx_status.buf);
462
463 cmd_type = (val >> 30) & 0x3;
464 if (cmd_type == 1) {
465 unsigned int pkt_rc, seq_no;
466 bool tok;
467 struct sk_buff *skb;
468 struct ieee80211_hdr *ieee80211hdr;
469 unsigned long flags;
470
471 pkt_rc = val & 0xFF;
472 tok = val & (1 << 15);
473 seq_no = (val >> 16) & 0xFFF;
474
475 spin_lock_irqsave(&priv->b_tx_status.queue.lock, flags);
476 skb_queue_reverse_walk(&priv->b_tx_status.queue, skb) {
477 ieee80211hdr = (struct ieee80211_hdr *)skb->data;
478
479 /*
480 * While testing, it was discovered that the seq_no
481 * doesn't actually contains the sequence number.
482 * Instead of returning just the 12 bits of sequence
483 * number, hardware is returning entire sequence control
484 * (fragment number plus sequence number) in a 12 bit
485 * only field overflowing after some time. As a
486 * workaround, just consider the lower bits, and expect
487 * it's unlikely we wrongly ack some sent data
488 */
489 if ((le16_to_cpu(ieee80211hdr->seq_ctrl)
490 & 0xFFF) == seq_no)
491 break;
492 }
493 if (skb != (struct sk_buff *) &priv->b_tx_status.queue) {
494 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
495
496 __skb_unlink(skb, &priv->b_tx_status.queue);
497 if (tok)
498 info->flags |= IEEE80211_TX_STAT_ACK;
499 info->status.rates[0].count = pkt_rc;
500
501 ieee80211_tx_status_irqsafe(hw, skb);
502 }
503 spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags);
504 }
505
506 usb_submit_urb(urb, GFP_ATOMIC);
507}
508
509static int rtl8187b_init_status_urb(struct ieee80211_hw *dev)
510{
511 struct rtl8187_priv *priv = dev->priv;
512 struct urb *entry;
513
514 entry = usb_alloc_urb(0, GFP_KERNEL);
515 if (!entry)
516 return -ENOMEM;
517 priv->b_tx_status.urb = entry;
518
519 usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9),
520 &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf),
521 rtl8187b_status_cb, dev);
522
523 usb_submit_urb(entry, GFP_KERNEL);
524
525 return 0;
526}
527
406static int rtl8187_cmd_reset(struct ieee80211_hw *dev) 528static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
407{ 529{
408 struct rtl8187_priv *priv = dev->priv; 530 struct rtl8187_priv *priv = dev->priv;
@@ -755,6 +877,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
755 (7 << 0 /* long retry limit */) | 877 (7 << 0 /* long retry limit */) |
756 (7 << 21 /* MAX TX DMA */)); 878 (7 << 21 /* MAX TX DMA */));
757 rtl8187_init_urbs(dev); 879 rtl8187_init_urbs(dev);
880 rtl8187b_init_status_urb(dev);
758 mutex_unlock(&priv->conf_mutex); 881 mutex_unlock(&priv->conf_mutex);
759 return 0; 882 return 0;
760 } 883 }
@@ -831,6 +954,9 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
831 usb_kill_urb(info->urb); 954 usb_kill_urb(info->urb);
832 kfree_skb(skb); 955 kfree_skb(skb);
833 } 956 }
957 while ((skb = skb_dequeue(&priv->b_tx_status.queue)))
958 dev_kfree_skb_any(skb);
959 usb_kill_urb(priv->b_tx_status.urb);
834 mutex_unlock(&priv->conf_mutex); 960 mutex_unlock(&priv->conf_mutex);
835} 961}
836 962
@@ -1317,6 +1443,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
1317 goto err_free_dev; 1443 goto err_free_dev;
1318 } 1444 }
1319 mutex_init(&priv->conf_mutex); 1445 mutex_init(&priv->conf_mutex);
1446 skb_queue_head_init(&priv->b_tx_status.queue);
1320 1447
1321 printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n", 1448 printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n",
1322 wiphy_name(dev->wiphy), dev->wiphy->perm_addr, 1449 wiphy_name(dev->wiphy), dev->wiphy->perm_addr,