aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43legacy/rfkill.c
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2007-10-10 23:48:17 -0400
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:03:27 -0500
commit6be50837e303c53b1e5a0138dfed132ccbabcdad (patch)
tree5664873c9ab28c798e7044adf25e4e6e34da755d /drivers/net/wireless/b43legacy/rfkill.c
parent93bb7f3a7bb5c95da10242d9763994a466c90b1d (diff)
b43legacy: 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. This patch is the port to b43legacy of a patch for b43 by Michael Buesch <mb@bu3sch.de>. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43legacy/rfkill.c')
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c135
1 files changed, 81 insertions, 54 deletions
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index db6292642057..b6bf205c6455 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -1,6 +1,6 @@
1/* 1/*
2 2
3 Broadcom B43legacy wireless driver 3 Broadcom B43 wireless driver
4 RFKILL support 4 RFKILL support
5 5
6 Copyright (c) 2007 Michael Buesch <mb@bu3sch.de> 6 Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
@@ -27,48 +27,39 @@
27#include "b43legacy.h" 27#include "b43legacy.h"
28 28
29 29
30static void b43legacy_notify_rfkill_press(struct work_struct *work) 30/* Returns TRUE, if the radio is enabled in hardware. */
31static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
31{ 32{
32 struct b43legacy_rfkill *rfk = container_of(work, 33 if (dev->phy.rev >= 3) {
33 struct b43legacy_rfkill, 34 if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
34 notify_work); 35 & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
35 struct b43legacy_wl *wl = container_of(rfk, struct b43legacy_wl, 36 return 1;
36 rfkill); 37 } else {
37 struct b43legacy_wldev *dev; 38 if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
38 enum rfkill_state state; 39 & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
39 40 return 1;
40 mutex_lock(&wl->mutex);
41 dev = wl->current_dev;
42 if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
43 mutex_unlock(&wl->mutex);
44 return;
45 }
46 if (dev->radio_hw_enable)
47 state = RFKILL_STATE_ON;
48 else
49 state = RFKILL_STATE_OFF;
50 b43legacyinfo(wl, "Radio hardware status changed to %s\n",
51 dev->radio_hw_enable ? "ENABLED" : "DISABLED");
52 mutex_unlock(&wl->mutex);
53
54 if (rfk->rfkill) {
55 /* Be careful. This calls back into the software toggle
56 * routines. So we must unlock before calling. */
57 rfkill_switch_all(rfk->rfkill->type, state);
58 } 41 }
42 return 0;
59} 43}
60 44
61/* Called when the RFKILL toggled in hardware. 45/* The poll callback for the hardware button. */
62 * This is called with the mutex locked. */ 46static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
63void b43legacy_rfkill_toggled(struct b43legacy_wldev *dev, bool on)
64{ 47{
48 struct b43legacy_wldev *dev = poll_dev->private;
65 struct b43legacy_wl *wl = dev->wl; 49 struct b43legacy_wl *wl = dev->wl;
50 bool enabled;
66 51
52 mutex_lock(&wl->mutex);
67 B43legacy_WARN_ON(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED); 53 B43legacy_WARN_ON(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED);
68 /* Update the RF status asynchronously, as rfkill will 54 enabled = b43legacy_is_hw_radio_enabled(dev);
69 * call back into the software toggle handler. 55 if (unlikely(enabled != dev->radio_hw_enable)) {
70 * This would deadlock if done synchronously. */ 56 dev->radio_hw_enable = enabled;
71 queue_work(wl->hw->workqueue, &wl->rfkill.notify_work); 57 b43legacyinfo(wl, "Radio hardware status changed to %s\n",
58 enabled ? "ENABLED" : "DISABLED");
59 mutex_unlock(&wl->mutex);
60 input_report_key(poll_dev->input, KEY_WLAN, enabled);
61 } else
62 mutex_unlock(&wl->mutex);
72} 63}
73 64
74/* Called when the RFKILL toggled in software. 65/* Called when the RFKILL toggled in software.
@@ -106,7 +97,7 @@ out_unlock:
106 return err; 97 return err;
107} 98}
108 99
109char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev) 100char * b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
110{ 101{
111 struct b43legacy_wl *wl = dev->wl; 102 struct b43legacy_wl *wl = dev->wl;
112 103
@@ -121,38 +112,74 @@ void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
121 struct b43legacy_rfkill *rfk = &(wl->rfkill); 112 struct b43legacy_rfkill *rfk = &(wl->rfkill);
122 int err; 113 int err;
123 114
115 if (rfk->rfkill) {
116 err = rfkill_register(rfk->rfkill);
117 if (err) {
118 b43legacywarn(wl, "Failed to register RF-kill button\n");
119 goto err_free_rfk;
120 }
121 }
122 if (rfk->poll_dev) {
123 err = input_register_polled_device(rfk->poll_dev);
124 if (err) {
125 b43legacywarn(wl, "Failed to register RF-kill polldev\n");
126 goto err_free_polldev;
127 }
128 }
129
130 return;
131err_free_rfk:
132 rfkill_free(rfk->rfkill);
133 rfk->rfkill = NULL;
134err_free_polldev:
135 input_free_polled_device(rfk->poll_dev);
136 rfk->poll_dev = NULL;
137}
138
139void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
140{
141 struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
142
143 if (rfk->poll_dev)
144 input_unregister_polled_device(rfk->poll_dev);
145 if (rfk->rfkill)
146 rfkill_unregister(rfk->rfkill);
147}
148
149void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev)
150{
151 struct b43legacy_wl *wl = dev->wl;
152 struct b43legacy_rfkill *rfk = &(wl->rfkill);
153
124 snprintf(rfk->name, sizeof(rfk->name), 154 snprintf(rfk->name, sizeof(rfk->name),
125 "b43legacy-%s", wiphy_name(wl->hw->wiphy)); 155 "b43legacy-%s", wiphy_name(wl->hw->wiphy));
156
126 rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); 157 rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
127 if (!rfk->rfkill) 158 if (!rfk->rfkill) {
128 goto error; 159 b43legacywarn(wl, "Failed to allocate RF-kill button\n");
160 return;
161 }
129 rfk->rfkill->name = rfk->name; 162 rfk->rfkill->name = rfk->name;
130 rfk->rfkill->state = RFKILL_STATE_ON; 163 rfk->rfkill->state = RFKILL_STATE_ON;
131 rfk->rfkill->data = dev; 164 rfk->rfkill->data = dev;
132 rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle; 165 rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle;
133 rfk->rfkill->user_claim_unsupported = 1; 166 rfk->rfkill->user_claim_unsupported = 1;
134 167
135 INIT_WORK(&rfk->notify_work, b43legacy_notify_rfkill_press); 168 rfk->poll_dev = input_allocate_polled_device();
136 169 if (rfk->poll_dev) {
137 err = rfkill_register(rfk->rfkill); 170 rfk->poll_dev->private = dev;
138 if (err) 171 rfk->poll_dev->poll = b43legacy_rfkill_poll;
139 goto error; 172 rfk->poll_dev->poll_interval = 1000; /* msecs */
140 173 } else
141 return; 174 b43legacywarn(wl, "Failed to allocate RF-kill polldev\n");
142error:
143 b43legacywarn(dev->wl, "Failed to initialize the RF-kill button\n");
144 rfkill_free(rfk->rfkill);
145 rfk->rfkill = NULL;
146} 175}
147 176
148void b43legacy_rfkill_exit(struct b43legacy_wldev *dev) 177void b43legacy_rfkill_free(struct b43legacy_wldev *dev)
149{ 178{
150 struct b43legacy_rfkill *rfk = &(dev->wl->rfkill); 179 struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
151 180
152 if (!rfk->rfkill) 181 input_free_polled_device(rfk->poll_dev);
153 return; 182 rfk->poll_dev = NULL;
154 cancel_work_sync(&rfk->notify_work);
155 rfkill_unregister(rfk->rfkill);
156 rfkill_free(rfk->rfkill); 183 rfkill_free(rfk->rfkill);
157 rfk->rfkill = NULL; 184 rfk->rfkill = NULL;
158} 185}