aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/b43/Kconfig7
-rw-r--r--drivers/net/wireless/b43/Makefile2
-rw-r--r--drivers/net/wireless/b43/b43.h3
-rw-r--r--drivers/net/wireless/b43/leds.c7
-rw-r--r--drivers/net/wireless/b43/main.c27
-rw-r--r--drivers/net/wireless/b43/phy_common.h2
-rw-r--r--drivers/net/wireless/b43/rfkill.c113
-rw-r--r--drivers/net/wireless/b43/rfkill.h44
-rw-r--r--drivers/net/wireless/b43legacy/Kconfig8
-rw-r--r--drivers/net/wireless/b43legacy/Makefile2
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h3
-rw-r--r--drivers/net/wireless/b43legacy/leds.c7
-rw-r--r--drivers/net/wireless/b43legacy/main.c17
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c115
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.h50
15 files changed, 66 insertions, 341 deletions
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 07a99e3faf94..67f564e37225 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -98,13 +98,6 @@ config B43_LEDS
98 depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43) 98 depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43)
99 default y 99 default y
100 100
101# This config option automatically enables b43 RFKILL support,
102# if it's possible.
103config B43_RFKILL
104 bool
105 depends on B43 && (RFKILL = y || RFKILL = B43)
106 default y
107
108# This config option automatically enables b43 HW-RNG support, 101# This config option automatically enables b43 HW-RNG support,
109# if the HW-RNG core is enabled. 102# if the HW-RNG core is enabled.
110config B43_HWRNG 103config B43_HWRNG
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index 281ef8310350..da379f4b0c3a 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -13,7 +13,7 @@ b43-y += lo.o
13b43-y += wa.o 13b43-y += wa.o
14b43-y += dma.o 14b43-y += dma.o
15b43-$(CONFIG_B43_PIO) += pio.o 15b43-$(CONFIG_B43_PIO) += pio.o
16b43-$(CONFIG_B43_RFKILL) += rfkill.o 16b43-y += rfkill.o
17b43-$(CONFIG_B43_LEDS) += leds.o 17b43-$(CONFIG_B43_LEDS) += leds.o
18b43-$(CONFIG_B43_PCMCIA) += pcmcia.o 18b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
19b43-$(CONFIG_B43_DEBUG) += debugfs.o 19b43-$(CONFIG_B43_DEBUG) += debugfs.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 4e8ad841c3c5..75aede02f932 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -631,9 +631,6 @@ struct b43_wl {
631 char rng_name[30 + 1]; 631 char rng_name[30 + 1];
632#endif /* CONFIG_B43_HWRNG */ 632#endif /* CONFIG_B43_HWRNG */
633 633
634 /* The RF-kill button */
635 struct b43_rfkill rfkill;
636
637 /* List of all wireless devices on this chip */ 634 /* List of all wireless devices on this chip */
638 struct list_head devlist; 635 struct list_head devlist;
639 u8 nr_devs; 636 u8 nr_devs;
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index 9a498d3fc653..c8b317094c31 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -28,6 +28,7 @@
28 28
29#include "b43.h" 29#include "b43.h"
30#include "leds.h" 30#include "leds.h"
31#include "rfkill.h"
31 32
32 33
33static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, 34static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
@@ -164,10 +165,10 @@ static void b43_map_led(struct b43_wldev *dev,
164 snprintf(name, sizeof(name), 165 snprintf(name, sizeof(name),
165 "b43-%s::radio", wiphy_name(hw->wiphy)); 166 "b43-%s::radio", wiphy_name(hw->wiphy));
166 b43_register_led(dev, &dev->led_radio, name, 167 b43_register_led(dev, &dev->led_radio, name,
167 b43_rfkill_led_name(dev), 168 ieee80211_get_radio_led_name(hw),
168 led_index, activelow); 169 led_index, activelow);
169 /* Sync the RF-kill LED state with the switch state. */ 170 /* Sync the RF-kill LED state with radio and switch states. */
170 if (dev->radio_hw_enable) 171 if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev))
171 b43_led_turn_on(dev, led_index, activelow); 172 b43_led_turn_on(dev, led_index, activelow);
172 break; 173 break;
173 case B43_LED_WEIRD: 174 case B43_LED_WEIRD:
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 1d3e40095ada..5d9f1981f2ce 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4298,7 +4298,6 @@ static int b43_op_start(struct ieee80211_hw *hw)
4298 struct b43_wldev *dev = wl->current_dev; 4298 struct b43_wldev *dev = wl->current_dev;
4299 int did_init = 0; 4299 int did_init = 0;
4300 int err = 0; 4300 int err = 0;
4301 bool do_rfkill_exit = 0;
4302 4301
4303 /* Kill all old instance specific information to make sure 4302 /* Kill all old instance specific information to make sure
4304 * the card won't use it in the short timeframe between start 4303 * the card won't use it in the short timeframe between start
@@ -4312,18 +4311,12 @@ static int b43_op_start(struct ieee80211_hw *hw)
4312 wl->beacon1_uploaded = 0; 4311 wl->beacon1_uploaded = 0;
4313 wl->beacon_templates_virgin = 1; 4312 wl->beacon_templates_virgin = 1;
4314 4313
4315 /* First register RFkill.
4316 * LEDs that are registered later depend on it. */
4317 b43_rfkill_init(dev);
4318
4319 mutex_lock(&wl->mutex); 4314 mutex_lock(&wl->mutex);
4320 4315
4321 if (b43_status(dev) < B43_STAT_INITIALIZED) { 4316 if (b43_status(dev) < B43_STAT_INITIALIZED) {
4322 err = b43_wireless_core_init(dev); 4317 err = b43_wireless_core_init(dev);
4323 if (err) { 4318 if (err)
4324 do_rfkill_exit = 1;
4325 goto out_mutex_unlock; 4319 goto out_mutex_unlock;
4326 }
4327 did_init = 1; 4320 did_init = 1;
4328 } 4321 }
4329 4322
@@ -4332,17 +4325,16 @@ static int b43_op_start(struct ieee80211_hw *hw)
4332 if (err) { 4325 if (err) {
4333 if (did_init) 4326 if (did_init)
4334 b43_wireless_core_exit(dev); 4327 b43_wireless_core_exit(dev);
4335 do_rfkill_exit = 1;
4336 goto out_mutex_unlock; 4328 goto out_mutex_unlock;
4337 } 4329 }
4338 } 4330 }
4339 4331
4332 /* XXX: only do if device doesn't support rfkill irq */
4333 wiphy_rfkill_start_polling(hw->wiphy);
4334
4340 out_mutex_unlock: 4335 out_mutex_unlock:
4341 mutex_unlock(&wl->mutex); 4336 mutex_unlock(&wl->mutex);
4342 4337
4343 if (do_rfkill_exit)
4344 b43_rfkill_exit(dev);
4345
4346 return err; 4338 return err;
4347} 4339}
4348 4340
@@ -4351,7 +4343,6 @@ static void b43_op_stop(struct ieee80211_hw *hw)
4351 struct b43_wl *wl = hw_to_b43_wl(hw); 4343 struct b43_wl *wl = hw_to_b43_wl(hw);
4352 struct b43_wldev *dev = wl->current_dev; 4344 struct b43_wldev *dev = wl->current_dev;
4353 4345
4354 b43_rfkill_exit(dev);
4355 cancel_work_sync(&(wl->beacon_update_trigger)); 4346 cancel_work_sync(&(wl->beacon_update_trigger));
4356 4347
4357 mutex_lock(&wl->mutex); 4348 mutex_lock(&wl->mutex);
@@ -4433,6 +4424,7 @@ static const struct ieee80211_ops b43_hw_ops = {
4433 .sta_notify = b43_op_sta_notify, 4424 .sta_notify = b43_op_sta_notify,
4434 .sw_scan_start = b43_op_sw_scan_start_notifier, 4425 .sw_scan_start = b43_op_sw_scan_start_notifier,
4435 .sw_scan_complete = b43_op_sw_scan_complete_notifier, 4426 .sw_scan_complete = b43_op_sw_scan_complete_notifier,
4427 .rfkill_poll = b43_rfkill_poll,
4436}; 4428};
4437 4429
4438/* Hard-reset the chip. Do not call this directly. 4430/* Hard-reset the chip. Do not call this directly.
@@ -4920,7 +4912,7 @@ static struct ssb_driver b43_ssb_driver = {
4920static void b43_print_driverinfo(void) 4912static void b43_print_driverinfo(void)
4921{ 4913{
4922 const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", 4914 const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
4923 *feat_leds = "", *feat_rfkill = ""; 4915 *feat_leds = "";
4924 4916
4925#ifdef CONFIG_B43_PCI_AUTOSELECT 4917#ifdef CONFIG_B43_PCI_AUTOSELECT
4926 feat_pci = "P"; 4918 feat_pci = "P";
@@ -4934,14 +4926,11 @@ static void b43_print_driverinfo(void)
4934#ifdef CONFIG_B43_LEDS 4926#ifdef CONFIG_B43_LEDS
4935 feat_leds = "L"; 4927 feat_leds = "L";
4936#endif 4928#endif
4937#ifdef CONFIG_B43_RFKILL
4938 feat_rfkill = "R";
4939#endif
4940 printk(KERN_INFO "Broadcom 43xx driver loaded " 4929 printk(KERN_INFO "Broadcom 43xx driver loaded "
4941 "[ Features: %s%s%s%s%s, Firmware-ID: " 4930 "[ Features: %s%s%s%s, Firmware-ID: "
4942 B43_SUPPORTED_FIRMWARE_ID " ]\n", 4931 B43_SUPPORTED_FIRMWARE_ID " ]\n",
4943 feat_pci, feat_pcmcia, feat_nphy, 4932 feat_pci, feat_pcmcia, feat_nphy,
4944 feat_leds, feat_rfkill); 4933 feat_leds);
4945} 4934}
4946 4935
4947static int __init b43_init(void) 4936static int __init b43_init(void)
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index f4c2d79cbc89..44cc918e4fc6 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -1,7 +1,7 @@
1#ifndef LINUX_B43_PHY_COMMON_H_ 1#ifndef LINUX_B43_PHY_COMMON_H_
2#define LINUX_B43_PHY_COMMON_H_ 2#define LINUX_B43_PHY_COMMON_H_
3 3
4#include <linux/rfkill.h> 4#include <linux/types.h>
5 5
6struct b43_wldev; 6struct b43_wldev;
7 7
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 96047843cd56..31e55999893f 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -22,15 +22,11 @@
22 22
23*/ 23*/
24 24
25#include "rfkill.h"
26#include "b43.h" 25#include "b43.h"
27#include "phy_common.h"
28
29#include <linux/kmod.h>
30 26
31 27
32/* Returns TRUE, if the radio is enabled in hardware. */ 28/* Returns TRUE, if the radio is enabled in hardware. */
33static bool b43_is_hw_radio_enabled(struct b43_wldev *dev) 29bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
34{ 30{
35 if (dev->phy.rev >= 3) { 31 if (dev->phy.rev >= 3) {
36 if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) 32 if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
@@ -45,110 +41,39 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
45} 41}
46 42
47/* The poll callback for the hardware button. */ 43/* The poll callback for the hardware button. */
48static void b43_rfkill_poll(struct rfkill *rfkill, void *data) 44void b43_rfkill_poll(struct ieee80211_hw *hw)
49{ 45{
50 struct b43_wldev *dev = data; 46 struct b43_wl *wl = hw_to_b43_wl(hw);
51 struct b43_wl *wl = dev->wl; 47 struct b43_wldev *dev = wl->current_dev;
48 struct ssb_bus *bus = dev->dev->bus;
52 bool enabled; 49 bool enabled;
50 bool brought_up = false;
53 51
54 mutex_lock(&wl->mutex); 52 mutex_lock(&wl->mutex);
55 if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) { 53 if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
56 mutex_unlock(&wl->mutex); 54 if (ssb_bus_powerup(bus, 0)) {
57 return; 55 mutex_unlock(&wl->mutex);
56 return;
57 }
58 ssb_device_enable(dev->dev, 0);
59 brought_up = true;
58 } 60 }
61
59 enabled = b43_is_hw_radio_enabled(dev); 62 enabled = b43_is_hw_radio_enabled(dev);
63
60 if (unlikely(enabled != dev->radio_hw_enable)) { 64 if (unlikely(enabled != dev->radio_hw_enable)) {
61 dev->radio_hw_enable = enabled; 65 dev->radio_hw_enable = enabled;
62 b43info(wl, "Radio hardware status changed to %s\n", 66 b43info(wl, "Radio hardware status changed to %s\n",
63 enabled ? "ENABLED" : "DISABLED"); 67 enabled ? "ENABLED" : "DISABLED");
64 enabled = !rfkill_set_hw_state(rfkill, !enabled); 68 wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
65 if (enabled != dev->phy.radio_on) 69 if (enabled != dev->phy.radio_on)
66 b43_software_rfkill(dev, !enabled); 70 b43_software_rfkill(dev, !enabled);
67 } 71 }
68 mutex_unlock(&wl->mutex);
69}
70
71/* Called when the RFKILL toggled in software. */
72static int b43_rfkill_soft_set(void *data, bool blocked)
73{
74 struct b43_wldev *dev = data;
75 struct b43_wl *wl = dev->wl;
76 int err = -EINVAL;
77
78 if (WARN_ON(!wl->rfkill.registered))
79 return -EINVAL;
80 72
81 mutex_lock(&wl->mutex); 73 if (brought_up) {
82 74 ssb_device_disable(dev->dev, 0);
83 if (b43_status(dev) < B43_STAT_INITIALIZED) 75 ssb_bus_may_powerdown(bus);
84 goto out_unlock; 76 }
85
86 if (!dev->radio_hw_enable)
87 goto out_unlock;
88 77
89 if (!blocked != dev->phy.radio_on)
90 b43_software_rfkill(dev, blocked);
91 err = 0;
92out_unlock:
93 mutex_unlock(&wl->mutex); 78 mutex_unlock(&wl->mutex);
94 return err;
95}
96
97const char *b43_rfkill_led_name(struct b43_wldev *dev)
98{
99 struct b43_rfkill *rfk = &(dev->wl->rfkill);
100
101 if (!rfk->registered)
102 return NULL;
103 return rfkill_get_led_trigger_name(rfk->rfkill);
104}
105
106static const struct rfkill_ops b43_rfkill_ops = {
107 .set_block = b43_rfkill_soft_set,
108 .poll = b43_rfkill_poll,
109};
110
111void b43_rfkill_init(struct b43_wldev *dev)
112{
113 struct b43_wl *wl = dev->wl;
114 struct b43_rfkill *rfk = &(wl->rfkill);
115 int err;
116
117 rfk->registered = 0;
118
119 snprintf(rfk->name, sizeof(rfk->name),
120 "b43-%s", wiphy_name(wl->hw->wiphy));
121
122 rfk->rfkill = rfkill_alloc(rfk->name,
123 dev->dev->dev,
124 RFKILL_TYPE_WLAN,
125 &b43_rfkill_ops, dev);
126 if (!rfk->rfkill)
127 goto out_error;
128
129 err = rfkill_register(rfk->rfkill);
130 if (err)
131 goto err_free;
132
133 rfk->registered = 1;
134
135 return;
136 err_free:
137 rfkill_destroy(rfk->rfkill);
138 out_error:
139 rfk->registered = 0;
140 b43warn(wl, "RF-kill button init failed\n");
141}
142
143void b43_rfkill_exit(struct b43_wldev *dev)
144{
145 struct b43_rfkill *rfk = &(dev->wl->rfkill);
146
147 if (!rfk->registered)
148 return;
149 rfk->registered = 0;
150
151 rfkill_unregister(rfk->rfkill);
152 rfkill_destroy(rfk->rfkill);
153 rfk->rfkill = NULL;
154} 79}
diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h
index da497e01bbb1..f046c3ca0519 100644
--- a/drivers/net/wireless/b43/rfkill.h
+++ b/drivers/net/wireless/b43/rfkill.h
@@ -1,49 +1,11 @@
1#ifndef B43_RFKILL_H_ 1#ifndef B43_RFKILL_H_
2#define B43_RFKILL_H_ 2#define B43_RFKILL_H_
3 3
4struct ieee80211_hw;
4struct b43_wldev; 5struct b43_wldev;
5 6
7void b43_rfkill_poll(struct ieee80211_hw *hw);
6 8
7#ifdef CONFIG_B43_RFKILL 9bool b43_is_hw_radio_enabled(struct b43_wldev *dev);
8
9#include <linux/rfkill.h>
10
11
12struct b43_rfkill {
13 /* The RFKILL subsystem data structure */
14 struct rfkill *rfkill;
15 /* Did initialization succeed? Used for freeing. */
16 bool registered;
17 /* The unique name of this rfkill switch */
18 char name[sizeof("b43-phy4294967295")];
19};
20
21/* The init function returns void, because we are not interested
22 * in failing the b43 init process when rfkill init failed. */
23void b43_rfkill_init(struct b43_wldev *dev);
24void b43_rfkill_exit(struct b43_wldev *dev);
25
26const char *b43_rfkill_led_name(struct b43_wldev *dev);
27
28
29#else /* CONFIG_B43_RFKILL */
30/* No RFKILL support. */
31
32struct b43_rfkill {
33 /* empty */
34};
35
36static inline void b43_rfkill_init(struct b43_wldev *dev)
37{
38}
39static inline void b43_rfkill_exit(struct b43_wldev *dev)
40{
41}
42static inline char * b43_rfkill_led_name(struct b43_wldev *dev)
43{
44 return NULL;
45}
46
47#endif /* CONFIG_B43_RFKILL */
48 10
49#endif /* B43_RFKILL_H_ */ 11#endif /* B43_RFKILL_H_ */
diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig
index 6893f439df70..94a463478053 100644
--- a/drivers/net/wireless/b43legacy/Kconfig
+++ b/drivers/net/wireless/b43legacy/Kconfig
@@ -42,14 +42,6 @@ config B43LEGACY_LEDS
42 depends on B43LEGACY && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43LEGACY) 42 depends on B43LEGACY && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43LEGACY)
43 default y 43 default y
44 44
45# RFKILL support
46# This config option automatically enables b43legacy RFKILL support,
47# if it's possible.
48config B43LEGACY_RFKILL
49 bool
50 depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY)
51 default y
52
53# This config option automatically enables b43 HW-RNG support, 45# This config option automatically enables b43 HW-RNG support,
54# if the HW-RNG core is enabled. 46# if the HW-RNG core is enabled.
55config B43LEGACY_HWRNG 47config B43LEGACY_HWRNG
diff --git a/drivers/net/wireless/b43legacy/Makefile b/drivers/net/wireless/b43legacy/Makefile
index 80cdb73bd140..227a77e84362 100644
--- a/drivers/net/wireless/b43legacy/Makefile
+++ b/drivers/net/wireless/b43legacy/Makefile
@@ -6,7 +6,7 @@ b43legacy-y += radio.o
6b43legacy-y += sysfs.o 6b43legacy-y += sysfs.o
7b43legacy-y += xmit.o 7b43legacy-y += xmit.o
8# b43 RFKILL button support 8# b43 RFKILL button support
9b43legacy-$(CONFIG_B43LEGACY_RFKILL) += rfkill.o 9b43legacy-y += rfkill.o
10# b43legacy LED support 10# b43legacy LED support
11b43legacy-$(CONFIG_B43LEGACY_LEDS) += leds.o 11b43legacy-$(CONFIG_B43LEGACY_LEDS) += leds.o
12# b43legacy debugging 12# b43legacy debugging
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index 19a4b0bc0d87..77fda148ac46 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -602,9 +602,6 @@ struct b43legacy_wl {
602 char rng_name[30 + 1]; 602 char rng_name[30 + 1];
603#endif 603#endif
604 604
605 /* The RF-kill button */
606 struct b43legacy_rfkill rfkill;
607
608 /* List of all wireless devices on this chip */ 605 /* List of all wireless devices on this chip */
609 struct list_head devlist; 606 struct list_head devlist;
610 u8 nr_devs; 607 u8 nr_devs;
diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c
index 538d3117594b..37e9be893560 100644
--- a/drivers/net/wireless/b43legacy/leds.c
+++ b/drivers/net/wireless/b43legacy/leds.c
@@ -28,6 +28,7 @@
28 28
29#include "b43legacy.h" 29#include "b43legacy.h"
30#include "leds.h" 30#include "leds.h"
31#include "rfkill.h"
31 32
32 33
33static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index, 34static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
@@ -164,10 +165,10 @@ static void b43legacy_map_led(struct b43legacy_wldev *dev,
164 snprintf(name, sizeof(name), 165 snprintf(name, sizeof(name),
165 "b43legacy-%s::radio", wiphy_name(hw->wiphy)); 166 "b43legacy-%s::radio", wiphy_name(hw->wiphy));
166 b43legacy_register_led(dev, &dev->led_radio, name, 167 b43legacy_register_led(dev, &dev->led_radio, name,
167 b43legacy_rfkill_led_name(dev), 168 ieee80211_get_radio_led_name(hw),
168 led_index, activelow); 169 led_index, activelow);
169 /* Sync the RF-kill LED state with the switch state. */ 170 /* Sync the RF-kill LED state with radio and switch states. */
170 if (dev->radio_hw_enable) 171 if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev))
171 b43legacy_led_turn_on(dev, led_index, activelow); 172 b43legacy_led_turn_on(dev, led_index, activelow);
172 break; 173 break;
173 case B43legacy_LED_WEIRD: 174 case B43legacy_LED_WEIRD:
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index f6f3fbf0a2f4..e5136fb65ddd 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -3431,11 +3431,6 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
3431 struct b43legacy_wldev *dev = wl->current_dev; 3431 struct b43legacy_wldev *dev = wl->current_dev;
3432 int did_init = 0; 3432 int did_init = 0;
3433 int err = 0; 3433 int err = 0;
3434 bool do_rfkill_exit = 0;
3435
3436 /* First register RFkill.
3437 * LEDs that are registered later depend on it. */
3438 b43legacy_rfkill_init(dev);
3439 3434
3440 /* Kill all old instance specific information to make sure 3435 /* Kill all old instance specific information to make sure
3441 * the card won't use it in the short timeframe between start 3436 * the card won't use it in the short timeframe between start
@@ -3451,10 +3446,8 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
3451 3446
3452 if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { 3447 if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
3453 err = b43legacy_wireless_core_init(dev); 3448 err = b43legacy_wireless_core_init(dev);
3454 if (err) { 3449 if (err)
3455 do_rfkill_exit = 1;
3456 goto out_mutex_unlock; 3450 goto out_mutex_unlock;
3457 }
3458 did_init = 1; 3451 did_init = 1;
3459 } 3452 }
3460 3453
@@ -3463,17 +3456,15 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
3463 if (err) { 3456 if (err) {
3464 if (did_init) 3457 if (did_init)
3465 b43legacy_wireless_core_exit(dev); 3458 b43legacy_wireless_core_exit(dev);
3466 do_rfkill_exit = 1;
3467 goto out_mutex_unlock; 3459 goto out_mutex_unlock;
3468 } 3460 }
3469 } 3461 }
3470 3462
3463 wiphy_rfkill_start_polling(hw->wiphy);
3464
3471out_mutex_unlock: 3465out_mutex_unlock:
3472 mutex_unlock(&wl->mutex); 3466 mutex_unlock(&wl->mutex);
3473 3467
3474 if (do_rfkill_exit)
3475 b43legacy_rfkill_exit(dev);
3476
3477 return err; 3468 return err;
3478} 3469}
3479 3470
@@ -3482,7 +3473,6 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw)
3482 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); 3473 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
3483 struct b43legacy_wldev *dev = wl->current_dev; 3474 struct b43legacy_wldev *dev = wl->current_dev;
3484 3475
3485 b43legacy_rfkill_exit(dev);
3486 cancel_work_sync(&(wl->beacon_update_trigger)); 3476 cancel_work_sync(&(wl->beacon_update_trigger));
3487 3477
3488 mutex_lock(&wl->mutex); 3478 mutex_lock(&wl->mutex);
@@ -3518,6 +3508,7 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
3518 .start = b43legacy_op_start, 3508 .start = b43legacy_op_start,
3519 .stop = b43legacy_op_stop, 3509 .stop = b43legacy_op_stop,
3520 .set_tim = b43legacy_op_beacon_set_tim, 3510 .set_tim = b43legacy_op_beacon_set_tim,
3511 .rfkill_poll = b43legacy_rfkill_poll,
3521}; 3512};
3522 3513
3523/* Hard-reset the chip. Do not call this directly. 3514/* Hard-reset the chip. Do not call this directly.
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index c6230a64505a..8783022db11e 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -22,15 +22,12 @@
22 22
23*/ 23*/
24 24
25#include "rfkill.h"
26#include "radio.h" 25#include "radio.h"
27#include "b43legacy.h" 26#include "b43legacy.h"
28 27
29#include <linux/kmod.h>
30
31 28
32/* Returns TRUE, if the radio is enabled in hardware. */ 29/* Returns TRUE, if the radio is enabled in hardware. */
33static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) 30bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
34{ 31{
35 if (dev->phy.rev >= 3) { 32 if (dev->phy.rev >= 3) {
36 if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI) 33 if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
@@ -45,23 +42,31 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
45} 42}
46 43
47/* The poll callback for the hardware button. */ 44/* The poll callback for the hardware button. */
48static void b43legacy_rfkill_poll(struct rfkill *rfkill, void *data) 45void b43legacy_rfkill_poll(struct ieee80211_hw *hw)
49{ 46{
50 struct b43legacy_wldev *dev = data; 47 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
51 struct b43legacy_wl *wl = dev->wl; 48 struct b43legacy_wldev *dev = wl->current_dev;
49 struct ssb_bus *bus = dev->dev->bus;
52 bool enabled; 50 bool enabled;
51 bool brought_up = false;
53 52
54 mutex_lock(&wl->mutex); 53 mutex_lock(&wl->mutex);
55 if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) { 54 if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) {
56 mutex_unlock(&wl->mutex); 55 if (ssb_bus_powerup(bus, 0)) {
57 return; 56 mutex_unlock(&wl->mutex);
57 return;
58 }
59 ssb_device_enable(dev->dev, 0);
60 brought_up = true;
58 } 61 }
62
59 enabled = b43legacy_is_hw_radio_enabled(dev); 63 enabled = b43legacy_is_hw_radio_enabled(dev);
64
60 if (unlikely(enabled != dev->radio_hw_enable)) { 65 if (unlikely(enabled != dev->radio_hw_enable)) {
61 dev->radio_hw_enable = enabled; 66 dev->radio_hw_enable = enabled;
62 b43legacyinfo(wl, "Radio hardware status changed to %s\n", 67 b43legacyinfo(wl, "Radio hardware status changed to %s\n",
63 enabled ? "ENABLED" : "DISABLED"); 68 enabled ? "ENABLED" : "DISABLED");
64 enabled = !rfkill_set_hw_state(rfkill, !enabled); 69 wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
65 if (enabled != dev->phy.radio_on) { 70 if (enabled != dev->phy.radio_on) {
66 if (enabled) 71 if (enabled)
67 b43legacy_radio_turn_on(dev); 72 b43legacy_radio_turn_on(dev);
@@ -69,95 +74,11 @@ static void b43legacy_rfkill_poll(struct rfkill *rfkill, void *data)
69 b43legacy_radio_turn_off(dev, 0); 74 b43legacy_radio_turn_off(dev, 0);
70 } 75 }
71 } 76 }
72 mutex_unlock(&wl->mutex);
73}
74
75/* Called when the RFKILL toggled in software.
76 * This is called without locking. */
77static int b43legacy_rfkill_soft_set(void *data, bool blocked)
78{
79 struct b43legacy_wldev *dev = data;
80 struct b43legacy_wl *wl = dev->wl;
81 int ret = -EINVAL;
82 77
83 if (!wl->rfkill.registered) 78 if (brought_up) {
84 return -EINVAL; 79 ssb_device_disable(dev->dev, 0);
85 80 ssb_bus_may_powerdown(bus);
86 mutex_lock(&wl->mutex);
87 if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
88 goto out_unlock;
89
90 if (!dev->radio_hw_enable)
91 goto out_unlock;
92
93 if (!blocked != dev->phy.radio_on) {
94 if (!blocked)
95 b43legacy_radio_turn_on(dev);
96 else
97 b43legacy_radio_turn_off(dev, 0);
98 } 81 }
99 ret = 0;
100 82
101out_unlock:
102 mutex_unlock(&wl->mutex); 83 mutex_unlock(&wl->mutex);
103 return ret;
104}
105
106const char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
107{
108 struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
109
110 if (!rfk->registered)
111 return NULL;
112 return rfkill_get_led_trigger_name(rfk->rfkill);
113} 84}
114
115static const struct rfkill_ops b43legacy_rfkill_ops = {
116 .set_block = b43legacy_rfkill_soft_set,
117 .poll = b43legacy_rfkill_poll,
118};
119
120void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
121{
122 struct b43legacy_wl *wl = dev->wl;
123 struct b43legacy_rfkill *rfk = &(wl->rfkill);
124 int err;
125
126 rfk->registered = 0;
127
128 snprintf(rfk->name, sizeof(rfk->name),
129 "b43legacy-%s", wiphy_name(wl->hw->wiphy));
130 rfk->rfkill = rfkill_alloc(rfk->name,
131 dev->dev->dev,
132 RFKILL_TYPE_WLAN,
133 &b43legacy_rfkill_ops, dev);
134 if (!rfk->rfkill)
135 goto out_error;
136
137 err = rfkill_register(rfk->rfkill);
138 if (err)
139 goto err_free;
140
141 rfk->registered = 1;
142
143 return;
144 err_free:
145 rfkill_destroy(rfk->rfkill);
146 out_error:
147 rfk->registered = 0;
148 b43legacywarn(wl, "RF-kill button init failed\n");
149}
150
151void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
152{
153 struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
154
155 if (!rfk->registered)
156 return;
157 rfk->registered = 0;
158
159 rfkill_unregister(rfk->rfkill);
160 rfkill_destroy(rfk->rfkill);
161 rfk->rfkill = NULL;
162}
163
diff --git a/drivers/net/wireless/b43legacy/rfkill.h b/drivers/net/wireless/b43legacy/rfkill.h
index adffc503a6a1..75585571c544 100644
--- a/drivers/net/wireless/b43legacy/rfkill.h
+++ b/drivers/net/wireless/b43legacy/rfkill.h
@@ -1,55 +1,11 @@
1#ifndef B43legacy_RFKILL_H_ 1#ifndef B43legacy_RFKILL_H_
2#define B43legacy_RFKILL_H_ 2#define B43legacy_RFKILL_H_
3 3
4struct ieee80211_hw;
4struct b43legacy_wldev; 5struct b43legacy_wldev;
5 6
6#ifdef CONFIG_B43LEGACY_RFKILL 7void b43legacy_rfkill_poll(struct ieee80211_hw *hw);
7 8
8#include <linux/rfkill.h> 9bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev);
9
10
11
12struct b43legacy_rfkill {
13 /* The RFKILL subsystem data structure */
14 struct rfkill *rfkill;
15 /* Did initialization succeed? Used for freeing. */
16 bool registered;
17 /* The unique name of this rfkill switch */
18 char name[sizeof("b43legacy-phy4294967295")];
19};
20
21/* The init function returns void, because we are not interested
22 * in failing the b43 init process when rfkill init failed. */
23void b43legacy_rfkill_init(struct b43legacy_wldev *dev);
24void b43legacy_rfkill_exit(struct b43legacy_wldev *dev);
25
26const char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev);
27
28
29#else /* CONFIG_B43LEGACY_RFKILL */
30/* No RFKILL support. */
31
32struct b43legacy_rfkill {
33 /* empty */
34};
35
36static inline void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev)
37{
38}
39static inline void b43legacy_rfkill_free(struct b43legacy_wldev *dev)
40{
41}
42static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
43{
44}
45static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
46{
47}
48static inline char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
49{
50 return NULL;
51}
52
53#endif /* CONFIG_B43LEGACY_RFKILL */
54 10
55#endif /* B43legacy_RFKILL_H_ */ 11#endif /* B43legacy_RFKILL_H_ */