aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}