aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtl8187_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rtl8187_dev.c')
-rw-r--r--drivers/net/wireless/rtl8187_dev.c93
1 files changed, 63 insertions, 30 deletions
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index d3067b1216ca..177988efd660 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -169,6 +169,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
169{ 169{
170 struct rtl8187_priv *priv = dev->priv; 170 struct rtl8187_priv *priv = dev->priv;
171 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 171 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
172 struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
172 unsigned int ep; 173 unsigned int ep;
173 void *buf; 174 void *buf;
174 struct urb *urb; 175 struct urb *urb;
@@ -234,6 +235,20 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
234 ep = epmap[skb_get_queue_mapping(skb)]; 235 ep = epmap[skb_get_queue_mapping(skb)];
235 } 236 }
236 237
238 /* FIXME: The sequence that follows is needed for this driver to
239 * work with mac80211 since "mac80211: fix TX sequence numbers".
240 * As with the temporary code in rt2x00, changes will be needed
241 * to get proper sequence numbers on beacons. In addition, this
242 * patch places the sequence number in the hardware state, which
243 * limits us to a single virtual state.
244 */
245 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
246 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
247 priv->seqno += 0x10;
248 ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
249 ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno);
250 }
251
237 info->driver_data[0] = dev; 252 info->driver_data[0] = dev;
238 info->driver_data[1] = urb; 253 info->driver_data[1] = urb;
239 254
@@ -257,6 +272,7 @@ static void rtl8187_rx_cb(struct urb *urb)
257 struct ieee80211_rx_status rx_status = { 0 }; 272 struct ieee80211_rx_status rx_status = { 0 };
258 int rate, signal; 273 int rate, signal;
259 u32 flags; 274 u32 flags;
275 u32 quality;
260 276
261 spin_lock(&priv->rx_queue.lock); 277 spin_lock(&priv->rx_queue.lock);
262 if (skb->next) 278 if (skb->next)
@@ -280,44 +296,57 @@ static void rtl8187_rx_cb(struct urb *urb)
280 flags = le32_to_cpu(hdr->flags); 296 flags = le32_to_cpu(hdr->flags);
281 signal = hdr->signal & 0x7f; 297 signal = hdr->signal & 0x7f;
282 rx_status.antenna = (hdr->signal >> 7) & 1; 298 rx_status.antenna = (hdr->signal >> 7) & 1;
283 rx_status.signal = signal;
284 rx_status.noise = hdr->noise; 299 rx_status.noise = hdr->noise;
285 rx_status.mactime = le64_to_cpu(hdr->mac_time); 300 rx_status.mactime = le64_to_cpu(hdr->mac_time);
286 priv->signal = signal;
287 priv->quality = signal; 301 priv->quality = signal;
302 rx_status.qual = priv->quality;
288 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;
289 } else { 320 } else {
290 struct rtl8187b_rx_hdr *hdr = 321 struct rtl8187b_rx_hdr *hdr =
291 (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 */
292 flags = le32_to_cpu(hdr->flags); 335 flags = le32_to_cpu(hdr->flags);
293 signal = hdr->agc >> 1; 336 quality = 170 - hdr->agc;
294 rx_status.antenna = (hdr->signal >> 7) & 1; 337 if (quality > 100)
295 rx_status.signal = 64 - min(hdr->noise, (u8)64); 338 quality = 100;
296 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;
297 rx_status.mactime = le64_to_cpu(hdr->mac_time); 345 rx_status.mactime = le64_to_cpu(hdr->mac_time);
298 priv->signal = hdr->signal; 346 rate = (flags >> 20) & 0xF;
299 priv->quality = hdr->agc >> 1;
300 priv->noise = hdr->noise;
301 } 347 }
302 348
303 skb_trim(skb, flags & 0x0FFF); 349 skb_trim(skb, flags & 0x0FFF);
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
319 rx_status.qual = priv->quality;
320 rx_status.signal = signal;
321 rx_status.rate_idx = rate; 350 rx_status.rate_idx = rate;
322 rx_status.freq = dev->conf.channel->center_freq; 351 rx_status.freq = dev->conf.channel->center_freq;
323 rx_status.band = dev->conf.channel->band; 352 rx_status.band = dev->conf.channel->band;
@@ -1015,9 +1044,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
1015 1044
1016 priv->mode = IEEE80211_IF_TYPE_MNTR; 1045 priv->mode = IEEE80211_IF_TYPE_MNTR;
1017 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | 1046 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
1018 IEEE80211_HW_RX_INCLUDES_FCS | 1047 IEEE80211_HW_RX_INCLUDES_FCS;
1019 IEEE80211_HW_SIGNAL_UNSPEC;
1020 dev->max_signal = 65;
1021 1048
1022 eeprom.data = dev; 1049 eeprom.data = dev;
1023 eeprom.register_read = rtl8187_eeprom_register_read; 1050 eeprom.register_read = rtl8187_eeprom_register_read;
@@ -1132,10 +1159,16 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
1132 (*channel++).hw_value = txpwr >> 8; 1159 (*channel++).hw_value = txpwr >> 8;
1133 } 1160 }
1134 1161
1135 if (priv->is_rtl8187b) 1162 if (priv->is_rtl8187b) {
1136 printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " 1163 printk(KERN_WARNING "rtl8187: 8187B chip detected. Support "
1137 "is EXPERIMENTAL, and could damage your\n" 1164 "is EXPERIMENTAL, and could damage your\n"
1138 " 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
1139 if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) 1172 if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
1140 printk(KERN_INFO "rtl8187: inconsistency between id with OEM" 1173 printk(KERN_INFO "rtl8187: inconsistency between id with OEM"
1141 " info!\n"); 1174 " info!\n");