aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 8961901b5c04..1b0d750f6623 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 7ff03aca2518..177988efd660 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");