aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/net/wireless/b43/Kconfig2
-rw-r--r--drivers/net/wireless/b43/main.c53
-rw-r--r--drivers/net/wireless/b43/rfkill.c129
-rw-r--r--drivers/net/wireless/b43/rfkill.h21
4 files changed, 107 insertions, 98 deletions
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 968f0611ed49..e3c573e56b63 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -70,7 +70,7 @@ config B43_LEDS
70# RFKILL support 70# RFKILL support
71config B43_RFKILL 71config B43_RFKILL
72 bool 72 bool
73 depends on B43 && RFKILL 73 depends on B43 && RFKILL && RFKILL_INPUT && INPUT_POLLDEV
74 default y 74 default y
75 75
76config B43_DEBUG 76config B43_DEBUG
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index a9f7148493f7..a603a154d496 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2143,21 +2143,6 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
2143 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp); 2143 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp);
2144} 2144}
2145 2145
2146/* Returns TRUE, if the radio is enabled in hardware. */
2147static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
2148{
2149 if (dev->phy.rev >= 3) {
2150 if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
2151 & B43_MMIO_RADIO_HWENABLED_HI_MASK))
2152 return 1;
2153 } else {
2154 if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
2155 & B43_MMIO_RADIO_HWENABLED_LO_MASK)
2156 return 1;
2157 }
2158 return 0;
2159}
2160
2161/* This is the opposite of b43_chip_init() */ 2146/* This is the opposite of b43_chip_init() */
2162static void b43_chip_exit(struct b43_wldev *dev) 2147static void b43_chip_exit(struct b43_wldev *dev)
2163{ 2148{
@@ -2350,32 +2335,18 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
2350 //TODO for APHY (temperature?) 2335 //TODO for APHY (temperature?)
2351} 2336}
2352 2337
2353static void b43_periodic_every1sec(struct b43_wldev *dev)
2354{
2355 bool radio_hw_enable;
2356
2357 /* check if radio hardware enabled status changed */
2358 radio_hw_enable = b43_is_hw_radio_enabled(dev);
2359 if (unlikely(dev->radio_hw_enable != radio_hw_enable)) {
2360 dev->radio_hw_enable = radio_hw_enable;
2361 b43_rfkill_toggled(dev, radio_hw_enable);
2362 }
2363}
2364
2365static void do_periodic_work(struct b43_wldev *dev) 2338static void do_periodic_work(struct b43_wldev *dev)
2366{ 2339{
2367 unsigned int state; 2340 unsigned int state;
2368 2341
2369 state = dev->periodic_state; 2342 state = dev->periodic_state;
2370 if (state % 120 == 0) 2343 if (state % 8 == 0)
2371 b43_periodic_every120sec(dev); 2344 b43_periodic_every120sec(dev);
2372 if (state % 60 == 0) 2345 if (state % 4 == 0)
2373 b43_periodic_every60sec(dev); 2346 b43_periodic_every60sec(dev);
2374 if (state % 30 == 0) 2347 if (state % 2 == 0)
2375 b43_periodic_every30sec(dev); 2348 b43_periodic_every30sec(dev);
2376 if (state % 15 == 0) 2349 b43_periodic_every15sec(dev);
2377 b43_periodic_every15sec(dev);
2378 b43_periodic_every1sec(dev);
2379} 2350}
2380 2351
2381/* Estimate a "Badness" value based on the periodic work 2352/* Estimate a "Badness" value based on the periodic work
@@ -2386,13 +2357,11 @@ static int estimate_periodic_work_badness(unsigned int state)
2386{ 2357{
2387 int badness = 0; 2358 int badness = 0;
2388 2359
2389 if (state % 120 == 0) /* every 120 sec */ 2360 if (state % 8 == 0) /* every 120 sec */
2390 badness += 10; 2361 badness += 10;
2391 if (state % 60 == 0) /* every 60 sec */ 2362 if (state % 4 == 0) /* every 60 sec */
2392 badness += 5; 2363 badness += 5;
2393 if (state % 30 == 0) /* every 30 sec */ 2364 if (state % 2 == 0) /* every 30 sec */
2394 badness += 1;
2395 if (state % 15 == 0) /* every 15 sec */
2396 badness += 1; 2365 badness += 1;
2397 2366
2398#define BADNESS_LIMIT 4 2367#define BADNESS_LIMIT 4
@@ -2443,13 +2412,13 @@ static void b43_periodic_work_handler(struct work_struct *work)
2443 spin_unlock_irqrestore(&dev->wl->irq_lock, flags); 2412 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
2444 } 2413 }
2445 dev->periodic_state++; 2414 dev->periodic_state++;
2446 out_requeue: 2415out_requeue:
2447 if (b43_debug(dev, B43_DBG_PWORK_FAST)) 2416 if (b43_debug(dev, B43_DBG_PWORK_FAST))
2448 delay = msecs_to_jiffies(50); 2417 delay = msecs_to_jiffies(50);
2449 else 2418 else
2450 delay = round_jiffies(HZ); 2419 delay = round_jiffies(HZ * 15);
2451 queue_delayed_work(dev->wl->hw->workqueue, &dev->periodic_work, delay); 2420 queue_delayed_work(dev->wl->hw->workqueue, &dev->periodic_work, delay);
2452 out: 2421out:
2453 mutex_unlock(&dev->wl->mutex); 2422 mutex_unlock(&dev->wl->mutex);
2454} 2423}
2455 2424
@@ -3720,6 +3689,7 @@ static int b43_setup_modes(struct b43_wldev *dev,
3720 3689
3721static void b43_wireless_core_detach(struct b43_wldev *dev) 3690static void b43_wireless_core_detach(struct b43_wldev *dev)
3722{ 3691{
3692 b43_rfkill_free(dev);
3723 /* We release firmware that late to not be required to re-request 3693 /* We release firmware that late to not be required to re-request
3724 * is all the time when we reinit the core. */ 3694 * is all the time when we reinit the core. */
3725 b43_release_firmware(dev); 3695 b43_release_firmware(dev);
@@ -3805,6 +3775,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
3805 if (!wl->current_dev) 3775 if (!wl->current_dev)
3806 wl->current_dev = dev; 3776 wl->current_dev = dev;
3807 INIT_WORK(&dev->restart_work, b43_chip_reset); 3777 INIT_WORK(&dev->restart_work, b43_chip_reset);
3778 b43_rfkill_alloc(dev);
3808 3779
3809 b43_radio_turn_off(dev, 1); 3780 b43_radio_turn_off(dev, 1);
3810 b43_switch_analog(dev, 0); 3781 b43_switch_analog(dev, 0);
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}
diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h
index 05db0d67a92e..29544e8c9e5f 100644
--- a/drivers/net/wireless/b43/rfkill.h
+++ b/drivers/net/wireless/b43/rfkill.h
@@ -7,19 +7,25 @@ struct b43_wldev;
7#ifdef CONFIG_B43_RFKILL 7#ifdef CONFIG_B43_RFKILL
8 8
9#include <linux/rfkill.h> 9#include <linux/rfkill.h>
10#include <linux/input-polldev.h>
11
10 12
11struct b43_rfkill { 13struct b43_rfkill {
12 /* The RFKILL subsystem data structure */ 14 /* The RFKILL subsystem data structure */
13 struct rfkill *rfkill; 15 struct rfkill *rfkill;
16 /* The poll device for the RFKILL input button */
17 struct input_polled_dev *poll_dev;
14 /* The unique name of this rfkill switch */ 18 /* The unique name of this rfkill switch */
15 char name[32]; 19 char name[32];
16 /* Workqueue for asynchronous notification. */
17 struct work_struct notify_work;
18}; 20};
19 21
22/* All the init functions return void, because we are not interested
23 * in failing the b43 init process when rfkill init failed. */
24void b43_rfkill_alloc(struct b43_wldev *dev);
25void b43_rfkill_free(struct b43_wldev *dev);
20void b43_rfkill_init(struct b43_wldev *dev); 26void b43_rfkill_init(struct b43_wldev *dev);
21void b43_rfkill_exit(struct b43_wldev *dev); 27void b43_rfkill_exit(struct b43_wldev *dev);
22void b43_rfkill_toggled(struct b43_wldev *dev, bool on); 28
23char * b43_rfkill_led_name(struct b43_wldev *dev); 29char * b43_rfkill_led_name(struct b43_wldev *dev);
24 30
25 31
@@ -30,13 +36,16 @@ struct b43_rfkill {
30 /* empty */ 36 /* empty */
31}; 37};
32 38
33static inline void b43_rfkill_init(struct b43_wldev *dev) 39static inline void b43_rfkill_alloc(struct b43_wldev *dev)
34{ 40{
35} 41}
36static inline void b43_rfkill_exit(struct b43_wldev *dev) 42static inline void b43_rfkill_free(struct b43_wldev *dev)
37{ 43{
38} 44}
39static inline void b43_rfkill_toggled(struct b43_wldev *dev, bool on) 45static inline void b43_rfkill_init(struct b43_wldev *dev)
46{
47}
48static inline void b43_rfkill_exit(struct b43_wldev *dev)
40{ 49{
41} 50}
42static inline char * b43_rfkill_led_name(struct b43_wldev *dev) 51static inline char * b43_rfkill_led_name(struct b43_wldev *dev)