diff options
Diffstat (limited to 'drivers/net/wireless/rtl818x')
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8180.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8180_dev.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8187.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8187_dev.c | 53 | ||||
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8187_leds.c | 74 | ||||
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8187_leds.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8187_rfkill.c | 4 |
7 files changed, 116 insertions, 70 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h index 8721282a8185..de3844fe06d8 100644 --- a/drivers/net/wireless/rtl818x/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180.h | |||
@@ -60,7 +60,6 @@ struct rtl8180_priv { | |||
60 | struct rtl818x_csr __iomem *map; | 60 | struct rtl818x_csr __iomem *map; |
61 | const struct rtl818x_rf_ops *rf; | 61 | const struct rtl818x_rf_ops *rf; |
62 | struct ieee80211_vif *vif; | 62 | struct ieee80211_vif *vif; |
63 | int mode; | ||
64 | 63 | ||
65 | /* rtl8180 driver specific */ | 64 | /* rtl8180 driver specific */ |
66 | spinlock_t lock; | 65 | spinlock_t lock; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 16429c49139c..2131a442831a 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
20 | #include <linux/slab.h> | ||
20 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
21 | #include <linux/etherdevice.h> | 22 | #include <linux/etherdevice.h> |
22 | #include <linux/eeprom_93cx6.h> | 23 | #include <linux/eeprom_93cx6.h> |
@@ -33,7 +34,7 @@ MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); | |||
33 | MODULE_DESCRIPTION("RTL8180 / RTL8185 PCI wireless driver"); | 34 | MODULE_DESCRIPTION("RTL8180 / RTL8185 PCI wireless driver"); |
34 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
35 | 36 | ||
36 | static struct pci_device_id rtl8180_table[] __devinitdata = { | 37 | static DEFINE_PCI_DEVICE_TABLE(rtl8180_table) = { |
37 | /* rtl8185 */ | 38 | /* rtl8185 */ |
38 | { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) }, | 39 | { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) }, |
39 | { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) }, | 40 | { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) }, |
@@ -82,8 +83,6 @@ static const struct ieee80211_channel rtl818x_channels[] = { | |||
82 | }; | 83 | }; |
83 | 84 | ||
84 | 85 | ||
85 | |||
86 | |||
87 | void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) | 86 | void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) |
88 | { | 87 | { |
89 | struct rtl8180_priv *priv = dev->priv; | 88 | struct rtl8180_priv *priv = dev->priv; |
@@ -132,7 +131,6 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
132 | 131 | ||
133 | rx_status.antenna = (flags2 >> 15) & 1; | 132 | rx_status.antenna = (flags2 >> 15) & 1; |
134 | /* TODO: improve signal/rssi reporting */ | 133 | /* TODO: improve signal/rssi reporting */ |
135 | rx_status.qual = flags2 & 0xFF; | ||
136 | rx_status.signal = (flags2 >> 8) & 0x7F; | 134 | rx_status.signal = (flags2 >> 8) & 0x7F; |
137 | /* XXX: is this correct? */ | 135 | /* XXX: is this correct? */ |
138 | rx_status.rate_idx = (flags >> 20) & 0xF; | 136 | rx_status.rate_idx = (flags >> 20) & 0xF; |
@@ -548,7 +546,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) | |||
548 | rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma); | 546 | rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma); |
549 | rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma); | 547 | rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma); |
550 | 548 | ||
551 | ret = request_irq(priv->pdev->irq, &rtl8180_interrupt, | 549 | ret = request_irq(priv->pdev->irq, rtl8180_interrupt, |
552 | IRQF_SHARED, KBUILD_MODNAME, dev); | 550 | IRQF_SHARED, KBUILD_MODNAME, dev); |
553 | if (ret) { | 551 | if (ret) { |
554 | printk(KERN_ERR "%s: failed to register IRQ handler\n", | 552 | printk(KERN_ERR "%s: failed to register IRQ handler\n", |
@@ -616,7 +614,6 @@ static int rtl8180_start(struct ieee80211_hw *dev) | |||
616 | reg |= RTL818X_CMD_TX_ENABLE; | 614 | reg |= RTL818X_CMD_TX_ENABLE; |
617 | rtl818x_iowrite8(priv, &priv->map->CMD, reg); | 615 | rtl818x_iowrite8(priv, &priv->map->CMD, reg); |
618 | 616 | ||
619 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
620 | return 0; | 617 | return 0; |
621 | 618 | ||
622 | err_free_rings: | 619 | err_free_rings: |
@@ -634,8 +631,6 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
634 | u8 reg; | 631 | u8 reg; |
635 | int i; | 632 | int i; |
636 | 633 | ||
637 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | ||
638 | |||
639 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); | 634 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); |
640 | 635 | ||
641 | reg = rtl818x_ioread8(priv, &priv->map->CMD); | 636 | reg = rtl818x_ioread8(priv, &priv->map->CMD); |
@@ -658,38 +653,39 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
658 | } | 653 | } |
659 | 654 | ||
660 | static int rtl8180_add_interface(struct ieee80211_hw *dev, | 655 | static int rtl8180_add_interface(struct ieee80211_hw *dev, |
661 | struct ieee80211_if_init_conf *conf) | 656 | struct ieee80211_vif *vif) |
662 | { | 657 | { |
663 | struct rtl8180_priv *priv = dev->priv; | 658 | struct rtl8180_priv *priv = dev->priv; |
664 | 659 | ||
665 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 660 | /* |
666 | return -EOPNOTSUPP; | 661 | * We only support one active interface at a time. |
662 | */ | ||
663 | if (priv->vif) | ||
664 | return -EBUSY; | ||
667 | 665 | ||
668 | switch (conf->type) { | 666 | switch (vif->type) { |
669 | case NL80211_IFTYPE_STATION: | 667 | case NL80211_IFTYPE_STATION: |
670 | priv->mode = conf->type; | ||
671 | break; | 668 | break; |
672 | default: | 669 | default: |
673 | return -EOPNOTSUPP; | 670 | return -EOPNOTSUPP; |
674 | } | 671 | } |
675 | 672 | ||
676 | priv->vif = conf->vif; | 673 | priv->vif = vif; |
677 | 674 | ||
678 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 675 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
679 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], | 676 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], |
680 | le32_to_cpu(*(__le32 *)conf->mac_addr)); | 677 | le32_to_cpu(*(__le32 *)vif->addr)); |
681 | rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], | 678 | rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], |
682 | le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); | 679 | le16_to_cpu(*(__le16 *)(vif->addr + 4))); |
683 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 680 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
684 | 681 | ||
685 | return 0; | 682 | return 0; |
686 | } | 683 | } |
687 | 684 | ||
688 | static void rtl8180_remove_interface(struct ieee80211_hw *dev, | 685 | static void rtl8180_remove_interface(struct ieee80211_hw *dev, |
689 | struct ieee80211_if_init_conf *conf) | 686 | struct ieee80211_vif *vif) |
690 | { | 687 | { |
691 | struct rtl8180_priv *priv = dev->priv; | 688 | struct rtl8180_priv *priv = dev->priv; |
692 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
693 | priv->vif = NULL; | 689 | priv->vif = NULL; |
694 | } | 690 | } |
695 | 691 | ||
@@ -766,6 +762,14 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev, | |||
766 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); | 762 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); |
767 | } | 763 | } |
768 | 764 | ||
765 | static u64 rtl8180_get_tsf(struct ieee80211_hw *dev) | ||
766 | { | ||
767 | struct rtl8180_priv *priv = dev->priv; | ||
768 | |||
769 | return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | | ||
770 | (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; | ||
771 | } | ||
772 | |||
769 | static const struct ieee80211_ops rtl8180_ops = { | 773 | static const struct ieee80211_ops rtl8180_ops = { |
770 | .tx = rtl8180_tx, | 774 | .tx = rtl8180_tx, |
771 | .start = rtl8180_start, | 775 | .start = rtl8180_start, |
@@ -776,6 +780,7 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
776 | .bss_info_changed = rtl8180_bss_info_changed, | 780 | .bss_info_changed = rtl8180_bss_info_changed, |
777 | .prepare_multicast = rtl8180_prepare_multicast, | 781 | .prepare_multicast = rtl8180_prepare_multicast, |
778 | .configure_filter = rtl8180_configure_filter, | 782 | .configure_filter = rtl8180_configure_filter, |
783 | .get_tsf = rtl8180_get_tsf, | ||
779 | }; | 784 | }; |
780 | 785 | ||
781 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 786 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) |
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index bf9175a8c1f4..6bb32112e65c 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */ | 23 | #define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */ |
24 | #define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */ | 24 | #define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */ |
25 | #define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */ | 25 | #define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */ |
26 | #define RTL8187_EEPROM_SELECT_GPIO 0x3B | ||
26 | 27 | ||
27 | #define RTL8187_REQT_READ 0xC0 | 28 | #define RTL8187_REQT_READ 0xC0 |
28 | #define RTL8187_REQT_WRITE 0x40 | 29 | #define RTL8187_REQT_WRITE 0x40 |
@@ -31,6 +32,9 @@ | |||
31 | 32 | ||
32 | #define RTL8187_MAX_RX 0x9C4 | 33 | #define RTL8187_MAX_RX 0x9C4 |
33 | 34 | ||
35 | #define RFKILL_MASK_8187_89_97 0x2 | ||
36 | #define RFKILL_MASK_8198 0x4 | ||
37 | |||
34 | struct rtl8187_rx_info { | 38 | struct rtl8187_rx_info { |
35 | struct urb *urb; | 39 | struct urb *urb; |
36 | struct ieee80211_hw *dev; | 40 | struct ieee80211_hw *dev; |
@@ -88,7 +92,7 @@ struct rtl8187_priv { | |||
88 | struct rtl818x_csr *map; | 92 | struct rtl818x_csr *map; |
89 | const struct rtl818x_rf_ops *rf; | 93 | const struct rtl818x_rf_ops *rf; |
90 | struct ieee80211_vif *vif; | 94 | struct ieee80211_vif *vif; |
91 | int mode; | 95 | |
92 | /* The mutex protects the TX loopback state. | 96 | /* The mutex protects the TX loopback state. |
93 | * Any attempt to set channels concurrently locks the device. | 97 | * Any attempt to set channels concurrently locks the device. |
94 | */ | 98 | */ |
@@ -104,6 +108,7 @@ struct rtl8187_priv { | |||
104 | struct delayed_work work; | 108 | struct delayed_work work; |
105 | struct ieee80211_hw *dev; | 109 | struct ieee80211_hw *dev; |
106 | #ifdef CONFIG_RTL8187_LEDS | 110 | #ifdef CONFIG_RTL8187_LEDS |
111 | struct rtl8187_led led_radio; | ||
107 | struct rtl8187_led led_tx; | 112 | struct rtl8187_led led_tx; |
108 | struct rtl8187_led led_rx; | 113 | struct rtl8187_led led_rx; |
109 | struct delayed_work led_on; | 114 | struct delayed_work led_on; |
@@ -119,10 +124,10 @@ struct rtl8187_priv { | |||
119 | } hw_rev; | 124 | } hw_rev; |
120 | struct sk_buff_head rx_queue; | 125 | struct sk_buff_head rx_queue; |
121 | u8 signal; | 126 | u8 signal; |
122 | u8 quality; | ||
123 | u8 noise; | 127 | u8 noise; |
124 | u8 slot_time; | 128 | u8 slot_time; |
125 | u8 aifsn[4]; | 129 | u8 aifsn[4]; |
130 | u8 rfkill_mask; | ||
126 | struct { | 131 | struct { |
127 | __le64 buf; | 132 | __le64 buf; |
128 | struct sk_buff_head queue; | 133 | struct sk_buff_head queue; |
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, ®); |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c index cf8a4a40fdf6..4637337d5ce6 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c | |||
@@ -33,7 +33,7 @@ static void led_turn_on(struct work_struct *work) | |||
33 | struct rtl8187_led *led = &priv->led_tx; | 33 | struct rtl8187_led *led = &priv->led_tx; |
34 | 34 | ||
35 | /* Don't change the LED, when the device is down. */ | 35 | /* Don't change the LED, when the device is down. */ |
36 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | 36 | if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) |
37 | return ; | 37 | return ; |
38 | 38 | ||
39 | /* Skip if the LED is not registered. */ | 39 | /* Skip if the LED is not registered. */ |
@@ -71,7 +71,7 @@ static void led_turn_off(struct work_struct *work) | |||
71 | struct rtl8187_led *led = &priv->led_tx; | 71 | struct rtl8187_led *led = &priv->led_tx; |
72 | 72 | ||
73 | /* Don't change the LED, when the device is down. */ | 73 | /* Don't change the LED, when the device is down. */ |
74 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | 74 | if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) |
75 | return ; | 75 | return ; |
76 | 76 | ||
77 | /* Skip if the LED is not registered. */ | 77 | /* Skip if the LED is not registered. */ |
@@ -105,19 +105,36 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, | |||
105 | struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led, | 105 | struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led, |
106 | led_dev); | 106 | led_dev); |
107 | struct ieee80211_hw *hw = led->dev; | 107 | struct ieee80211_hw *hw = led->dev; |
108 | struct rtl8187_priv *priv = hw->priv; | 108 | struct rtl8187_priv *priv; |
109 | static bool radio_on; | ||
109 | 110 | ||
110 | if (brightness == LED_OFF) { | 111 | if (!hw) |
111 | ieee80211_queue_delayed_work(hw, &priv->led_off, 0); | 112 | return; |
112 | /* The LED is off for 1/20 sec so that it just blinks. */ | 113 | priv = hw->priv; |
113 | ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20); | 114 | if (led->is_radio) { |
114 | } else | 115 | if (brightness == LED_FULL) { |
115 | ieee80211_queue_delayed_work(hw, &priv->led_on, 0); | 116 | ieee80211_queue_delayed_work(hw, &priv->led_on, 0); |
117 | radio_on = true; | ||
118 | } else if (radio_on) { | ||
119 | radio_on = false; | ||
120 | cancel_delayed_work_sync(&priv->led_on); | ||
121 | ieee80211_queue_delayed_work(hw, &priv->led_off, 0); | ||
122 | } | ||
123 | } else if (radio_on) { | ||
124 | if (brightness == LED_OFF) { | ||
125 | ieee80211_queue_delayed_work(hw, &priv->led_off, 0); | ||
126 | /* The LED is off for 1/20 sec - it just blinks. */ | ||
127 | ieee80211_queue_delayed_work(hw, &priv->led_on, | ||
128 | HZ / 20); | ||
129 | } else | ||
130 | ieee80211_queue_delayed_work(hw, &priv->led_on, 0); | ||
131 | } | ||
116 | } | 132 | } |
117 | 133 | ||
118 | static int rtl8187_register_led(struct ieee80211_hw *dev, | 134 | static int rtl8187_register_led(struct ieee80211_hw *dev, |
119 | struct rtl8187_led *led, const char *name, | 135 | struct rtl8187_led *led, const char *name, |
120 | const char *default_trigger, u8 ledpin) | 136 | const char *default_trigger, u8 ledpin, |
137 | bool is_radio) | ||
121 | { | 138 | { |
122 | int err; | 139 | int err; |
123 | struct rtl8187_priv *priv = dev->priv; | 140 | struct rtl8187_priv *priv = dev->priv; |
@@ -128,6 +145,7 @@ static int rtl8187_register_led(struct ieee80211_hw *dev, | |||
128 | return -EINVAL; | 145 | return -EINVAL; |
129 | led->dev = dev; | 146 | led->dev = dev; |
130 | led->ledpin = ledpin; | 147 | led->ledpin = ledpin; |
148 | led->is_radio = is_radio; | ||
131 | strncpy(led->name, name, sizeof(led->name)); | 149 | strncpy(led->name, name, sizeof(led->name)); |
132 | 150 | ||
133 | led->led_dev.name = led->name; | 151 | led->led_dev.name = led->name; |
@@ -145,7 +163,11 @@ static int rtl8187_register_led(struct ieee80211_hw *dev, | |||
145 | 163 | ||
146 | static void rtl8187_unregister_led(struct rtl8187_led *led) | 164 | static void rtl8187_unregister_led(struct rtl8187_led *led) |
147 | { | 165 | { |
166 | struct ieee80211_hw *hw = led->dev; | ||
167 | struct rtl8187_priv *priv = hw->priv; | ||
168 | |||
148 | led_classdev_unregister(&led->led_dev); | 169 | led_classdev_unregister(&led->led_dev); |
170 | flush_delayed_work(&priv->led_off); | ||
149 | led->dev = NULL; | 171 | led->dev = NULL; |
150 | } | 172 | } |
151 | 173 | ||
@@ -183,37 +205,41 @@ void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid) | |||
183 | INIT_DELAYED_WORK(&priv->led_off, led_turn_off); | 205 | INIT_DELAYED_WORK(&priv->led_off, led_turn_off); |
184 | 206 | ||
185 | snprintf(name, sizeof(name), | 207 | snprintf(name, sizeof(name), |
208 | "rtl8187-%s::radio", wiphy_name(dev->wiphy)); | ||
209 | err = rtl8187_register_led(dev, &priv->led_radio, name, | ||
210 | ieee80211_get_radio_led_name(dev), ledpin, true); | ||
211 | if (err) | ||
212 | return; | ||
213 | |||
214 | snprintf(name, sizeof(name), | ||
186 | "rtl8187-%s::tx", wiphy_name(dev->wiphy)); | 215 | "rtl8187-%s::tx", wiphy_name(dev->wiphy)); |
187 | err = rtl8187_register_led(dev, &priv->led_tx, name, | 216 | err = rtl8187_register_led(dev, &priv->led_tx, name, |
188 | ieee80211_get_tx_led_name(dev), ledpin); | 217 | ieee80211_get_tx_led_name(dev), ledpin, false); |
189 | if (err) | 218 | if (err) |
190 | goto error; | 219 | goto err_tx; |
220 | |||
191 | snprintf(name, sizeof(name), | 221 | snprintf(name, sizeof(name), |
192 | "rtl8187-%s::rx", wiphy_name(dev->wiphy)); | 222 | "rtl8187-%s::rx", wiphy_name(dev->wiphy)); |
193 | err = rtl8187_register_led(dev, &priv->led_rx, name, | 223 | err = rtl8187_register_led(dev, &priv->led_rx, name, |
194 | ieee80211_get_rx_led_name(dev), ledpin); | 224 | ieee80211_get_rx_led_name(dev), ledpin, false); |
195 | if (!err) { | 225 | if (!err) |
196 | ieee80211_queue_delayed_work(dev, &priv->led_on, 0); | ||
197 | return; | 226 | return; |
198 | } | 227 | |
199 | /* registration of RX LED failed - unregister TX */ | 228 | /* registration of RX LED failed - unregister */ |
200 | rtl8187_unregister_led(&priv->led_tx); | 229 | rtl8187_unregister_led(&priv->led_tx); |
201 | error: | 230 | err_tx: |
202 | /* If registration of either failed, cancel delayed work */ | 231 | rtl8187_unregister_led(&priv->led_radio); |
203 | cancel_delayed_work_sync(&priv->led_off); | ||
204 | cancel_delayed_work_sync(&priv->led_on); | ||
205 | } | 232 | } |
206 | 233 | ||
207 | void rtl8187_leds_exit(struct ieee80211_hw *dev) | 234 | void rtl8187_leds_exit(struct ieee80211_hw *dev) |
208 | { | 235 | { |
209 | struct rtl8187_priv *priv = dev->priv; | 236 | struct rtl8187_priv *priv = dev->priv; |
210 | 237 | ||
211 | /* turn the LED off before exiting */ | 238 | rtl8187_unregister_led(&priv->led_radio); |
212 | ieee80211_queue_delayed_work(dev, &priv->led_off, 0); | ||
213 | rtl8187_unregister_led(&priv->led_rx); | 239 | rtl8187_unregister_led(&priv->led_rx); |
214 | rtl8187_unregister_led(&priv->led_tx); | 240 | rtl8187_unregister_led(&priv->led_tx); |
215 | cancel_delayed_work_sync(&priv->led_off); | 241 | cancel_delayed_work_sync(&priv->led_off); |
216 | cancel_delayed_work_sync(&priv->led_on); | 242 | cancel_delayed_work_sync(&priv->led_on); |
217 | } | 243 | } |
218 | #endif /* def CONFIG_RTL8187_LED */ | 244 | #endif /* def CONFIG_RTL8187_LEDS */ |
219 | 245 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h index a0332027aead..d743c96d4a20 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.h +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.h | |||
@@ -47,11 +47,13 @@ struct rtl8187_led { | |||
47 | u8 ledpin; | 47 | u8 ledpin; |
48 | /* The unique name string for this LED device. */ | 48 | /* The unique name string for this LED device. */ |
49 | char name[RTL8187_LED_MAX_NAME_LEN + 1]; | 49 | char name[RTL8187_LED_MAX_NAME_LEN + 1]; |
50 | /* If the LED is radio or tx/rx */ | ||
51 | bool is_radio; | ||
50 | }; | 52 | }; |
51 | 53 | ||
52 | void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); | 54 | void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); |
53 | void rtl8187_leds_exit(struct ieee80211_hw *dev); | 55 | void rtl8187_leds_exit(struct ieee80211_hw *dev); |
54 | 56 | ||
55 | #endif /* def CONFIG_RTL8187_LED */ | 57 | #endif /* def CONFIG_RTL8187_LEDS */ |
56 | 58 | ||
57 | #endif /* RTL8187_LED_H */ | 59 | #endif /* RTL8187_LED_H */ |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c index cad8037ab2af..03555e1e0cab 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c +++ b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c | |||
@@ -25,10 +25,10 @@ static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv) | |||
25 | u8 gpio; | 25 | u8 gpio; |
26 | 26 | ||
27 | gpio = rtl818x_ioread8(priv, &priv->map->GPIO0); | 27 | gpio = rtl818x_ioread8(priv, &priv->map->GPIO0); |
28 | rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~0x02); | 28 | rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask); |
29 | gpio = rtl818x_ioread8(priv, &priv->map->GPIO1); | 29 | gpio = rtl818x_ioread8(priv, &priv->map->GPIO1); |
30 | 30 | ||
31 | return gpio & 0x02; | 31 | return gpio & priv->rfkill_mask; |
32 | } | 32 | } |
33 | 33 | ||
34 | void rtl8187_rfkill_init(struct ieee80211_hw *hw) | 34 | void rtl8187_rfkill_init(struct ieee80211_hw *hw) |