diff options
Diffstat (limited to 'drivers/net/wireless/b43/rfkill.c')
-rw-r--r-- | drivers/net/wireless/b43/rfkill.c | 115 |
1 files changed, 52 insertions, 63 deletions
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 800e0a61a7f5..9b1f905ffbf4 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c | |||
@@ -47,32 +47,35 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) | |||
47 | struct b43_wldev *dev = poll_dev->private; | 47 | struct b43_wldev *dev = poll_dev->private; |
48 | struct b43_wl *wl = dev->wl; | 48 | struct b43_wl *wl = dev->wl; |
49 | bool enabled; | 49 | bool enabled; |
50 | bool report_change = 0; | ||
50 | 51 | ||
51 | mutex_lock(&wl->mutex); | 52 | mutex_lock(&wl->mutex); |
52 | B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); | 53 | B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); |
53 | enabled = b43_is_hw_radio_enabled(dev); | 54 | enabled = b43_is_hw_radio_enabled(dev); |
54 | if (unlikely(enabled != dev->radio_hw_enable)) { | 55 | if (unlikely(enabled != dev->radio_hw_enable)) { |
55 | dev->radio_hw_enable = enabled; | 56 | dev->radio_hw_enable = enabled; |
57 | report_change = 1; | ||
56 | b43info(wl, "Radio hardware status changed to %s\n", | 58 | b43info(wl, "Radio hardware status changed to %s\n", |
57 | enabled ? "ENABLED" : "DISABLED"); | 59 | enabled ? "ENABLED" : "DISABLED"); |
58 | mutex_unlock(&wl->mutex); | 60 | } |
61 | mutex_unlock(&wl->mutex); | ||
62 | |||
63 | if (unlikely(report_change)) | ||
59 | input_report_key(poll_dev->input, KEY_WLAN, enabled); | 64 | input_report_key(poll_dev->input, KEY_WLAN, enabled); |
60 | } else | ||
61 | mutex_unlock(&wl->mutex); | ||
62 | } | 65 | } |
63 | 66 | ||
64 | /* Called when the RFKILL toggled in software. | 67 | /* Called when the RFKILL toggled in software. */ |
65 | * This is called without locking. */ | ||
66 | static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) | 68 | static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) |
67 | { | 69 | { |
68 | struct b43_wldev *dev = data; | 70 | struct b43_wldev *dev = data; |
69 | struct b43_wl *wl = dev->wl; | 71 | struct b43_wl *wl = dev->wl; |
70 | int err = 0; | 72 | int err = 0; |
71 | 73 | ||
72 | mutex_lock(&wl->mutex); | 74 | if (!wl->rfkill.registered) |
73 | if (b43_status(dev) < B43_STAT_INITIALIZED) | 75 | return 0; |
74 | goto out_unlock; | ||
75 | 76 | ||
77 | mutex_lock(&wl->mutex); | ||
78 | B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); | ||
76 | switch (state) { | 79 | switch (state) { |
77 | case RFKILL_STATE_ON: | 80 | case RFKILL_STATE_ON: |
78 | if (!dev->radio_hw_enable) { | 81 | if (!dev->radio_hw_enable) { |
@@ -89,7 +92,6 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) | |||
89 | b43_radio_turn_off(dev, 0); | 92 | b43_radio_turn_off(dev, 0); |
90 | break; | 93 | break; |
91 | } | 94 | } |
92 | |||
93 | out_unlock: | 95 | out_unlock: |
94 | mutex_unlock(&wl->mutex); | 96 | mutex_unlock(&wl->mutex); |
95 | 97 | ||
@@ -98,11 +100,11 @@ out_unlock: | |||
98 | 100 | ||
99 | char * b43_rfkill_led_name(struct b43_wldev *dev) | 101 | char * b43_rfkill_led_name(struct b43_wldev *dev) |
100 | { | 102 | { |
101 | struct b43_wl *wl = dev->wl; | 103 | struct b43_rfkill *rfk = &(dev->wl->rfkill); |
102 | 104 | ||
103 | if (!wl->rfkill.rfkill) | 105 | if (!rfk->registered) |
104 | return NULL; | 106 | return NULL; |
105 | return rfkill_get_led_name(wl->rfkill.rfkill); | 107 | return rfkill_get_led_name(rfk->rfkill); |
106 | } | 108 | } |
107 | 109 | ||
108 | void b43_rfkill_init(struct b43_wldev *dev) | 110 | void b43_rfkill_init(struct b43_wldev *dev) |
@@ -111,53 +113,13 @@ void b43_rfkill_init(struct b43_wldev *dev) | |||
111 | struct b43_rfkill *rfk = &(wl->rfkill); | 113 | struct b43_rfkill *rfk = &(wl->rfkill); |
112 | int err; | 114 | int err; |
113 | 115 | ||
114 | if (rfk->rfkill) { | 116 | rfk->registered = 0; |
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; | ||
130 | err_free_rfk: | ||
131 | rfkill_free(rfk->rfkill); | ||
132 | rfk->rfkill = NULL; | ||
133 | err_free_polldev: | ||
134 | input_free_polled_device(rfk->poll_dev); | ||
135 | rfk->poll_dev = NULL; | ||
136 | } | ||
137 | |||
138 | void 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 | |||
148 | void b43_rfkill_alloc(struct b43_wldev *dev) | ||
149 | { | ||
150 | struct b43_wl *wl = dev->wl; | ||
151 | struct b43_rfkill *rfk = &(wl->rfkill); | ||
152 | 117 | ||
118 | rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); | ||
119 | if (!rfk->rfkill) | ||
120 | goto out_error; | ||
153 | snprintf(rfk->name, sizeof(rfk->name), | 121 | snprintf(rfk->name, sizeof(rfk->name), |
154 | "b43-%s", wiphy_name(wl->hw->wiphy)); | 122 | "b43-%s", wiphy_name(wl->hw->wiphy)); |
155 | |||
156 | rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); | ||
157 | if (!rfk->rfkill) { | ||
158 | b43warn(wl, "Failed to allocate RF-kill button\n"); | ||
159 | return; | ||
160 | } | ||
161 | rfk->rfkill->name = rfk->name; | 123 | rfk->rfkill->name = rfk->name; |
162 | rfk->rfkill->state = RFKILL_STATE_ON; | 124 | rfk->rfkill->state = RFKILL_STATE_ON; |
163 | rfk->rfkill->data = dev; | 125 | rfk->rfkill->data = dev; |
@@ -165,18 +127,45 @@ void b43_rfkill_alloc(struct b43_wldev *dev) | |||
165 | rfk->rfkill->user_claim_unsupported = 1; | 127 | rfk->rfkill->user_claim_unsupported = 1; |
166 | 128 | ||
167 | rfk->poll_dev = input_allocate_polled_device(); | 129 | rfk->poll_dev = input_allocate_polled_device(); |
168 | if (rfk->poll_dev) { | 130 | if (!rfk->poll_dev) |
169 | rfk->poll_dev->private = dev; | 131 | goto err_free_rfk; |
170 | rfk->poll_dev->poll = b43_rfkill_poll; | 132 | rfk->poll_dev->private = dev; |
171 | rfk->poll_dev->poll_interval = 1000; /* msecs */ | 133 | rfk->poll_dev->poll = b43_rfkill_poll; |
172 | } else | 134 | rfk->poll_dev->poll_interval = 1000; /* msecs */ |
173 | b43warn(wl, "Failed to allocate RF-kill polldev\n"); | 135 | |
136 | err = rfkill_register(rfk->rfkill); | ||
137 | if (err) | ||
138 | goto err_free_polldev; | ||
139 | err = input_register_polled_device(rfk->poll_dev); | ||
140 | if (err) | ||
141 | goto err_unreg_rfk; | ||
142 | |||
143 | rfk->registered = 1; | ||
144 | |||
145 | return; | ||
146 | err_unreg_rfk: | ||
147 | rfkill_unregister(rfk->rfkill); | ||
148 | err_free_polldev: | ||
149 | input_free_polled_device(rfk->poll_dev); | ||
150 | rfk->poll_dev = NULL; | ||
151 | err_free_rfk: | ||
152 | rfkill_free(rfk->rfkill); | ||
153 | rfk->rfkill = NULL; | ||
154 | out_error: | ||
155 | rfk->registered = 0; | ||
156 | b43warn(wl, "RF-kill button init failed\n"); | ||
174 | } | 157 | } |
175 | 158 | ||
176 | void b43_rfkill_free(struct b43_wldev *dev) | 159 | void b43_rfkill_exit(struct b43_wldev *dev) |
177 | { | 160 | { |
178 | struct b43_rfkill *rfk = &(dev->wl->rfkill); | 161 | struct b43_rfkill *rfk = &(dev->wl->rfkill); |
179 | 162 | ||
163 | if (!rfk->registered) | ||
164 | return; | ||
165 | rfk->registered = 0; | ||
166 | |||
167 | input_unregister_polled_device(rfk->poll_dev); | ||
168 | rfkill_unregister(rfk->rfkill); | ||
180 | input_free_polled_device(rfk->poll_dev); | 169 | input_free_polled_device(rfk->poll_dev); |
181 | rfk->poll_dev = NULL; | 170 | rfk->poll_dev = NULL; |
182 | rfkill_free(rfk->rfkill); | 171 | rfkill_free(rfk->rfkill); |