aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2008-07-28 23:25:08 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-07-29 16:55:08 -0400
commit0ccd58fc03f40529f66190b1a41e92a732d2bda8 (patch)
tree6b1cb0b32489a2ef00f654be896744816f6a5a5c /drivers
parent1f690d7b549ef9c7424536475501885dd5b54930 (diff)
rtl8187: Improve wireless statistics for RTL8187B
Wireless statistics produced by the RTL8187B driver are not particularly informative about the strength of the received signal. From the data sheet provided by Realtek, I discovered that certain parts of the RX header should have the information necessary to calculate signal quality and strength. With testing, it became clear that most of these quantities were very jittery - only the AGC correlated with the signals expected from nearby AP's. As a result, the quality and strength are derived from the agc value. The scaling has been determined so that the numbers are close to those obtained by b43 under the same conditions. The results are qualitatively correct. Statistics derived for the RTL8187 have not been changed. The RX header variables have been renamed to match the quantites described in the Realtek data sheet. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/rtl8187.h10
-rw-r--r--drivers/net/wireless/rtl8187_dev.c78
2 files changed, 54 insertions, 34 deletions
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
index 8961901b5c0..1b0d750f662 100644
--- a/drivers/net/wireless/rtl8187.h
+++ b/drivers/net/wireless/rtl8187.h
@@ -47,11 +47,13 @@ struct rtl8187_rx_hdr {
47struct rtl8187b_rx_hdr { 47struct rtl8187b_rx_hdr {
48 __le32 flags; 48 __le32 flags;
49 __le64 mac_time; 49 __le64 mac_time;
50 u8 noise; 50 u8 sq;
51 u8 signal; 51 u8 rssi;
52 u8 agc; 52 u8 agc;
53 u8 reserved; 53 u8 flags2;
54 __le32 unused; 54 __le16 snr_long2end;
55 s8 pwdb_g12;
56 u8 fot;
55} __attribute__((packed)); 57} __attribute__((packed));
56 58
57/* {rtl8187,rtl8187b}_tx_info is in skb */ 59/* {rtl8187,rtl8187b}_tx_info is in skb */
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index 7ff03aca251..177988efd66 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -272,6 +272,7 @@ static void rtl8187_rx_cb(struct urb *urb)
272 struct ieee80211_rx_status rx_status = { 0 }; 272 struct ieee80211_rx_status rx_status = { 0 };
273 int rate, signal; 273 int rate, signal;
274 u32 flags; 274 u32 flags;
275 u32 quality;
275 276
276 spin_lock(&priv->rx_queue.lock); 277 spin_lock(&priv->rx_queue.lock);
277 if (skb->next) 278 if (skb->next)
@@ -295,44 +296,57 @@ static void rtl8187_rx_cb(struct urb *urb)
295 flags = le32_to_cpu(hdr->flags); 296 flags = le32_to_cpu(hdr->flags);
296 signal = hdr->signal & 0x7f; 297 signal = hdr->signal & 0x7f;
297 rx_status.antenna = (hdr->signal >> 7) & 1; 298 rx_status.antenna = (hdr->signal >> 7) & 1;
298 rx_status.signal = signal;
299 rx_status.noise = hdr->noise; 299 rx_status.noise = hdr->noise;
300 rx_status.mactime = le64_to_cpu(hdr->mac_time); 300 rx_status.mactime = le64_to_cpu(hdr->mac_time);
301 priv->signal = signal;
302 priv->quality = signal; 301 priv->quality = signal;
302 rx_status.qual = priv->quality;
303 priv->noise = hdr->noise; 303 priv->noise = hdr->noise;
304 rate = (flags >> 20) & 0xF;
305 if (rate > 3) { /* OFDM rate */
306 if (signal > 90)
307 signal = 90;
308 else if (signal < 25)
309 signal = 25;
310 signal = 90 - signal;
311 } else { /* CCK rate */
312 if (signal > 95)
313 signal = 95;
314 else if (signal < 30)
315 signal = 30;
316 signal = 95 - signal;
317 }
318 rx_status.signal = signal;
319 priv->signal = signal;
304 } else { 320 } else {
305 struct rtl8187b_rx_hdr *hdr = 321 struct rtl8187b_rx_hdr *hdr =
306 (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); 322 (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
323 /* The Realtek datasheet for the RTL8187B shows that the RX
324 * header contains the following quantities: signal quality,
325 * RSSI, AGC, the received power in dB, and the measured SNR.
326 * In testing, none of these quantities show qualitative
327 * agreement with AP signal strength, except for the AGC,
328 * which is inversely proportional to the strength of the
329 * signal. In the following, the quality and signal strength
330 * are derived from the AGC. The arbitrary scaling constants
331 * are chosen to make the results close to the values obtained
332 * for a BCM4312 using b43 as the driver. The noise is ignored
333 * for now.
334 */
307 flags = le32_to_cpu(hdr->flags); 335 flags = le32_to_cpu(hdr->flags);
308 signal = hdr->agc >> 1; 336 quality = 170 - hdr->agc;
309 rx_status.antenna = (hdr->signal >> 7) & 1; 337 if (quality > 100)
310 rx_status.signal = 64 - min(hdr->noise, (u8)64); 338 quality = 100;
311 rx_status.noise = hdr->noise; 339 signal = 14 - hdr->agc / 2;
340 rx_status.qual = quality;
341 priv->quality = quality;
342 rx_status.signal = signal;
343 priv->signal = signal;
344 rx_status.antenna = (hdr->rssi >> 7) & 1;
312 rx_status.mactime = le64_to_cpu(hdr->mac_time); 345 rx_status.mactime = le64_to_cpu(hdr->mac_time);
313 priv->signal = hdr->signal; 346 rate = (flags >> 20) & 0xF;
314 priv->quality = hdr->agc >> 1;
315 priv->noise = hdr->noise;
316 } 347 }
317 348
318 skb_trim(skb, flags & 0x0FFF); 349 skb_trim(skb, flags & 0x0FFF);
319 rate = (flags >> 20) & 0xF;
320 if (rate > 3) { /* OFDM rate */
321 if (signal > 90)
322 signal = 90;
323 else if (signal < 25)
324 signal = 25;
325 signal = 90 - signal;
326 } else { /* CCK rate */
327 if (signal > 95)
328 signal = 95;
329 else if (signal < 30)
330 signal = 30;
331 signal = 95 - signal;
332 }
333
334 rx_status.qual = priv->quality;
335 rx_status.signal = signal;
336 rx_status.rate_idx = rate; 350 rx_status.rate_idx = rate;
337 rx_status.freq = dev->conf.channel->center_freq; 351 rx_status.freq = dev->conf.channel->center_freq;
338 rx_status.band = dev->conf.channel->band; 352 rx_status.band = dev->conf.channel->band;
@@ -1030,9 +1044,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
1030 1044
1031 priv->mode = IEEE80211_IF_TYPE_MNTR; 1045 priv->mode = IEEE80211_IF_TYPE_MNTR;
1032 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | 1046 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
1033 IEEE80211_HW_RX_INCLUDES_FCS | 1047 IEEE80211_HW_RX_INCLUDES_FCS;
1034 IEEE80211_HW_SIGNAL_UNSPEC;
1035 dev->max_signal = 65;
1036 1048
1037 eeprom.data = dev; 1049 eeprom.data = dev;
1038 eeprom.register_read = rtl8187_eeprom_register_read; 1050 eeprom.register_read = rtl8187_eeprom_register_read;
@@ -1147,10 +1159,16 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
1147 (*channel++).hw_value = txpwr >> 8; 1159 (*channel++).hw_value = txpwr >> 8;
1148 } 1160 }
1149 1161
1150 if (priv->is_rtl8187b) 1162 if (priv->is_rtl8187b) {
1151 printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " 1163 printk(KERN_WARNING "rtl8187: 8187B chip detected. Support "
1152 "is EXPERIMENTAL, and could damage your\n" 1164 "is EXPERIMENTAL, and could damage your\n"
1153 " hardware, use at your own risk\n"); 1165 " hardware, use at your own risk\n");
1166 dev->flags |= IEEE80211_HW_SIGNAL_DBM;
1167 } else {
1168 dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC;
1169 dev->max_signal = 65;
1170 }
1171
1154 if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) 1172 if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
1155 printk(KERN_INFO "rtl8187: inconsistency between id with OEM" 1173 printk(KERN_INFO "rtl8187: inconsistency between id with OEM"
1156 " info!\n"); 1174 " info!\n");