diff options
Diffstat (limited to 'drivers/net/wireless/rtl818x/rtl8187_dev.c')
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8187_dev.c | 53 |
1 files changed, 31 insertions, 22 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 2017ccc00145..1d30792973f5 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/usb.h> | 24 | #include <linux/usb.h> |
25 | #include <linux/slab.h> | ||
25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
26 | #include <linux/etherdevice.h> | 27 | #include <linux/etherdevice.h> |
27 | #include <linux/eeprom_93cx6.h> | 28 | #include <linux/eeprom_93cx6.h> |
@@ -65,6 +66,7 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { | |||
65 | /* Sitecom */ | 66 | /* Sitecom */ |
66 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, | 67 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, |
67 | {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, | 68 | {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, |
69 | {USB_DEVICE(0x0df6, 0x0029), .driver_info = DEVICE_RTL8187B}, | ||
68 | /* Sphairon Access Systems GmbH */ | 70 | /* Sphairon Access Systems GmbH */ |
69 | {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, | 71 | {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, |
70 | /* Dick Smith Electronics */ | 72 | /* Dick Smith Electronics */ |
@@ -320,7 +322,6 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
320 | struct ieee80211_rx_status rx_status = { 0 }; | 322 | struct ieee80211_rx_status rx_status = { 0 }; |
321 | int rate, signal; | 323 | int rate, signal; |
322 | u32 flags; | 324 | u32 flags; |
323 | u32 quality; | ||
324 | unsigned long f; | 325 | unsigned long f; |
325 | 326 | ||
326 | spin_lock_irqsave(&priv->rx_queue.lock, f); | 327 | spin_lock_irqsave(&priv->rx_queue.lock, f); |
@@ -338,10 +339,9 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
338 | (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); | 339 | (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); |
339 | flags = le32_to_cpu(hdr->flags); | 340 | flags = le32_to_cpu(hdr->flags); |
340 | /* As with the RTL8187B below, the AGC is used to calculate | 341 | /* As with the RTL8187B below, the AGC is used to calculate |
341 | * signal strength and quality. In this case, the scaling | 342 | * signal strength. In this case, the scaling |
342 | * constants are derived from the output of p54usb. | 343 | * constants are derived from the output of p54usb. |
343 | */ | 344 | */ |
344 | quality = 130 - ((41 * hdr->agc) >> 6); | ||
345 | signal = -4 - ((27 * hdr->agc) >> 6); | 345 | signal = -4 - ((27 * hdr->agc) >> 6); |
346 | rx_status.antenna = (hdr->signal >> 7) & 1; | 346 | rx_status.antenna = (hdr->signal >> 7) & 1; |
347 | rx_status.mactime = le64_to_cpu(hdr->mac_time); | 347 | rx_status.mactime = le64_to_cpu(hdr->mac_time); |
@@ -354,23 +354,18 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
354 | * In testing, none of these quantities show qualitative | 354 | * In testing, none of these quantities show qualitative |
355 | * agreement with AP signal strength, except for the AGC, | 355 | * agreement with AP signal strength, except for the AGC, |
356 | * which is inversely proportional to the strength of the | 356 | * which is inversely proportional to the strength of the |
357 | * signal. In the following, the quality and signal strength | 357 | * signal. In the following, the signal strength |
358 | * are derived from the AGC. The arbitrary scaling constants | 358 | * is derived from the AGC. The arbitrary scaling constants |
359 | * are chosen to make the results close to the values obtained | 359 | * are chosen to make the results close to the values obtained |
360 | * for a BCM4312 using b43 as the driver. The noise is ignored | 360 | * for a BCM4312 using b43 as the driver. The noise is ignored |
361 | * for now. | 361 | * for now. |
362 | */ | 362 | */ |
363 | flags = le32_to_cpu(hdr->flags); | 363 | flags = le32_to_cpu(hdr->flags); |
364 | quality = 170 - hdr->agc; | ||
365 | signal = 14 - hdr->agc / 2; | 364 | signal = 14 - hdr->agc / 2; |
366 | rx_status.antenna = (hdr->rssi >> 7) & 1; | 365 | rx_status.antenna = (hdr->rssi >> 7) & 1; |
367 | rx_status.mactime = le64_to_cpu(hdr->mac_time); | 366 | rx_status.mactime = le64_to_cpu(hdr->mac_time); |
368 | } | 367 | } |
369 | 368 | ||
370 | if (quality > 100) | ||
371 | quality = 100; | ||
372 | rx_status.qual = quality; | ||
373 | priv->quality = quality; | ||
374 | rx_status.signal = signal; | 369 | rx_status.signal = signal; |
375 | priv->signal = signal; | 370 | priv->signal = signal; |
376 | rate = (flags >> 20) & 0xF; | 371 | rate = (flags >> 20) & 0xF; |
@@ -1025,31 +1020,30 @@ static void rtl8187_stop(struct ieee80211_hw *dev) | |||
1025 | } | 1020 | } |
1026 | 1021 | ||
1027 | static int rtl8187_add_interface(struct ieee80211_hw *dev, | 1022 | static int rtl8187_add_interface(struct ieee80211_hw *dev, |
1028 | struct ieee80211_if_init_conf *conf) | 1023 | struct ieee80211_vif *vif) |
1029 | { | 1024 | { |
1030 | struct rtl8187_priv *priv = dev->priv; | 1025 | struct rtl8187_priv *priv = dev->priv; |
1031 | int i; | 1026 | int i; |
1032 | int ret = -EOPNOTSUPP; | 1027 | int ret = -EOPNOTSUPP; |
1033 | 1028 | ||
1034 | mutex_lock(&priv->conf_mutex); | 1029 | mutex_lock(&priv->conf_mutex); |
1035 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 1030 | if (priv->vif) |
1036 | goto exit; | 1031 | goto exit; |
1037 | 1032 | ||
1038 | switch (conf->type) { | 1033 | switch (vif->type) { |
1039 | case NL80211_IFTYPE_STATION: | 1034 | case NL80211_IFTYPE_STATION: |
1040 | priv->mode = conf->type; | ||
1041 | break; | 1035 | break; |
1042 | default: | 1036 | default: |
1043 | goto exit; | 1037 | goto exit; |
1044 | } | 1038 | } |
1045 | 1039 | ||
1046 | ret = 0; | 1040 | ret = 0; |
1047 | priv->vif = conf->vif; | 1041 | priv->vif = vif; |
1048 | 1042 | ||
1049 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 1043 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
1050 | for (i = 0; i < ETH_ALEN; i++) | 1044 | for (i = 0; i < ETH_ALEN; i++) |
1051 | rtl818x_iowrite8(priv, &priv->map->MAC[i], | 1045 | rtl818x_iowrite8(priv, &priv->map->MAC[i], |
1052 | ((u8 *)conf->mac_addr)[i]); | 1046 | ((u8 *)vif->addr)[i]); |
1053 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 1047 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
1054 | 1048 | ||
1055 | exit: | 1049 | exit: |
@@ -1058,11 +1052,10 @@ exit: | |||
1058 | } | 1052 | } |
1059 | 1053 | ||
1060 | static void rtl8187_remove_interface(struct ieee80211_hw *dev, | 1054 | static void rtl8187_remove_interface(struct ieee80211_hw *dev, |
1061 | struct ieee80211_if_init_conf *conf) | 1055 | struct ieee80211_vif *vif) |
1062 | { | 1056 | { |
1063 | struct rtl8187_priv *priv = dev->priv; | 1057 | struct rtl8187_priv *priv = dev->priv; |
1064 | mutex_lock(&priv->conf_mutex); | 1058 | mutex_lock(&priv->conf_mutex); |
1065 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
1066 | priv->vif = NULL; | 1059 | priv->vif = NULL; |
1067 | mutex_unlock(&priv->conf_mutex); | 1060 | mutex_unlock(&priv->conf_mutex); |
1068 | } | 1061 | } |
@@ -1274,6 +1267,14 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue, | |||
1274 | return 0; | 1267 | return 0; |
1275 | } | 1268 | } |
1276 | 1269 | ||
1270 | static u64 rtl8187_get_tsf(struct ieee80211_hw *dev) | ||
1271 | { | ||
1272 | struct rtl8187_priv *priv = dev->priv; | ||
1273 | |||
1274 | return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | | ||
1275 | (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; | ||
1276 | } | ||
1277 | |||
1277 | static const struct ieee80211_ops rtl8187_ops = { | 1278 | static const struct ieee80211_ops rtl8187_ops = { |
1278 | .tx = rtl8187_tx, | 1279 | .tx = rtl8187_tx, |
1279 | .start = rtl8187_start, | 1280 | .start = rtl8187_start, |
@@ -1285,7 +1286,8 @@ static const struct ieee80211_ops rtl8187_ops = { | |||
1285 | .prepare_multicast = rtl8187_prepare_multicast, | 1286 | .prepare_multicast = rtl8187_prepare_multicast, |
1286 | .configure_filter = rtl8187_configure_filter, | 1287 | .configure_filter = rtl8187_configure_filter, |
1287 | .conf_tx = rtl8187_conf_tx, | 1288 | .conf_tx = rtl8187_conf_tx, |
1288 | .rfkill_poll = rtl8187_rfkill_poll | 1289 | .rfkill_poll = rtl8187_rfkill_poll, |
1290 | .get_tsf = rtl8187_get_tsf, | ||
1289 | }; | 1291 | }; |
1290 | 1292 | ||
1291 | static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 1293 | static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) |
@@ -1329,6 +1331,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1329 | struct ieee80211_channel *channel; | 1331 | struct ieee80211_channel *channel; |
1330 | const char *chip_name; | 1332 | const char *chip_name; |
1331 | u16 txpwr, reg; | 1333 | u16 txpwr, reg; |
1334 | u16 product_id = le16_to_cpu(udev->descriptor.idProduct); | ||
1332 | int err, i; | 1335 | int err, i; |
1333 | 1336 | ||
1334 | dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); | 1337 | dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); |
@@ -1371,7 +1374,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1371 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; | 1374 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; |
1372 | 1375 | ||
1373 | 1376 | ||
1374 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
1375 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 1377 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
1376 | IEEE80211_HW_SIGNAL_DBM | | 1378 | IEEE80211_HW_SIGNAL_DBM | |
1377 | IEEE80211_HW_RX_INCLUDES_FCS; | 1379 | IEEE80211_HW_RX_INCLUDES_FCS; |
@@ -1488,6 +1490,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1488 | (*channel++).hw_value = txpwr & 0xFF; | 1490 | (*channel++).hw_value = txpwr & 0xFF; |
1489 | (*channel++).hw_value = txpwr >> 8; | 1491 | (*channel++).hw_value = txpwr >> 8; |
1490 | } | 1492 | } |
1493 | /* Handle the differing rfkill GPIO bit in different models */ | ||
1494 | priv->rfkill_mask = RFKILL_MASK_8187_89_97; | ||
1495 | if (product_id == 0x8197 || product_id == 0x8198) { | ||
1496 | eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_SELECT_GPIO, ®); | ||
1497 | if (reg & 0xFF00) | ||
1498 | priv->rfkill_mask = RFKILL_MASK_8198; | ||
1499 | } | ||
1491 | 1500 | ||
1492 | /* | 1501 | /* |
1493 | * XXX: Once this driver supports anything that requires | 1502 | * XXX: Once this driver supports anything that requires |
@@ -1516,9 +1525,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1516 | mutex_init(&priv->conf_mutex); | 1525 | mutex_init(&priv->conf_mutex); |
1517 | skb_queue_head_init(&priv->b_tx_status.queue); | 1526 | skb_queue_head_init(&priv->b_tx_status.queue); |
1518 | 1527 | ||
1519 | printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n", | 1528 | printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n", |
1520 | wiphy_name(dev->wiphy), dev->wiphy->perm_addr, | 1529 | wiphy_name(dev->wiphy), dev->wiphy->perm_addr, |
1521 | chip_name, priv->asic_rev, priv->rf->name); | 1530 | chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask); |
1522 | 1531 | ||
1523 | #ifdef CONFIG_RTL8187_LEDS | 1532 | #ifdef CONFIG_RTL8187_LEDS |
1524 | eeprom_93cx6_read(&eeprom, 0x3F, ®); | 1533 | eeprom_93cx6_read(&eeprom, 0x3F, ®); |