aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/rfkill.c
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2007-09-28 08:22:33 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:54:13 -0400
commit42bb4cd5ae320dd46630533fecb91b940d4468e2 (patch)
tree13635dd2a2457f53f4ff09a6b429f8e4ac23c246 /drivers/net/wireless/b43/rfkill.c
parent8e9f7529fdfe34ed519f048682eb404fbd8004e8 (diff)
[B43]: Use input-polldev for the rfkill switch
This removes the direct call to rfkill on an rfkill event and replaces it with an input device. This way userspace is also notified about the event. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/b43/rfkill.c')
-rw-r--r--drivers/net/wireless/b43/rfkill.c129
1 files changed, 79 insertions, 50 deletions
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index c25fd9956a9c..800e0a61a7f5 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -26,46 +26,39 @@
26#include "b43.h" 26#include "b43.h"
27 27
28 28
29static void b43_notify_rfkill_press(struct work_struct *work) 29/* Returns TRUE, if the radio is enabled in hardware. */
30static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
30{ 31{
31 struct b43_rfkill *rfk = container_of(work, struct b43_rfkill, 32 if (dev->phy.rev >= 3) {
32 notify_work); 33 if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
33 struct b43_wl *wl = container_of(rfk, struct b43_wl, rfkill); 34 & B43_MMIO_RADIO_HWENABLED_HI_MASK))
34 struct b43_wldev *dev; 35 return 1;
35 enum rfkill_state state; 36 } else {
36 37 if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
37 mutex_lock(&wl->mutex); 38 & B43_MMIO_RADIO_HWENABLED_LO_MASK)
38 dev = wl->current_dev; 39 return 1;
39 if (b43_status(dev) < B43_STAT_INITIALIZED) {
40 mutex_unlock(&wl->mutex);
41 return;
42 }
43 if (dev->radio_hw_enable)
44 state = RFKILL_STATE_ON;
45 else
46 state = RFKILL_STATE_OFF;
47 b43info(wl, "Radio hardware status changed to %s\n",
48 dev->radio_hw_enable ? "ENABLED" : "DISABLED");
49 mutex_unlock(&wl->mutex);
50
51 if (rfk->rfkill) {
52 /* Be careful. This calls back into the software toggle routines.
53 * So we must unlock before calling. */
54 rfkill_switch_all(rfk->rfkill->type, state);
55 } 40 }
41 return 0;
56} 42}
57 43
58/* Called when the RFKILL toggled in hardware. 44/* The poll callback for the hardware button. */
59 * This is called with the mutex locked. */ 45static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
60void b43_rfkill_toggled(struct b43_wldev *dev, bool on)
61{ 46{
47 struct b43_wldev *dev = poll_dev->private;
62 struct b43_wl *wl = dev->wl; 48 struct b43_wl *wl = dev->wl;
49 bool enabled;
63 50
51 mutex_lock(&wl->mutex);
64 B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); 52 B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED);
65 /* Update the RF status asynchronously, as rfkill will 53 enabled = b43_is_hw_radio_enabled(dev);
66 * call back into the software toggle handler. 54 if (unlikely(enabled != dev->radio_hw_enable)) {
67 * This would deadlock if done synchronously. */ 55 dev->radio_hw_enable = enabled;
68 queue_work(wl->hw->workqueue, &wl->rfkill.notify_work); 56 b43info(wl, "Radio hardware status changed to %s\n",
57 enabled ? "ENABLED" : "DISABLED");
58 mutex_unlock(&wl->mutex);
59 input_report_key(poll_dev->input, KEY_WLAN, enabled);
60 } else
61 mutex_unlock(&wl->mutex);
69} 62}
70 63
71/* Called when the RFKILL toggled in software. 64/* Called when the RFKILL toggled in software.
@@ -118,38 +111,74 @@ void b43_rfkill_init(struct b43_wldev *dev)
118 struct b43_rfkill *rfk = &(wl->rfkill); 111 struct b43_rfkill *rfk = &(wl->rfkill);
119 int err; 112 int err;
120 113
114 if (rfk->rfkill) {
115 err = rfkill_register(rfk->rfkill);
116 if (err) {
117 b43warn(wl, "Failed to register RF-kill button\n");
118 goto err_free_rfk;
119 }
120 }
121 if (rfk->poll_dev) {
122 err = input_register_polled_device(rfk->poll_dev);
123 if (err) {
124 b43warn(wl, "Failed to register RF-kill polldev\n");
125 goto err_free_polldev;
126 }
127 }
128
129 return;
130err_free_rfk:
131 rfkill_free(rfk->rfkill);
132 rfk->rfkill = NULL;
133err_free_polldev:
134 input_free_polled_device(rfk->poll_dev);
135 rfk->poll_dev = NULL;
136}
137
138void b43_rfkill_exit(struct b43_wldev *dev)
139{
140 struct b43_rfkill *rfk = &(dev->wl->rfkill);
141
142 if (rfk->poll_dev)
143 input_unregister_polled_device(rfk->poll_dev);
144 if (rfk->rfkill)
145 rfkill_unregister(rfk->rfkill);
146}
147
148void b43_rfkill_alloc(struct b43_wldev *dev)
149{
150 struct b43_wl *wl = dev->wl;
151 struct b43_rfkill *rfk = &(wl->rfkill);
152
121 snprintf(rfk->name, sizeof(rfk->name), 153 snprintf(rfk->name, sizeof(rfk->name),
122 "b43-%s", wiphy_name(wl->hw->wiphy)); 154 "b43-%s", wiphy_name(wl->hw->wiphy));
155
123 rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); 156 rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
124 if (!rfk->rfkill) 157 if (!rfk->rfkill) {
125 goto error; 158 b43warn(wl, "Failed to allocate RF-kill button\n");
159 return;
160 }
126 rfk->rfkill->name = rfk->name; 161 rfk->rfkill->name = rfk->name;
127 rfk->rfkill->state = RFKILL_STATE_ON; 162 rfk->rfkill->state = RFKILL_STATE_ON;
128 rfk->rfkill->data = dev; 163 rfk->rfkill->data = dev;
129 rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle; 164 rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle;
130 rfk->rfkill->user_claim_unsupported = 1; 165 rfk->rfkill->user_claim_unsupported = 1;
131 166
132 INIT_WORK(&rfk->notify_work, b43_notify_rfkill_press); 167 rfk->poll_dev = input_allocate_polled_device();
133 168 if (rfk->poll_dev) {
134 err = rfkill_register(rfk->rfkill); 169 rfk->poll_dev->private = dev;
135 if (err) 170 rfk->poll_dev->poll = b43_rfkill_poll;
136 goto error; 171 rfk->poll_dev->poll_interval = 1000; /* msecs */
137 172 } else
138 return; 173 b43warn(wl, "Failed to allocate RF-kill polldev\n");
139error:
140 b43warn(dev->wl, "Failed to initialize the RF-kill button\n");
141 rfkill_free(rfk->rfkill);
142 rfk->rfkill = NULL;
143} 174}
144 175
145void b43_rfkill_exit(struct b43_wldev *dev) 176void b43_rfkill_free(struct b43_wldev *dev)
146{ 177{
147 struct b43_rfkill *rfk = &(dev->wl->rfkill); 178 struct b43_rfkill *rfk = &(dev->wl->rfkill);
148 179
149 if (!rfk->rfkill) 180 input_free_polled_device(rfk->poll_dev);
150 return; 181 rfk->poll_dev = NULL;
151 cancel_work_sync(&rfk->notify_work);
152 rfkill_unregister(rfk->rfkill);
153 rfkill_free(rfk->rfkill); 182 rfkill_free(rfk->rfkill);
154 rfk->rfkill = NULL; 183 rfk->rfkill = NULL;
155} 184}