diff options
Diffstat (limited to 'drivers/net/wireless/b43legacy/rfkill.c')
-rw-r--r-- | drivers/net/wireless/b43legacy/rfkill.c | 172 |
1 files changed, 24 insertions, 148 deletions
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index 4b0c7d27a51f..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. */ |
33 | static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) | 30 | bool 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,164 +42,43 @@ 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. */ |
48 | static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) | 45 | void b43legacy_rfkill_poll(struct ieee80211_hw *hw) |
49 | { | 46 | { |
50 | struct b43legacy_wldev *dev = poll_dev->private; | 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; |
53 | bool report_change = 0; | 51 | bool brought_up = false; |
54 | 52 | ||
55 | mutex_lock(&wl->mutex); | 53 | mutex_lock(&wl->mutex); |
56 | if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) { | 54 | if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) { |
57 | mutex_unlock(&wl->mutex); | 55 | if (ssb_bus_powerup(bus, 0)) { |
58 | return; | 56 | mutex_unlock(&wl->mutex); |
57 | return; | ||
58 | } | ||
59 | ssb_device_enable(dev->dev, 0); | ||
60 | brought_up = true; | ||
59 | } | 61 | } |
62 | |||
60 | enabled = b43legacy_is_hw_radio_enabled(dev); | 63 | enabled = b43legacy_is_hw_radio_enabled(dev); |
64 | |||
61 | if (unlikely(enabled != dev->radio_hw_enable)) { | 65 | if (unlikely(enabled != dev->radio_hw_enable)) { |
62 | dev->radio_hw_enable = enabled; | 66 | dev->radio_hw_enable = enabled; |
63 | report_change = 1; | ||
64 | b43legacyinfo(wl, "Radio hardware status changed to %s\n", | 67 | b43legacyinfo(wl, "Radio hardware status changed to %s\n", |
65 | enabled ? "ENABLED" : "DISABLED"); | 68 | enabled ? "ENABLED" : "DISABLED"); |
66 | } | 69 | wiphy_rfkill_set_hw_state(hw->wiphy, !enabled); |
67 | mutex_unlock(&wl->mutex); | 70 | if (enabled != dev->phy.radio_on) { |
68 | 71 | if (enabled) | |
69 | /* send the radio switch event to the system - note both a key press | 72 | b43legacy_radio_turn_on(dev); |
70 | * and a release are required */ | 73 | else |
71 | if (unlikely(report_change)) { | 74 | b43legacy_radio_turn_off(dev, 0); |
72 | input_report_key(poll_dev->input, KEY_WLAN, 1); | ||
73 | input_report_key(poll_dev->input, KEY_WLAN, 0); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | /* Called when the RFKILL toggled in software. | ||
78 | * This is called without locking. */ | ||
79 | static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state) | ||
80 | { | ||
81 | struct b43legacy_wldev *dev = data; | ||
82 | struct b43legacy_wl *wl = dev->wl; | ||
83 | int err = -EBUSY; | ||
84 | |||
85 | if (!wl->rfkill.registered) | ||
86 | return 0; | ||
87 | |||
88 | mutex_lock(&wl->mutex); | ||
89 | if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) | ||
90 | goto out_unlock; | ||
91 | err = 0; | ||
92 | switch (state) { | ||
93 | case RFKILL_STATE_UNBLOCKED: | ||
94 | if (!dev->radio_hw_enable) { | ||
95 | /* No luck. We can't toggle the hardware RF-kill | ||
96 | * button from software. */ | ||
97 | err = -EBUSY; | ||
98 | goto out_unlock; | ||
99 | } | 75 | } |
100 | if (!dev->phy.radio_on) | ||
101 | b43legacy_radio_turn_on(dev); | ||
102 | break; | ||
103 | case RFKILL_STATE_SOFT_BLOCKED: | ||
104 | if (dev->phy.radio_on) | ||
105 | b43legacy_radio_turn_off(dev, 0); | ||
106 | break; | ||
107 | default: | ||
108 | b43legacywarn(wl, "Received unexpected rfkill state %d.\n", | ||
109 | state); | ||
110 | break; | ||
111 | } | 76 | } |
112 | 77 | ||
113 | out_unlock: | 78 | if (brought_up) { |
114 | mutex_unlock(&wl->mutex); | 79 | ssb_device_disable(dev->dev, 0); |
115 | 80 | ssb_bus_may_powerdown(bus); | |
116 | return err; | ||
117 | } | ||
118 | |||
119 | char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev) | ||
120 | { | ||
121 | struct b43legacy_rfkill *rfk = &(dev->wl->rfkill); | ||
122 | |||
123 | if (!rfk->registered) | ||
124 | return NULL; | ||
125 | return rfkill_get_led_name(rfk->rfkill); | ||
126 | } | ||
127 | |||
128 | void b43legacy_rfkill_init(struct b43legacy_wldev *dev) | ||
129 | { | ||
130 | struct b43legacy_wl *wl = dev->wl; | ||
131 | struct b43legacy_rfkill *rfk = &(wl->rfkill); | ||
132 | int err; | ||
133 | |||
134 | rfk->registered = 0; | ||
135 | |||
136 | rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); | ||
137 | if (!rfk->rfkill) | ||
138 | goto out_error; | ||
139 | snprintf(rfk->name, sizeof(rfk->name), | ||
140 | "b43legacy-%s", wiphy_name(wl->hw->wiphy)); | ||
141 | rfk->rfkill->name = rfk->name; | ||
142 | rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; | ||
143 | rfk->rfkill->data = dev; | ||
144 | rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle; | ||
145 | |||
146 | rfk->poll_dev = input_allocate_polled_device(); | ||
147 | if (!rfk->poll_dev) { | ||
148 | rfkill_free(rfk->rfkill); | ||
149 | goto err_freed_rfk; | ||
150 | } | 81 | } |
151 | 82 | ||
152 | rfk->poll_dev->private = dev; | 83 | mutex_unlock(&wl->mutex); |
153 | rfk->poll_dev->poll = b43legacy_rfkill_poll; | ||
154 | rfk->poll_dev->poll_interval = 1000; /* msecs */ | ||
155 | |||
156 | rfk->poll_dev->input->name = rfk->name; | ||
157 | rfk->poll_dev->input->id.bustype = BUS_HOST; | ||
158 | rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor; | ||
159 | rfk->poll_dev->input->evbit[0] = BIT(EV_KEY); | ||
160 | set_bit(KEY_WLAN, rfk->poll_dev->input->keybit); | ||
161 | |||
162 | err = rfkill_register(rfk->rfkill); | ||
163 | if (err) | ||
164 | goto err_free_polldev; | ||
165 | |||
166 | #ifdef CONFIG_RFKILL_INPUT_MODULE | ||
167 | /* B43legacy RF-kill isn't useful without the rfkill-input subsystem. | ||
168 | * Try to load the module. */ | ||
169 | err = request_module("rfkill-input"); | ||
170 | if (err) | ||
171 | b43legacywarn(wl, "Failed to load the rfkill-input module." | ||
172 | "The built-in radio LED will not work.\n"); | ||
173 | #endif /* CONFIG_RFKILL_INPUT */ | ||
174 | |||
175 | err = input_register_polled_device(rfk->poll_dev); | ||
176 | if (err) | ||
177 | goto err_unreg_rfk; | ||
178 | |||
179 | rfk->registered = 1; | ||
180 | |||
181 | return; | ||
182 | err_unreg_rfk: | ||
183 | rfkill_unregister(rfk->rfkill); | ||
184 | err_free_polldev: | ||
185 | input_free_polled_device(rfk->poll_dev); | ||
186 | rfk->poll_dev = NULL; | ||
187 | err_freed_rfk: | ||
188 | rfk->rfkill = NULL; | ||
189 | out_error: | ||
190 | rfk->registered = 0; | ||
191 | b43legacywarn(wl, "RF-kill button init failed\n"); | ||
192 | } | ||
193 | |||
194 | void b43legacy_rfkill_exit(struct b43legacy_wldev *dev) | ||
195 | { | ||
196 | struct b43legacy_rfkill *rfk = &(dev->wl->rfkill); | ||
197 | |||
198 | if (!rfk->registered) | ||
199 | return; | ||
200 | rfk->registered = 0; | ||
201 | |||
202 | input_unregister_polled_device(rfk->poll_dev); | ||
203 | rfkill_unregister(rfk->rfkill); | ||
204 | input_free_polled_device(rfk->poll_dev); | ||
205 | rfk->poll_dev = NULL; | ||
206 | rfk->rfkill = NULL; | ||
207 | } | 84 | } |
208 | |||