diff options
-rw-r--r-- | drivers/net/wireless/b43legacy/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/wireless/b43legacy/main.c | 49 | ||||
-rw-r--r-- | drivers/net/wireless/b43legacy/rfkill.c | 135 | ||||
-rw-r--r-- | drivers/net/wireless/b43legacy/rfkill.h | 26 |
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 |
44 | config B43LEGACY_RFKILL | 44 | config 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 | ||
49 | config B43LEGACY_DEBUG | 49 | config 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. */ | ||
1979 | static 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() */ |
1994 | static void b43legacy_chip_exit(struct b43legacy_wldev *dev) | 1979 | static 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 | ||
2149 | static 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 | |||
2161 | static void do_periodic_work(struct b43legacy_wldev *dev) | 2134 | static 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); |
2252 | out: | 2221 | out: |
@@ -3449,6 +3418,7 @@ static int b43legacy_setup_modes(struct b43legacy_wldev *dev, | |||
3449 | 3418 | ||
3450 | static void b43legacy_wireless_core_detach(struct b43legacy_wldev *dev) | 3419 | static 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 | ||
30 | static void b43legacy_notify_rfkill_press(struct work_struct *work) | 30 | /* Returns TRUE, if the radio is enabled in hardware. */ |
31 | static 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. */ | 46 | static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) |
63 | void 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 | ||
109 | char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev) | 100 | char * 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; | ||
131 | err_free_rfk: | ||
132 | rfkill_free(rfk->rfkill); | ||
133 | rfk->rfkill = NULL; | ||
134 | err_free_polldev: | ||
135 | input_free_polled_device(rfk->poll_dev); | ||
136 | rfk->poll_dev = NULL; | ||
137 | } | ||
138 | |||
139 | void 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 | |||
149 | void 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"); |
142 | error: | ||
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 | ||
148 | void b43legacy_rfkill_exit(struct b43legacy_wldev *dev) | 177 | void 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 | ||
12 | struct b43legacy_rfkill { | 14 | struct 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. */ | ||
25 | void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev); | ||
26 | void b43legacy_rfkill_free(struct b43legacy_wldev *dev); | ||
21 | void b43legacy_rfkill_init(struct b43legacy_wldev *dev); | 27 | void b43legacy_rfkill_init(struct b43legacy_wldev *dev); |
22 | void b43legacy_rfkill_exit(struct b43legacy_wldev *dev); | 28 | void b43legacy_rfkill_exit(struct b43legacy_wldev *dev); |
23 | void b43legacy_rfkill_toggled(struct b43legacy_wldev *dev, bool on); | 29 | |
24 | char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev); | 30 | char * 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 | ||
34 | static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev) | 40 | static inline void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev) |
35 | { | 41 | { |
36 | } | 42 | } |
37 | static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev) | 43 | static inline void b43legacy_rfkill_free(struct b43legacy_wldev *dev) |
38 | { | 44 | { |
39 | } | 45 | } |
40 | static inline void b43legacy_rfkill_toggled(struct b43legacy_wldev *dev, | 46 | static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev) |
41 | bool on) | 47 | { |
48 | } | ||
49 | static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev) | ||
42 | { | 50 | { |
43 | } | 51 | } |
44 | static inline char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev) | 52 | static inline char * b43legacy_rfkill_led_name(struct b43legacy_wldev *dev) |
45 | { | 53 | { |
46 | return NULL; | 54 | return NULL; |
47 | } | 55 | } |