aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/net/wireless/b43legacy/Kconfig2
-rw-r--r--drivers/net/wireless/b43legacy/main.c49
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c135
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.h26
4 files changed, 109 insertions, 103 deletions
diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig
index 68e05f06b33f..9718529af660 100644
--- a/drivers/net/wireless/b43legacy/Kconfig
+++ b/drivers/net/wireless/b43legacy/Kconfig
@@ -43,7 +43,7 @@ config B43LEGACY_LEDS
43# RFKILL support 43# RFKILL support
44config B43LEGACY_RFKILL 44config B43LEGACY_RFKILL
45 bool 45 bool
46 depends on B43LEGACY && RFKILL 46 depends on B43LEGACY && RFKILL && RFKILL_INPUT && INPUT_POLLDEV
47 default y 47 default y
48 48
49config B43LEGACY_DEBUG 49config B43LEGACY_DEBUG
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 04bc3f6c5e63..069abe5fb8ee 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1975,21 +1975,6 @@ static void b43legacy_mgmtframe_txantenna(struct b43legacy_wldev *dev,
1975 B43legacy_SHM_SH_PRPHYCTL, tmp); 1975 B43legacy_SHM_SH_PRPHYCTL, tmp);
1976} 1976}
1977 1977
1978/* Returns TRUE, if the radio is enabled in hardware. */
1979static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
1980{
1981 if (dev->phy.rev >= 3) {
1982 if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
1983 & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
1984 return 1;
1985 } else {
1986 if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
1987 & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
1988 return 1;
1989 }
1990 return 0;
1991}
1992
1993/* This is the opposite of b43legacy_chip_init() */ 1978/* This is the opposite of b43legacy_chip_init() */
1994static void b43legacy_chip_exit(struct b43legacy_wldev *dev) 1979static void b43legacy_chip_exit(struct b43legacy_wldev *dev)
1995{ 1980{
@@ -2146,32 +2131,18 @@ static void b43legacy_periodic_every15sec(struct b43legacy_wldev *dev)
2146 b43legacy_phy_xmitpower(dev); /* FIXME: unless scanning? */ 2131 b43legacy_phy_xmitpower(dev); /* FIXME: unless scanning? */
2147} 2132}
2148 2133
2149static void b43legacy_periodic_every1sec(struct b43legacy_wldev *dev)
2150{
2151 bool radio_hw_enable;
2152
2153 /* check if radio hardware enabled status changed */
2154 radio_hw_enable = b43legacy_is_hw_radio_enabled(dev);
2155 if (unlikely(dev->radio_hw_enable != radio_hw_enable)) {
2156 dev->radio_hw_enable = radio_hw_enable;
2157 b43legacy_rfkill_toggled(dev, radio_hw_enable);
2158 }
2159}
2160
2161static void do_periodic_work(struct b43legacy_wldev *dev) 2134static void do_periodic_work(struct b43legacy_wldev *dev)
2162{ 2135{
2163 unsigned int state; 2136 unsigned int state;
2164 2137
2165 state = dev->periodic_state; 2138 state = dev->periodic_state;
2166 if (state % 120 == 0) 2139 if (state % 8 == 0)
2167 b43legacy_periodic_every120sec(dev); 2140 b43legacy_periodic_every120sec(dev);
2168 if (state % 60 == 0) 2141 if (state % 4 == 0)
2169 b43legacy_periodic_every60sec(dev); 2142 b43legacy_periodic_every60sec(dev);
2170 if (state % 30 == 0) 2143 if (state % 2 == 0)
2171 b43legacy_periodic_every30sec(dev); 2144 b43legacy_periodic_every30sec(dev);
2172 if (state % 15 == 0) 2145 b43legacy_periodic_every15sec(dev);
2173 b43legacy_periodic_every15sec(dev);
2174 b43legacy_periodic_every1sec(dev);
2175} 2146}
2176 2147
2177/* Estimate a "Badness" value based on the periodic work 2148/* Estimate a "Badness" value based on the periodic work
@@ -2182,13 +2153,11 @@ static int estimate_periodic_work_badness(unsigned int state)
2182{ 2153{
2183 int badness = 0; 2154 int badness = 0;
2184 2155
2185 if (state % 120 == 0) /* every 120 sec */ 2156 if (state % 8 == 0) /* every 120 sec */
2186 badness += 10; 2157 badness += 10;
2187 if (state % 60 == 0) /* every 60 sec */ 2158 if (state % 4 == 0) /* every 60 sec */
2188 badness += 5; 2159 badness += 5;
2189 if (state % 30 == 0) /* every 30 sec */ 2160 if (state % 2 == 0) /* every 30 sec */
2190 badness += 1;
2191 if (state % 15 == 0) /* every 15 sec */
2192 badness += 1; 2161 badness += 1;
2193 2162
2194#define BADNESS_LIMIT 4 2163#define BADNESS_LIMIT 4
@@ -2246,7 +2215,7 @@ out_requeue:
2246 if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST)) 2215 if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST))
2247 delay = msecs_to_jiffies(50); 2216 delay = msecs_to_jiffies(50);
2248 else 2217 else
2249 delay = round_jiffies_relative(HZ); 2218 delay = round_jiffies_relative(HZ * 15);
2250 queue_delayed_work(dev->wl->hw->workqueue, 2219 queue_delayed_work(dev->wl->hw->workqueue,
2251 &dev->periodic_work, delay); 2220 &dev->periodic_work, delay);
2252out: 2221out:
@@ -3449,6 +3418,7 @@ static int b43legacy_setup_modes(struct b43legacy_wldev *dev,
3449 3418
3450static void b43legacy_wireless_core_detach(struct b43legacy_wldev *dev) 3419static void b43legacy_wireless_core_detach(struct b43legacy_wldev *dev)
3451{ 3420{
3421 b43legacy_rfkill_free(dev);
3452 /* We release firmware that late to not be required to re-request 3422 /* We release firmware that late to not be required to re-request
3453 * is all the time when we reinit the core. */ 3423 * is all the time when we reinit the core. */
3454 b43legacy_release_firmware(dev); 3424 b43legacy_release_firmware(dev);
@@ -3530,6 +3500,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
3530 if (!wl->current_dev) 3500 if (!wl->current_dev)
3531 wl->current_dev = dev; 3501 wl->current_dev = dev;
3532 INIT_WORK(&dev->restart_work, b43legacy_chip_reset); 3502 INIT_WORK(&dev->restart_work, b43legacy_chip_reset);
3503 b43legacy_rfkill_alloc(dev);
3533 3504
3534 b43legacy_radio_turn_off(dev, 1); 3505 b43legacy_radio_turn_off(dev, 1);
3535 b43legacy_switch_analog(dev, 0); 3506 b43legacy_switch_analog(dev, 0);
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}
diff --git a/drivers/net/wireless/b43legacy/rfkill.h b/drivers/net/wireless/b43legacy/rfkill.h
index 388ee0b855a6..4a81ba3f54f2 100644
--- a/drivers/net/wireless/b43legacy/rfkill.h
+++ b/drivers/net/wireless/b43legacy/rfkill.h
@@ -7,21 +7,27 @@ struct b43legacy_wldev;
7 7
8#include <linux/rfkill.h> 8#include <linux/rfkill.h>
9#include <linux/workqueue.h> 9#include <linux/workqueue.h>
10#include <linux/input-polldev.h>
11
10 12
11 13
12struct b43legacy_rfkill { 14struct b43legacy_rfkill {
13 /* The RFKILL subsystem data structure */ 15 /* The RFKILL subsystem data structure */
14 struct rfkill *rfkill; 16 struct rfkill *rfkill;
17 /* The poll device for the RFKILL input button */
18 struct input_polled_dev *poll_dev;
15 /* The unique name of this rfkill switch */ 19 /* The unique name of this rfkill switch */
16 char name[32]; 20 char name[32];
17 /* Workqueue for asynchronous notification. */
18 struct work_struct notify_work;
19}; 21};
20 22
23/* All the init functions return void, because we are not interested
24 * in failing the b43 init process when rfkill init failed. */
25void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev);
26void b43legacy_rfkill_free(struct b43legacy_wldev *dev);
21void b43legacy_rfkill_init(struct b43legacy_wldev *dev); 27void b43legacy_rfkill_init(struct b43legacy_wldev *dev);
22void b43legacy_rfkill_exit(struct b43legacy_wldev *dev); 28void b43legacy_rfkill_exit(struct b43legacy_wldev *dev);
23void b43legacy_rfkill_toggled(struct b43legacy_wldev *dev, bool on); 29
24char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev); 30char * b43legacy_rfkill_led_name(struct b43legacy_wldev *dev);
25 31
26 32
27#else /* CONFIG_B43LEGACY_RFKILL */ 33#else /* CONFIG_B43LEGACY_RFKILL */
@@ -31,17 +37,19 @@ struct b43legacy_rfkill {
31 /* empty */ 37 /* empty */
32}; 38};
33 39
34static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev) 40static inline void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev)
35{ 41{
36} 42}
37static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev) 43static inline void b43legacy_rfkill_free(struct b43legacy_wldev *dev)
38{ 44{
39} 45}
40static inline void b43legacy_rfkill_toggled(struct b43legacy_wldev *dev, 46static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
41 bool on) 47{
48}
49static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
42{ 50{
43} 51}
44static inline char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev) 52static inline char * b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
45{ 53{
46 return NULL; 54 return NULL;
47} 55}