summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-07-12 15:17:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-12 15:33:00 -0400
commit5274cf846b822b67381e26af1512e45bbc73bf50 (patch)
tree5c8ed5ddf5417f5a40d4b635829fc054ef130c21
parentb054bb08212e7c8c1be87f2126bf2d2196da36d5 (diff)
downloadkernel-5274cf846b822b67381e26af1512e45bbc73bf50.tar.gz
kernel-5274cf846b822b67381e26af1512e45bbc73bf50.tar.xz
kernel-5274cf846b822b67381e26af1512e45bbc73bf50.zip
zd1211rw: fix invalid signal values from device (rhbz 720093)
-rw-r--r--kernel.spec7
-rw-r--r--linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch82
2 files changed, 89 insertions, 0 deletions
diff --git a/kernel.spec b/kernel.spec
index 858dd4999..84dfff747 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -687,6 +687,8 @@ Patch12018: neuter_intel_microcode_load.patch
Patch12019: linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch
+Patch12020: linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch
+
# Runtime power management
Patch12203: linux-2.6-usb-pci-autosuspend.patch
Patch12204: linux-2.6-enable-more-pci-autosuspend.patch
@@ -1200,6 +1202,8 @@ ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch
# Networking
+ApplyPatch linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch
+
# Misc fixes
# The input layer spews crap no-one cares about.
ApplyPatch linux-2.6-input-kill-stupid-messages.patch
@@ -1881,6 +1885,9 @@ fi
%changelog
* Tue Jul 12 2011 John W. Linville <linville@redhat.com>
+- zd1211rw: fix invalid signal values from device (rhbz 720093)
+
+* Tue Jul 12 2011 John W. Linville <linville@redhat.com>
- rt2x00: Add device ID for RT539F device. (rhbz 720594)
* Tue Jul 12 2011 Kyle McMartin <kmcmartin@redhat.com> 3.0-0.rc7.git0.1
diff --git a/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch b/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch
new file mode 100644
index 000000000..f91ceb808
--- /dev/null
+++ b/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch
@@ -0,0 +1,82 @@
+commit 7a1d6564a15183cb5994656040966df09af8390f
+Author: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Date: Mon Jun 20 14:42:28 2011 +0300
+
+ zd1211rw: fix invalid signal values from device
+
+ Driver uses IEEE80211_HW_SIGNAL_UNSPEC and so signal values reported to
+ mac80211 should be in range 0..100. Sometimes device return out of range
+ values. These out of range values can then trigger warning in
+ cfg80211_inform_bss_frame.
+
+ This patch adds checks to enforce range returned from driver to
+ mac80211 be in 0..100 range.
+
+ Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ Signed-off-by: John W. Linville <linville@tuxdriver.com>
+
+diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
+index 5463ca9..9a1b013 100644
+--- a/drivers/net/wireless/zd1211rw/zd_def.h
++++ b/drivers/net/wireless/zd1211rw/zd_def.h
+@@ -37,9 +37,15 @@ typedef u16 __nocast zd_addr_t;
+ if (net_ratelimit()) \
+ dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
+ } while (0)
++# define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \
++ bool __cond = !!(cond); \
++ if (unlikely(__cond)) \
++ dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
++})
+ #else
+ # define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
+ # define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0)
++# define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0)
+ #endif /* DEBUG */
+
+ #ifdef DEBUG
+diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
+index 5037c8b..5de28bf 100644
+--- a/drivers/net/wireless/zd1211rw/zd_mac.c
++++ b/drivers/net/wireless/zd1211rw/zd_mac.c
+@@ -160,6 +160,22 @@ static int zd_reg2alpha2(u8 regdomain, char *alpha2)
+ return 1;
+ }
+
++static int zd_check_signal(struct ieee80211_hw *hw, int signal)
++{
++ struct zd_mac *mac = zd_hw_mac(hw);
++
++ dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100,
++ "%s: signal value from device not in range 0..100, "
++ "but %d.\n", __func__, signal);
++
++ if (signal < 0)
++ signal = 0;
++ else if (signal > 100)
++ signal = 100;
++
++ return signal;
++}
++
+ int zd_mac_preinit_hw(struct ieee80211_hw *hw)
+ {
+ int r;
+@@ -461,7 +477,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
+ if (i<IEEE80211_TX_MAX_RATES)
+ info->status.rates[i].idx = -1; /* terminate */
+
+- info->status.ack_signal = ackssi;
++ info->status.ack_signal = zd_check_signal(hw, ackssi);
+ ieee80211_tx_status_irqsafe(hw, skb);
+ }
+
+@@ -982,7 +998,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
+
+ stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
+ stats.band = IEEE80211_BAND_2GHZ;
+- stats.signal = status->signal_strength;
++ stats.signal = zd_check_signal(hw, status->signal_strength);
+
+ rate = zd_rx_rate(buffer, status);
+