rpms/kernel/F-10 linux-2.6-rtl8187b-tx-status-feedback.patch, NONE, 1.1.2.2 linux-2.6.27-ath5k-ignore-the-return-value-of-ath5k_hw_noise_floor_calibration.patch, NONE, 1.1.2.1 kernel.spec, 1.1206.2.4, 1.1206.2.5

Chuck Ebbert cebbert at fedoraproject.org
Wed Jan 21 06:17:13 UTC 2009


Author: cebbert

Update of /cvs/pkgs/rpms/kernel/F-10
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv19706

Modified Files:
      Tag: private-fedora-10-2_6_27
	kernel.spec 
Added Files:
      Tag: private-fedora-10-2_6_27
	linux-2.6-rtl8187b-tx-status-feedback.patch 
	linux-2.6.27-ath5k-ignore-the-return-value-of-ath5k_hw_noise_floor_calibration.patch 
Log Message:
ath5k: ignore the return value of ath5k_hw_noise_floor_calibration
  (backport to 2.6.27)
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),

linux-2.6.27-ath5k-ignore-the-return-value-of-ath5k_hw_noise_floor_calibration.patch:

--- NEW FILE linux-2.6.27-ath5k-ignore-the-return-value-of-ath5k_hw_noise_floor_calibration.patch ---
>From 8b0162a3dc5c30e862b7a73da29e32de3170f5e4 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd at openwrt.org>
Date: Mon, 3 Nov 2008 11:27:38 +0100
Subject: ath5k: ignore the return value of ath5k_hw_noise_floor_calibration

From: Felix Fietkau <nbd at openwrt.org>

commit 8b0162a3dc5c30e862b7a73da29e32de3170f5e4 upstream.

Noise floor calibration occasionally fails on Atheros hardware.
This is not fatal and can happen if there's simply too much
noise on the air. Ignoring the calibration error is the right
thing to do here, because when the error is ignored, the hardware
will still work, whereas if the error causes the driver to bail out
of a bigger configuration function and does not configure the tx
queues or the IMR (as is the case in reset.c), the hw no longer
works properly until the next reset.

Signed-off-by: Felix Fietkau <nbd at openwrt.org>
Signed-off-by: John W. Linville <linville at tuxdriver.com>
Cc: Bob Copeland <me at bobcopeland.com>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>

---
 drivers/net/wireless/ath5k/phy.c   |    4 +---
 drivers/net/wireless/ath5k/reset.c |    4 +---
 2 files changed, 2 insertions(+), 6 deletions(-)

--- a/drivers/net/wireless/ath5k/phy.c
+++ b/drivers/net/wireless/ath5k/phy.c
@@ -2193,9 +2193,7 @@ static int ath5k_hw_rf5110_calibrate(str
 		return ret;
 	}
 
-	ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
-	if (ret)
-		return ret;
+	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
 
 	/*
 	 * Re-enable RX/TX and beacons
--- a/drivers/net/wireless/ath5k/hw.c
+++ b/drivers/net/wireless/ath5k/hw.c
@@ -1131,9 +1131,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, 
 	 *
 	 * XXX: Find an interval that's OK for all cards...
 	 */
-	ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
-	if (ret)
-		return ret;
+	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
 
 	/*
 	 * Reset queues and start beacon timers at the end of the reset routine


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-10/kernel.spec,v
retrieving revision 1.1206.2.4
retrieving revision 1.1206.2.5
diff -u -r1.1206.2.4 -r1.1206.2.5
--- kernel.spec	21 Jan 2009 05:51:11 -0000	1.1206.2.4
+++ kernel.spec	21 Jan 2009 06:16:42 -0000	1.1206.2.5
@@ -644,7 +644,9 @@
 
 Patch681: linux-2.6-iwl3945-ibss-tsf-fix.patch
 Patch682: linux-2.6-wireless-ath9k-dma-fixes.patch
-Patch690: linux-2.6-at76.patch
+Patch683: linux-2.6-at76.patch
+Patch684: linux-2.6.27-ath5k-ignore-the-return-value-of-ath5k_hw_noise_floor_calibration.patch
+Patch685: linux-2.6-rtl8187b-tx-status-feedback.patch
 
 Patch700: linux-2.6-nfs-client-mounts-hang.patch
 
@@ -1252,6 +1254,11 @@
 # Add misc wireless bits from upstream wireless tree
 ApplyPatch linux-2.6-at76.patch
 
+# ignore calibration so driver will work in noisy areas
+ApplyPatch linux-2.6.27-ath5k-ignore-the-return-value-of-ath5k_hw_noise_floor_calibration.patch
+
+ApplyPatch linux-2.6-rtl8187b-tx-status-feedback.patch
+
 # NFS Client mounts hang when exported directory do not exist
 ApplyPatch linux-2.6-nfs-client-mounts-hang.patch
 
@@ -1909,6 +1916,11 @@
 %kernel_variant_files -k vmlinux %{with_kdump} kdump
 
 %changelog
+* Tue Jan 20 2009 Chuck Ebbert <cebbert at redhat.com>
+- ath5k: ignore the return value of ath5k_hw_noise_floor_calibration
+  (backport to 2.6.27)
+- rtl8187: feedback transmitted packets using tx close descriptor for 8187B
+
 * Tue Jan 20 2009 Chuck Ebbert <cebbert at redhat.com> 2.6.27.12-170.2.4
 - Fix CVE-2009-0065: SCTP buffer overflow
 




More information about the scm-commits mailing list