diff options
Diffstat (limited to 'drivers/net/wireless/rtl8187_dev.c')
-rw-r--r-- | drivers/net/wireless/rtl8187_dev.c | 93 |
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"); |