rpms/kernel/F-10 linux-2.6-rtl8187b-tx-status-feedback.patch, NONE, 1.1 kernel.spec, 1.1224, 1.1225
John W. Linville
linville at fedoraproject.org
Tue Jan 20 17:36:30 UTC 2009
Author: linville
Update of /cvs/pkgs/rpms/kernel/F-10
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv29420
Modified Files:
kernel.spec
Added Files:
linux-2.6-rtl8187b-tx-status-feedback.patch
Log Message:
rtl8187: feedback transmitted packets using tx close descriptor for 8187B
linux-2.6-rtl8187b-tx-status-feedback.patch:
--- NEW FILE linux-2.6-rtl8187b-tx-status-feedback.patch ---
Back-ported from the following commit:
commit 3517afdefc3ad335b276eb5f8691841f48097abf
Author: Herton Ronaldo Krzesinski <herton at mandriva.com.br>
Date: Thu Nov 13 10:39:16 2008 -0500
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 at lwfinger.net>
Tested-by: Hin-Tak Leung <htl10 at users.sourceforge.net>
Signed-off-by: Herton Ronaldo Krzesinski <herton at mandriva.com.br>
Signed-off-by: John W. Linville <linville at tuxdriver.com>
diff -up linux-2.6.28.noarch/drivers/net/wireless/rtl8187.h.orig linux-2.6.28.noarch/drivers/net/wireless/rtl8187.h
--- linux-2.6.28.noarch/drivers/net/wireless/rtl8187.h.orig 2008-12-24 18:26:37.000000000 -0500
+++ linux-2.6.28.noarch/drivers/net/wireless/rtl8187.h 2009-01-20 11:46:40.000000000 -0500
@@ -112,6 +112,11 @@ struct rtl8187_priv {
u8 signal;
u8 quality;
u8 noise;
+ struct {
+ __le64 buf;
+ struct urb *urb;
+ struct sk_buff_head queue;
+ } b_tx_status;
};
void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
diff -up linux-2.6.28.noarch/drivers/net/wireless/rtl8187_dev.c.orig linux-2.6.28.noarch/drivers/net/wireless/rtl8187_dev.c
--- linux-2.6.28.noarch/drivers/net/wireless/rtl8187_dev.c.orig 2008-12-24 18:26:37.000000000 -0500
+++ linux-2.6.28.noarch/drivers/net/wireless/rtl8187_dev.c 2009-01-20 11:51:33.000000000 -0500
@@ -170,8 +170,27 @@ static void rtl8187_tx_cb(struct urb *ur
skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
sizeof(struct rtl8187_tx_hdr));
memset(&info->status, 0, sizeof(info->status));
- info->flags |= IEEE80211_TX_STAT_ACK;
- ieee80211_tx_status_irqsafe(hw, skb);
+
+ if (!urb->status &&
+ !(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+ priv->is_rtl8187b) {
+ skb_queue_tail(&priv->b_tx_status.queue, skb);
+
+ /* queue is "full", discard last items */
+ while (skb_queue_len(&priv->b_tx_status.queue) > 5) {
+ struct sk_buff *old_skb;
+
+ dev_dbg(&priv->udev->dev,
+ "transmit status queue full\n");
+
+ old_skb = skb_dequeue(&priv->b_tx_status.queue);
+ ieee80211_tx_status_irqsafe(hw, old_skb);
+ }
+ } else {
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !urb->status)
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ ieee80211_tx_status_irqsafe(hw, skb);
+ }
}
static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
@@ -412,6 +431,111 @@ static int rtl8187_init_urbs(struct ieee
return 0;
}
+static void rtl8187b_status_cb(struct urb *urb)
+{
+ struct ieee80211_hw *hw = (struct ieee80211_hw *)urb->context;
+ struct rtl8187_priv *priv = hw->priv;
+ u64 val;
+ unsigned int cmd_type;
+
+ if (unlikely(urb->status)) {
+ usb_free_urb(urb);
+ return;
+ }
+
+ /*
+ * Read from status buffer:
+ *
+ * bits [30:31] = cmd type:
+ * - 0 indicates tx beacon interrupt
+ * - 1 indicates tx close descriptor
+ *
+ * In the case of tx beacon interrupt:
+ * [0:9] = Last Beacon CW
+ * [10:29] = reserved
+ * [30:31] = 00b
+ * [32:63] = Last Beacon TSF
+ *
+ * If it's tx close descriptor:
+ * [0:7] = Packet Retry Count
+ * [8:14] = RTS Retry Count
+ * [15] = TOK
+ * [16:27] = Sequence No
+ * [28] = LS
+ * [29] = FS
+ * [30:31] = 01b
+ * [32:47] = unused (reserved?)
+ * [48:63] = MAC Used Time
+ */
+ val = le64_to_cpu(priv->b_tx_status.buf);
+
+ cmd_type = (val >> 30) & 0x3;
+ if (cmd_type == 1) {
+ unsigned int pkt_rc, seq_no;
+ bool tok;
+ struct sk_buff *skb;
+ struct ieee80211_hdr *ieee80211hdr;
+ unsigned long flags;
+
+ pkt_rc = val & 0xFF;
+ tok = val & (1 << 15);
+ seq_no = (val >> 16) & 0xFFF;
+
+ spin_lock_irqsave(&priv->b_tx_status.queue.lock, flags);
+ skb_queue_reverse_walk(&priv->b_tx_status.queue, skb) {
+ ieee80211hdr = (struct ieee80211_hdr *)skb->data;
+
+ /*
+ * While testing, it was discovered that the seq_no
+ * doesn't actually contains the sequence number.
+ * Instead of returning just the 12 bits of sequence
+ * number, hardware is returning entire sequence control
+ * (fragment number plus sequence number) in a 12 bit
+ * only field overflowing after some time. As a
+ * workaround, just consider the lower bits, and expect
+ * it's unlikely we wrongly ack some sent data
+ */
+ if ((le16_to_cpu(ieee80211hdr->seq_ctrl)
+ & 0xFFF) == seq_no)
+ break;
+ }
+ if (skb != (struct sk_buff *) &priv->b_tx_status.queue) {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ __skb_unlink(skb, &priv->b_tx_status.queue);
+ if (tok)
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ else
+ info->status.excessive_retries = 1;
+ info->status.retry_count = pkt_rc;
+
+ ieee80211_tx_status_irqsafe(hw, skb);
+ }
+ spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags);
+ }
+
+ usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int rtl8187b_init_status_urb(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct urb *entry;
+
+ entry = usb_alloc_urb(0, GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+ priv->b_tx_status.urb = entry;
+
+ usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9),
+ &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf),
+ rtl8187b_status_cb, dev);
+
+ usb_submit_urb(entry, GFP_KERNEL);
+
+ return 0;
+}
+
static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
@@ -757,6 +879,7 @@ static int rtl8187_start(struct ieee8021
(7 << 0 /* long retry limit */) |
(7 << 21 /* MAX TX DMA */));
rtl8187_init_urbs(dev);
+ rtl8187b_init_status_urb(dev);
mutex_unlock(&priv->conf_mutex);
return 0;
}
@@ -833,6 +956,9 @@ static void rtl8187_stop(struct ieee8021
usb_kill_urb(info->urb);
kfree_skb(skb);
}
+ while ((skb = skb_dequeue(&priv->b_tx_status.queue)))
+ dev_kfree_skb_any(skb);
+ usb_kill_urb(priv->b_tx_status.urb);
mutex_unlock(&priv->conf_mutex);
}
@@ -1211,6 +1337,7 @@ static int __devinit rtl8187_probe(struc
goto err_free_dev;
}
mutex_init(&priv->conf_mutex);
+ skb_queue_head_init(&priv->b_tx_status.queue);
printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n",
wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-10/kernel.spec,v
retrieving revision 1.1224
retrieving revision 1.1225
diff -u -r1.1224 -r1.1225
--- kernel.spec 20 Jan 2009 16:34:06 -0000 1.1224
+++ kernel.spec 20 Jan 2009 17:35:59 -0000 1.1225
@@ -628,7 +628,8 @@
Patch670: linux-2.6-ata-quirk.patch
-Patch682: iwlwifi-intel-bug-1822.patch
+Patch680: iwlwifi-intel-bug-1822.patch
+Patch681: linux-2.6-rtl8187b-tx-status-feedback.patch
Patch690: linux-2.6-at76.patch
@@ -1154,6 +1155,9 @@
# iwlwifi: avoid rs_get_rate warnings
ApplyPatch iwlwifi-intel-bug-1822.patch
+# rtl8187: feedback transmitted packets using tx close descriptor for 8187B
+ApplyPatch linux-2.6-rtl8187b-tx-status-feedback.patch
+
# Add misc wireless bits from upstream wireless tree
ApplyPatch linux-2.6-at76.patch
@@ -1779,6 +1783,9 @@
%kernel_variant_files -k vmlinux %{with_kdump} kdump
%changelog
+* Tue Jan 20 2009 John W. Linville <linville at redhat.com> 2.6.28.1-18
+- rtl8187: feedback transmitted packets using tx close descriptor for 8187B
+
* Tue Jan 20 2009 Chuck Ebbert <cebbert at redhat.com> 2.6.28.1-17
- Set CONFIG_CAPI_EICON on x86_64, re-enable Radeon kernel modesetting.
- Change remaining config options from '=n' to 'is not set'.
More information about the fedora-extras-commits
mailing list