diff options
Diffstat (limited to 'drivers/uwb')
-rw-r--r-- | drivers/uwb/Makefile | 2 | ||||
-rw-r--r-- | drivers/uwb/beacon.c | 122 | ||||
-rw-r--r-- | drivers/uwb/driver.c | 2 | ||||
-rw-r--r-- | drivers/uwb/drp-ie.c | 1 | ||||
-rw-r--r-- | drivers/uwb/drp.c | 24 | ||||
-rw-r--r-- | drivers/uwb/hwa-rc.c | 23 | ||||
-rw-r--r-- | drivers/uwb/i1480/dfu/usb.c | 1 | ||||
-rw-r--r-- | drivers/uwb/i1480/i1480u-wlp/lc.c | 3 | ||||
-rw-r--r-- | drivers/uwb/i1480/i1480u-wlp/netdev.c | 51 | ||||
-rw-r--r-- | drivers/uwb/i1480/i1480u-wlp/sysfs.c | 1 | ||||
-rw-r--r-- | drivers/uwb/ie-rcv.c | 55 | ||||
-rw-r--r-- | drivers/uwb/ie.c | 463 | ||||
-rw-r--r-- | drivers/uwb/lc-rc.c | 62 | ||||
-rw-r--r-- | drivers/uwb/neh.c | 46 | ||||
-rw-r--r-- | drivers/uwb/pal.c | 25 | ||||
-rw-r--r-- | drivers/uwb/radio.c | 202 | ||||
-rw-r--r-- | drivers/uwb/reset.c | 45 | ||||
-rw-r--r-- | drivers/uwb/rsv.c | 88 | ||||
-rw-r--r-- | drivers/uwb/umc-bus.c | 62 | ||||
-rw-r--r-- | drivers/uwb/umc-dev.c | 3 | ||||
-rw-r--r-- | drivers/uwb/uwb-debug.c | 81 | ||||
-rw-r--r-- | drivers/uwb/uwb-internal.h | 46 | ||||
-rw-r--r-- | drivers/uwb/uwbd.c | 102 | ||||
-rw-r--r-- | drivers/uwb/whc-rc.c | 65 | ||||
-rw-r--r-- | drivers/uwb/whci.c | 6 | ||||
-rw-r--r-- | drivers/uwb/wlp/wlp-internal.h | 4 | ||||
-rw-r--r-- | drivers/uwb/wlp/wlp-lc.c | 19 |
27 files changed, 871 insertions, 733 deletions
diff --git a/drivers/uwb/Makefile b/drivers/uwb/Makefile index 257e6908304c..ce21a95da04a 100644 --- a/drivers/uwb/Makefile +++ b/drivers/uwb/Makefile | |||
@@ -13,10 +13,12 @@ uwb-objs := \ | |||
13 | drp-ie.o \ | 13 | drp-ie.o \ |
14 | est.o \ | 14 | est.o \ |
15 | ie.o \ | 15 | ie.o \ |
16 | ie-rcv.o \ | ||
16 | lc-dev.o \ | 17 | lc-dev.o \ |
17 | lc-rc.o \ | 18 | lc-rc.o \ |
18 | neh.o \ | 19 | neh.o \ |
19 | pal.o \ | 20 | pal.o \ |
21 | radio.o \ | ||
20 | reset.o \ | 22 | reset.o \ |
21 | rsv.o \ | 23 | rsv.o \ |
22 | scan.o \ | 24 | scan.o \ |
diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c index 46b18eec5026..d9c60cb94993 100644 --- a/drivers/uwb/beacon.c +++ b/drivers/uwb/beacon.c | |||
@@ -119,7 +119,6 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset) | |||
119 | int result; | 119 | int result; |
120 | struct device *dev = &rc->uwb_dev.dev; | 120 | struct device *dev = &rc->uwb_dev.dev; |
121 | 121 | ||
122 | mutex_lock(&rc->uwb_dev.mutex); | ||
123 | if (channel < 0) | 122 | if (channel < 0) |
124 | channel = -1; | 123 | channel = -1; |
125 | if (channel == -1) | 124 | if (channel == -1) |
@@ -128,7 +127,7 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset) | |||
128 | /* channel >= 0...dah */ | 127 | /* channel >= 0...dah */ |
129 | result = uwb_rc_start_beacon(rc, bpst_offset, channel); | 128 | result = uwb_rc_start_beacon(rc, bpst_offset, channel); |
130 | if (result < 0) | 129 | if (result < 0) |
131 | goto out_up; | 130 | return result; |
132 | if (le16_to_cpu(rc->ies->wIELength) > 0) { | 131 | if (le16_to_cpu(rc->ies->wIELength) > 0) { |
133 | result = uwb_rc_set_ie(rc, rc->ies); | 132 | result = uwb_rc_set_ie(rc, rc->ies); |
134 | if (result < 0) { | 133 | if (result < 0) { |
@@ -137,19 +136,12 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset) | |||
137 | result = uwb_rc_stop_beacon(rc); | 136 | result = uwb_rc_stop_beacon(rc); |
138 | channel = -1; | 137 | channel = -1; |
139 | bpst_offset = 0; | 138 | bpst_offset = 0; |
140 | } else | 139 | } |
141 | result = 0; | ||
142 | } | 140 | } |
143 | } | 141 | } |
144 | 142 | ||
145 | if (result < 0) | 143 | if (result >= 0) |
146 | goto out_up; | 144 | rc->beaconing = channel; |
147 | rc->beaconing = channel; | ||
148 | |||
149 | uwb_notify(rc, NULL, uwb_bg_joined(rc) ? UWB_NOTIF_BG_JOIN : UWB_NOTIF_BG_LEAVE); | ||
150 | |||
151 | out_up: | ||
152 | mutex_unlock(&rc->uwb_dev.mutex); | ||
153 | return result; | 145 | return result; |
154 | } | 146 | } |
155 | 147 | ||
@@ -168,12 +160,6 @@ out_up: | |||
168 | * FIXME: use something faster for search than a list | 160 | * FIXME: use something faster for search than a list |
169 | */ | 161 | */ |
170 | 162 | ||
171 | struct uwb_beca uwb_beca = { | ||
172 | .list = LIST_HEAD_INIT(uwb_beca.list), | ||
173 | .mutex = __MUTEX_INITIALIZER(uwb_beca.mutex) | ||
174 | }; | ||
175 | |||
176 | |||
177 | void uwb_bce_kfree(struct kref *_bce) | 163 | void uwb_bce_kfree(struct kref *_bce) |
178 | { | 164 | { |
179 | struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt); | 165 | struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt); |
@@ -185,10 +171,11 @@ void uwb_bce_kfree(struct kref *_bce) | |||
185 | 171 | ||
186 | /* Find a beacon by dev addr in the cache */ | 172 | /* Find a beacon by dev addr in the cache */ |
187 | static | 173 | static |
188 | struct uwb_beca_e *__uwb_beca_find_bydev(const struct uwb_dev_addr *dev_addr) | 174 | struct uwb_beca_e *__uwb_beca_find_bydev(struct uwb_rc *rc, |
175 | const struct uwb_dev_addr *dev_addr) | ||
189 | { | 176 | { |
190 | struct uwb_beca_e *bce, *next; | 177 | struct uwb_beca_e *bce, *next; |
191 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 178 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
192 | d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n", | 179 | d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n", |
193 | dev_addr->data[0], dev_addr->data[1], | 180 | dev_addr->data[0], dev_addr->data[1], |
194 | bce->dev_addr.data[0], bce->dev_addr.data[1]); | 181 | bce->dev_addr.data[0], bce->dev_addr.data[1]); |
@@ -202,10 +189,11 @@ out: | |||
202 | 189 | ||
203 | /* Find a beacon by dev addr in the cache */ | 190 | /* Find a beacon by dev addr in the cache */ |
204 | static | 191 | static |
205 | struct uwb_beca_e *__uwb_beca_find_bymac(const struct uwb_mac_addr *mac_addr) | 192 | struct uwb_beca_e *__uwb_beca_find_bymac(struct uwb_rc *rc, |
193 | const struct uwb_mac_addr *mac_addr) | ||
206 | { | 194 | { |
207 | struct uwb_beca_e *bce, *next; | 195 | struct uwb_beca_e *bce, *next; |
208 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 196 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
209 | if (!memcmp(bce->mac_addr, mac_addr->data, | 197 | if (!memcmp(bce->mac_addr, mac_addr->data, |
210 | sizeof(struct uwb_mac_addr))) | 198 | sizeof(struct uwb_mac_addr))) |
211 | goto out; | 199 | goto out; |
@@ -229,11 +217,11 @@ struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, | |||
229 | struct uwb_dev *found = NULL; | 217 | struct uwb_dev *found = NULL; |
230 | struct uwb_beca_e *bce; | 218 | struct uwb_beca_e *bce; |
231 | 219 | ||
232 | mutex_lock(&uwb_beca.mutex); | 220 | mutex_lock(&rc->uwb_beca.mutex); |
233 | bce = __uwb_beca_find_bydev(devaddr); | 221 | bce = __uwb_beca_find_bydev(rc, devaddr); |
234 | if (bce) | 222 | if (bce) |
235 | found = uwb_dev_try_get(rc, bce->uwb_dev); | 223 | found = uwb_dev_try_get(rc, bce->uwb_dev); |
236 | mutex_unlock(&uwb_beca.mutex); | 224 | mutex_unlock(&rc->uwb_beca.mutex); |
237 | 225 | ||
238 | return found; | 226 | return found; |
239 | } | 227 | } |
@@ -249,11 +237,11 @@ struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, | |||
249 | struct uwb_dev *found = NULL; | 237 | struct uwb_dev *found = NULL; |
250 | struct uwb_beca_e *bce; | 238 | struct uwb_beca_e *bce; |
251 | 239 | ||
252 | mutex_lock(&uwb_beca.mutex); | 240 | mutex_lock(&rc->uwb_beca.mutex); |
253 | bce = __uwb_beca_find_bymac(macaddr); | 241 | bce = __uwb_beca_find_bymac(rc, macaddr); |
254 | if (bce) | 242 | if (bce) |
255 | found = uwb_dev_try_get(rc, bce->uwb_dev); | 243 | found = uwb_dev_try_get(rc, bce->uwb_dev); |
256 | mutex_unlock(&uwb_beca.mutex); | 244 | mutex_unlock(&rc->uwb_beca.mutex); |
257 | 245 | ||
258 | return found; | 246 | return found; |
259 | } | 247 | } |
@@ -274,7 +262,9 @@ static void uwb_beca_e_init(struct uwb_beca_e *bce) | |||
274 | * @bf: Beacon frame (part of b, really) | 262 | * @bf: Beacon frame (part of b, really) |
275 | * @ts_jiffies: Timestamp (in jiffies) when the beacon was received | 263 | * @ts_jiffies: Timestamp (in jiffies) when the beacon was received |
276 | */ | 264 | */ |
277 | struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | 265 | static |
266 | struct uwb_beca_e *__uwb_beca_add(struct uwb_rc *rc, | ||
267 | struct uwb_rc_evt_beacon *be, | ||
278 | struct uwb_beacon_frame *bf, | 268 | struct uwb_beacon_frame *bf, |
279 | unsigned long ts_jiffies) | 269 | unsigned long ts_jiffies) |
280 | { | 270 | { |
@@ -286,7 +276,7 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | |||
286 | uwb_beca_e_init(bce); | 276 | uwb_beca_e_init(bce); |
287 | bce->ts_jiffies = ts_jiffies; | 277 | bce->ts_jiffies = ts_jiffies; |
288 | bce->uwb_dev = NULL; | 278 | bce->uwb_dev = NULL; |
289 | list_add(&bce->node, &uwb_beca.list); | 279 | list_add(&bce->node, &rc->uwb_beca.list); |
290 | return bce; | 280 | return bce; |
291 | } | 281 | } |
292 | 282 | ||
@@ -295,13 +285,13 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | |||
295 | * | 285 | * |
296 | * Remove associated devicest too. | 286 | * Remove associated devicest too. |
297 | */ | 287 | */ |
298 | void uwb_beca_purge(void) | 288 | void uwb_beca_purge(struct uwb_rc *rc) |
299 | { | 289 | { |
300 | struct uwb_beca_e *bce, *next; | 290 | struct uwb_beca_e *bce, *next; |
301 | unsigned long expires; | 291 | unsigned long expires; |
302 | 292 | ||
303 | mutex_lock(&uwb_beca.mutex); | 293 | mutex_lock(&rc->uwb_beca.mutex); |
304 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 294 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
305 | expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms); | 295 | expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms); |
306 | if (time_after(jiffies, expires)) { | 296 | if (time_after(jiffies, expires)) { |
307 | uwbd_dev_offair(bce); | 297 | uwbd_dev_offair(bce); |
@@ -309,19 +299,20 @@ void uwb_beca_purge(void) | |||
309 | uwb_bce_put(bce); | 299 | uwb_bce_put(bce); |
310 | } | 300 | } |
311 | } | 301 | } |
312 | mutex_unlock(&uwb_beca.mutex); | 302 | mutex_unlock(&rc->uwb_beca.mutex); |
313 | } | 303 | } |
314 | 304 | ||
315 | /* Clean up the whole beacon cache. Called on shutdown */ | 305 | /* Clean up the whole beacon cache. Called on shutdown */ |
316 | void uwb_beca_release(void) | 306 | void uwb_beca_release(struct uwb_rc *rc) |
317 | { | 307 | { |
318 | struct uwb_beca_e *bce, *next; | 308 | struct uwb_beca_e *bce, *next; |
319 | mutex_lock(&uwb_beca.mutex); | 309 | |
320 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 310 | mutex_lock(&rc->uwb_beca.mutex); |
311 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { | ||
321 | list_del(&bce->node); | 312 | list_del(&bce->node); |
322 | uwb_bce_put(bce); | 313 | uwb_bce_put(bce); |
323 | } | 314 | } |
324 | mutex_unlock(&uwb_beca.mutex); | 315 | mutex_unlock(&rc->uwb_beca.mutex); |
325 | } | 316 | } |
326 | 317 | ||
327 | static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be, | 318 | static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be, |
@@ -349,22 +340,22 @@ ssize_t uwb_bce_print_IEs(struct uwb_dev *uwb_dev, struct uwb_beca_e *bce, | |||
349 | ssize_t result = 0; | 340 | ssize_t result = 0; |
350 | struct uwb_rc_evt_beacon *be; | 341 | struct uwb_rc_evt_beacon *be; |
351 | struct uwb_beacon_frame *bf; | 342 | struct uwb_beacon_frame *bf; |
352 | struct uwb_buf_ctx ctx = { | 343 | int ies_len; |
353 | .buf = buf, | 344 | struct uwb_ie_hdr *ies; |
354 | .bytes = 0, | ||
355 | .size = size | ||
356 | }; | ||
357 | 345 | ||
358 | mutex_lock(&bce->mutex); | 346 | mutex_lock(&bce->mutex); |
347 | |||
359 | be = bce->be; | 348 | be = bce->be; |
360 | if (be == NULL) | 349 | if (be) { |
361 | goto out; | 350 | bf = (struct uwb_beacon_frame *)bce->be->BeaconInfo; |
362 | bf = (void *) be->BeaconInfo; | 351 | ies_len = be->wBeaconInfoLength - sizeof(struct uwb_beacon_frame); |
363 | uwb_ie_for_each(uwb_dev, uwb_ie_dump_hex, &ctx, | 352 | ies = (struct uwb_ie_hdr *)bf->IEData; |
364 | bf->IEData, be->wBeaconInfoLength - sizeof(*bf)); | 353 | |
365 | result = ctx.bytes; | 354 | result = uwb_ie_dump_hex(ies, ies_len, buf, size); |
366 | out: | 355 | } |
356 | |||
367 | mutex_unlock(&bce->mutex); | 357 | mutex_unlock(&bce->mutex); |
358 | |||
368 | return result; | 359 | return result; |
369 | } | 360 | } |
370 | 361 | ||
@@ -437,18 +428,18 @@ int uwbd_evt_handle_rc_beacon(struct uwb_event *evt) | |||
437 | if (uwb_mac_addr_bcast(&bf->Device_Identifier)) | 428 | if (uwb_mac_addr_bcast(&bf->Device_Identifier)) |
438 | return 0; | 429 | return 0; |
439 | 430 | ||
440 | mutex_lock(&uwb_beca.mutex); | 431 | mutex_lock(&rc->uwb_beca.mutex); |
441 | bce = __uwb_beca_find_bymac(&bf->Device_Identifier); | 432 | bce = __uwb_beca_find_bymac(rc, &bf->Device_Identifier); |
442 | if (bce == NULL) { | 433 | if (bce == NULL) { |
443 | /* Not in there, a new device is pinging */ | 434 | /* Not in there, a new device is pinging */ |
444 | uwb_beacon_print(evt->rc, be, bf); | 435 | uwb_beacon_print(evt->rc, be, bf); |
445 | bce = __uwb_beca_add(be, bf, evt->ts_jiffies); | 436 | bce = __uwb_beca_add(rc, be, bf, evt->ts_jiffies); |
446 | if (bce == NULL) { | 437 | if (bce == NULL) { |
447 | mutex_unlock(&uwb_beca.mutex); | 438 | mutex_unlock(&rc->uwb_beca.mutex); |
448 | return -ENOMEM; | 439 | return -ENOMEM; |
449 | } | 440 | } |
450 | } | 441 | } |
451 | mutex_unlock(&uwb_beca.mutex); | 442 | mutex_unlock(&rc->uwb_beca.mutex); |
452 | 443 | ||
453 | mutex_lock(&bce->mutex); | 444 | mutex_lock(&bce->mutex); |
454 | /* purge old beacon data */ | 445 | /* purge old beacon data */ |
@@ -588,19 +579,6 @@ error: | |||
588 | return result; | 579 | return result; |
589 | } | 580 | } |
590 | 581 | ||
591 | /** | ||
592 | * uwb_bg_joined - is the RC in a beacon group? | ||
593 | * @rc: the radio controller | ||
594 | * | ||
595 | * Returns true if the radio controller is in a beacon group (even if | ||
596 | * it's the sole member). | ||
597 | */ | ||
598 | int uwb_bg_joined(struct uwb_rc *rc) | ||
599 | { | ||
600 | return rc->beaconing != -1; | ||
601 | } | ||
602 | EXPORT_SYMBOL_GPL(uwb_bg_joined); | ||
603 | |||
604 | /* | 582 | /* |
605 | * Print beaconing state. | 583 | * Print beaconing state. |
606 | */ | 584 | */ |
@@ -619,9 +597,6 @@ static ssize_t uwb_rc_beacon_show(struct device *dev, | |||
619 | 597 | ||
620 | /* | 598 | /* |
621 | * Start beaconing on the specified channel, or stop beaconing. | 599 | * Start beaconing on the specified channel, or stop beaconing. |
622 | * | ||
623 | * The BPST offset of when to start searching for a beacon group to | ||
624 | * join may be specified. | ||
625 | */ | 600 | */ |
626 | static ssize_t uwb_rc_beacon_store(struct device *dev, | 601 | static ssize_t uwb_rc_beacon_store(struct device *dev, |
627 | struct device_attribute *attr, | 602 | struct device_attribute *attr, |
@@ -630,12 +605,11 @@ static ssize_t uwb_rc_beacon_store(struct device *dev, | |||
630 | struct uwb_dev *uwb_dev = to_uwb_dev(dev); | 605 | struct uwb_dev *uwb_dev = to_uwb_dev(dev); |
631 | struct uwb_rc *rc = uwb_dev->rc; | 606 | struct uwb_rc *rc = uwb_dev->rc; |
632 | int channel; | 607 | int channel; |
633 | unsigned bpst_offset = 0; | ||
634 | ssize_t result = -EINVAL; | 608 | ssize_t result = -EINVAL; |
635 | 609 | ||
636 | result = sscanf(buf, "%d %u\n", &channel, &bpst_offset); | 610 | result = sscanf(buf, "%d", &channel); |
637 | if (result >= 1) | 611 | if (result >= 1) |
638 | result = uwb_rc_beacon(rc, channel, bpst_offset); | 612 | result = uwb_radio_force_channel(rc, channel); |
639 | 613 | ||
640 | return result < 0 ? result : size; | 614 | return result < 0 ? result : size; |
641 | } | 615 | } |
diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c index 521cdeb84971..f57c26580de2 100644 --- a/drivers/uwb/driver.c +++ b/drivers/uwb/driver.c | |||
@@ -118,7 +118,6 @@ static int __init uwb_subsys_init(void) | |||
118 | result = class_register(&uwb_rc_class); | 118 | result = class_register(&uwb_rc_class); |
119 | if (result < 0) | 119 | if (result < 0) |
120 | goto error_uwb_rc_class_register; | 120 | goto error_uwb_rc_class_register; |
121 | uwbd_start(); | ||
122 | uwb_dbg_init(); | 121 | uwb_dbg_init(); |
123 | return 0; | 122 | return 0; |
124 | 123 | ||
@@ -132,7 +131,6 @@ module_init(uwb_subsys_init); | |||
132 | static void __exit uwb_subsys_exit(void) | 131 | static void __exit uwb_subsys_exit(void) |
133 | { | 132 | { |
134 | uwb_dbg_exit(); | 133 | uwb_dbg_exit(); |
135 | uwbd_stop(); | ||
136 | class_unregister(&uwb_rc_class); | 134 | class_unregister(&uwb_rc_class); |
137 | uwb_est_destroy(); | 135 | uwb_est_destroy(); |
138 | return; | 136 | return; |
diff --git a/drivers/uwb/drp-ie.c b/drivers/uwb/drp-ie.c index 882724c5f126..75491d47806b 100644 --- a/drivers/uwb/drp-ie.c +++ b/drivers/uwb/drp-ie.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 | */ | 18 | */ |
19 | #include <linux/version.h> | ||
20 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
21 | #include <linux/random.h> | 20 | #include <linux/random.h> |
22 | #include <linux/uwb.h> | 21 | #include <linux/uwb.h> |
diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c index c0b1e5e2bd08..fe328146adb7 100644 --- a/drivers/uwb/drp.c +++ b/drivers/uwb/drp.c | |||
@@ -37,14 +37,13 @@ | |||
37 | * | 37 | * |
38 | * A DRP Availability IE is appended. | 38 | * A DRP Availability IE is appended. |
39 | * | 39 | * |
40 | * rc->uwb_dev.mutex is held | 40 | * rc->rsvs_mutex is held |
41 | * | 41 | * |
42 | * FIXME We currently ignore the returned value indicating the remaining space | 42 | * FIXME We currently ignore the returned value indicating the remaining space |
43 | * in beacon. This could be used to deny reservation requests earlier if | 43 | * in beacon. This could be used to deny reservation requests earlier if |
44 | * determined that they would cause the beacon space to be exceeded. | 44 | * determined that they would cause the beacon space to be exceeded. |
45 | */ | 45 | */ |
46 | static | 46 | int uwb_rc_send_all_drp_ie(struct uwb_rc *rc) |
47 | int uwb_rc_gen_send_drp_ie(struct uwb_rc *rc) | ||
48 | { | 47 | { |
49 | int result; | 48 | int result; |
50 | struct device *dev = &rc->uwb_dev.dev; | 49 | struct device *dev = &rc->uwb_dev.dev; |
@@ -102,25 +101,6 @@ error_cmd: | |||
102 | kfree(cmd); | 101 | kfree(cmd); |
103 | error: | 102 | error: |
104 | return result; | 103 | return result; |
105 | |||
106 | } | ||
107 | /** | ||
108 | * Send all DRP IEs associated with this host | ||
109 | * | ||
110 | * @returns: >= 0 number of bytes still available in the beacon | ||
111 | * < 0 errno code on error. | ||
112 | * | ||
113 | * As per the protocol we obtain the host controller device lock to access | ||
114 | * bandwidth structures. | ||
115 | */ | ||
116 | int uwb_rc_send_all_drp_ie(struct uwb_rc *rc) | ||
117 | { | ||
118 | int result; | ||
119 | |||
120 | mutex_lock(&rc->uwb_dev.mutex); | ||
121 | result = uwb_rc_gen_send_drp_ie(rc); | ||
122 | mutex_unlock(&rc->uwb_dev.mutex); | ||
123 | return result; | ||
124 | } | 104 | } |
125 | 105 | ||
126 | void uwb_drp_handle_timeout(struct uwb_rsv *rsv) | 106 | void uwb_drp_handle_timeout(struct uwb_rsv *rsv) |
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 3d26fa0f8ae1..158e98d08af9 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c | |||
@@ -51,7 +51,6 @@ | |||
51 | * | 51 | * |
52 | * | 52 | * |
53 | */ | 53 | */ |
54 | #include <linux/version.h> | ||
55 | #include <linux/init.h> | 54 | #include <linux/init.h> |
56 | #include <linux/module.h> | 55 | #include <linux/module.h> |
57 | #include <linux/usb.h> | 56 | #include <linux/usb.h> |
@@ -882,6 +881,24 @@ static void hwarc_disconnect(struct usb_interface *iface) | |||
882 | uwb_rc_put(uwb_rc); /* when creating the device, refcount = 1 */ | 881 | uwb_rc_put(uwb_rc); /* when creating the device, refcount = 1 */ |
883 | } | 882 | } |
884 | 883 | ||
884 | static int hwarc_pre_reset(struct usb_interface *iface) | ||
885 | { | ||
886 | struct hwarc *hwarc = usb_get_intfdata(iface); | ||
887 | struct uwb_rc *uwb_rc = hwarc->uwb_rc; | ||
888 | |||
889 | uwb_rc_pre_reset(uwb_rc); | ||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | static int hwarc_post_reset(struct usb_interface *iface) | ||
894 | { | ||
895 | struct hwarc *hwarc = usb_get_intfdata(iface); | ||
896 | struct uwb_rc *uwb_rc = hwarc->uwb_rc; | ||
897 | |||
898 | uwb_rc_post_reset(uwb_rc); | ||
899 | return 0; | ||
900 | } | ||
901 | |||
885 | /** USB device ID's that we handle */ | 902 | /** USB device ID's that we handle */ |
886 | static struct usb_device_id hwarc_id_table[] = { | 903 | static struct usb_device_id hwarc_id_table[] = { |
887 | /* D-Link DUB-1210 */ | 904 | /* D-Link DUB-1210 */ |
@@ -898,9 +915,11 @@ MODULE_DEVICE_TABLE(usb, hwarc_id_table); | |||
898 | 915 | ||
899 | static struct usb_driver hwarc_driver = { | 916 | static struct usb_driver hwarc_driver = { |
900 | .name = "hwa-rc", | 917 | .name = "hwa-rc", |
918 | .id_table = hwarc_id_table, | ||
901 | .probe = hwarc_probe, | 919 | .probe = hwarc_probe, |
902 | .disconnect = hwarc_disconnect, | 920 | .disconnect = hwarc_disconnect, |
903 | .id_table = hwarc_id_table, | 921 | .pre_reset = hwarc_pre_reset, |
922 | .post_reset = hwarc_post_reset, | ||
904 | }; | 923 | }; |
905 | 924 | ||
906 | static int __init hwarc_driver_init(void) | 925 | static int __init hwarc_driver_init(void) |
diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c index 98eeeff051aa..b7ea525fc06a 100644 --- a/drivers/uwb/i1480/dfu/usb.c +++ b/drivers/uwb/i1480/dfu/usb.c | |||
@@ -35,7 +35,6 @@ | |||
35 | * the functions are i1480_usb_NAME(). | 35 | * the functions are i1480_usb_NAME(). |
36 | */ | 36 | */ |
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | #include <linux/version.h> | ||
39 | #include <linux/usb.h> | 38 | #include <linux/usb.h> |
40 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
41 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
diff --git a/drivers/uwb/i1480/i1480u-wlp/lc.c b/drivers/uwb/i1480/i1480u-wlp/lc.c index 737d60cd5b73..488b2e30a0a8 100644 --- a/drivers/uwb/i1480/i1480u-wlp/lc.c +++ b/drivers/uwb/i1480/i1480u-wlp/lc.c | |||
@@ -55,7 +55,6 @@ | |||
55 | * is being removed. | 55 | * is being removed. |
56 | * i1480u_rm() | 56 | * i1480u_rm() |
57 | */ | 57 | */ |
58 | #include <linux/version.h> | ||
59 | #include <linux/if_arp.h> | 58 | #include <linux/if_arp.h> |
60 | #include <linux/etherdevice.h> | 59 | #include <linux/etherdevice.h> |
61 | #include <linux/uwb/debug.h> | 60 | #include <linux/uwb/debug.h> |
@@ -207,7 +206,7 @@ int i1480u_add(struct i1480u *i1480u, struct usb_interface *iface) | |||
207 | wlp->fill_device_info = i1480u_fill_device_info; | 206 | wlp->fill_device_info = i1480u_fill_device_info; |
208 | wlp->stop_queue = i1480u_stop_queue; | 207 | wlp->stop_queue = i1480u_stop_queue; |
209 | wlp->start_queue = i1480u_start_queue; | 208 | wlp->start_queue = i1480u_start_queue; |
210 | result = wlp_setup(wlp, rc); | 209 | result = wlp_setup(wlp, rc, net_dev); |
211 | if (result < 0) { | 210 | if (result < 0) { |
212 | dev_err(&iface->dev, "Cannot setup WLP\n"); | 211 | dev_err(&iface->dev, "Cannot setup WLP\n"); |
213 | goto error_wlp_setup; | 212 | goto error_wlp_setup; |
diff --git a/drivers/uwb/i1480/i1480u-wlp/netdev.c b/drivers/uwb/i1480/i1480u-wlp/netdev.c index 8802ac43d872..2eafb973cd05 100644 --- a/drivers/uwb/i1480/i1480u-wlp/netdev.c +++ b/drivers/uwb/i1480/i1480u-wlp/netdev.c | |||
@@ -207,6 +207,11 @@ int i1480u_open(struct net_device *net_dev) | |||
207 | result = i1480u_rx_setup(i1480u); /* Alloc RX stuff */ | 207 | result = i1480u_rx_setup(i1480u); /* Alloc RX stuff */ |
208 | if (result < 0) | 208 | if (result < 0) |
209 | goto error_rx_setup; | 209 | goto error_rx_setup; |
210 | |||
211 | result = uwb_radio_start(&wlp->pal); | ||
212 | if (result < 0) | ||
213 | goto error_radio_start; | ||
214 | |||
210 | netif_wake_queue(net_dev); | 215 | netif_wake_queue(net_dev); |
211 | #ifdef i1480u_FLOW_CONTROL | 216 | #ifdef i1480u_FLOW_CONTROL |
212 | result = usb_submit_urb(i1480u->notif_urb, GFP_KERNEL);; | 217 | result = usb_submit_urb(i1480u->notif_urb, GFP_KERNEL);; |
@@ -215,25 +220,20 @@ int i1480u_open(struct net_device *net_dev) | |||
215 | goto error_notif_urb_submit; | 220 | goto error_notif_urb_submit; |
216 | } | 221 | } |
217 | #endif | 222 | #endif |
218 | i1480u->uwb_notifs_handler.cb = i1480u_uwb_notifs_cb; | ||
219 | i1480u->uwb_notifs_handler.data = i1480u; | ||
220 | if (uwb_bg_joined(rc)) | ||
221 | netif_carrier_on(net_dev); | ||
222 | else | ||
223 | netif_carrier_off(net_dev); | ||
224 | uwb_notifs_register(rc, &i1480u->uwb_notifs_handler); | ||
225 | /* Interface is up with an address, now we can create WSS */ | 223 | /* Interface is up with an address, now we can create WSS */ |
226 | result = wlp_wss_setup(net_dev, &wlp->wss); | 224 | result = wlp_wss_setup(net_dev, &wlp->wss); |
227 | if (result < 0) { | 225 | if (result < 0) { |
228 | dev_err(dev, "Can't create WSS: %d. \n", result); | 226 | dev_err(dev, "Can't create WSS: %d. \n", result); |
229 | goto error_notif_deregister; | 227 | goto error_wss_setup; |
230 | } | 228 | } |
231 | return 0; | 229 | return 0; |
232 | error_notif_deregister: | 230 | error_wss_setup: |
233 | uwb_notifs_deregister(rc, &i1480u->uwb_notifs_handler); | ||
234 | #ifdef i1480u_FLOW_CONTROL | 231 | #ifdef i1480u_FLOW_CONTROL |
232 | usb_kill_urb(i1480u->notif_urb); | ||
235 | error_notif_urb_submit: | 233 | error_notif_urb_submit: |
236 | #endif | 234 | #endif |
235 | uwb_radio_stop(&wlp->pal); | ||
236 | error_radio_start: | ||
237 | netif_stop_queue(net_dev); | 237 | netif_stop_queue(net_dev); |
238 | i1480u_rx_release(i1480u); | 238 | i1480u_rx_release(i1480u); |
239 | error_rx_setup: | 239 | error_rx_setup: |
@@ -248,16 +248,15 @@ int i1480u_stop(struct net_device *net_dev) | |||
248 | { | 248 | { |
249 | struct i1480u *i1480u = netdev_priv(net_dev); | 249 | struct i1480u *i1480u = netdev_priv(net_dev); |
250 | struct wlp *wlp = &i1480u->wlp; | 250 | struct wlp *wlp = &i1480u->wlp; |
251 | struct uwb_rc *rc = wlp->rc; | ||
252 | 251 | ||
253 | BUG_ON(wlp->rc == NULL); | 252 | BUG_ON(wlp->rc == NULL); |
254 | wlp_wss_remove(&wlp->wss); | 253 | wlp_wss_remove(&wlp->wss); |
255 | uwb_notifs_deregister(rc, &i1480u->uwb_notifs_handler); | ||
256 | netif_carrier_off(net_dev); | 254 | netif_carrier_off(net_dev); |
257 | #ifdef i1480u_FLOW_CONTROL | 255 | #ifdef i1480u_FLOW_CONTROL |
258 | usb_kill_urb(i1480u->notif_urb); | 256 | usb_kill_urb(i1480u->notif_urb); |
259 | #endif | 257 | #endif |
260 | netif_stop_queue(net_dev); | 258 | netif_stop_queue(net_dev); |
259 | uwb_radio_stop(&wlp->pal); | ||
261 | i1480u_rx_release(i1480u); | 260 | i1480u_rx_release(i1480u); |
262 | i1480u_tx_release(i1480u); | 261 | i1480u_tx_release(i1480u); |
263 | return 0; | 262 | return 0; |
@@ -303,34 +302,6 @@ int i1480u_change_mtu(struct net_device *net_dev, int mtu) | |||
303 | return 0; | 302 | return 0; |
304 | } | 303 | } |
305 | 304 | ||
306 | |||
307 | /** | ||
308 | * Callback function to handle events from UWB | ||
309 | * When we see other devices we know the carrier is ok, | ||
310 | * if we are the only device in the beacon group we set the carrier | ||
311 | * state to off. | ||
312 | * */ | ||
313 | void i1480u_uwb_notifs_cb(void *data, struct uwb_dev *uwb_dev, | ||
314 | enum uwb_notifs event) | ||
315 | { | ||
316 | struct i1480u *i1480u = data; | ||
317 | struct net_device *net_dev = i1480u->net_dev; | ||
318 | struct device *dev = &i1480u->usb_iface->dev; | ||
319 | switch (event) { | ||
320 | case UWB_NOTIF_BG_JOIN: | ||
321 | netif_carrier_on(net_dev); | ||
322 | dev_info(dev, "Link is up\n"); | ||
323 | break; | ||
324 | case UWB_NOTIF_BG_LEAVE: | ||
325 | netif_carrier_off(net_dev); | ||
326 | dev_info(dev, "Link is down\n"); | ||
327 | break; | ||
328 | default: | ||
329 | dev_err(dev, "don't know how to handle event %d from uwb\n", | ||
330 | event); | ||
331 | } | ||
332 | } | ||
333 | |||
334 | /** | 305 | /** |
335 | * Stop the network queue | 306 | * Stop the network queue |
336 | * | 307 | * |
diff --git a/drivers/uwb/i1480/i1480u-wlp/sysfs.c b/drivers/uwb/i1480/i1480u-wlp/sysfs.c index a1d8ca6ac935..a92a787725fc 100644 --- a/drivers/uwb/i1480/i1480u-wlp/sysfs.c +++ b/drivers/uwb/i1480/i1480u-wlp/sysfs.c | |||
@@ -226,7 +226,6 @@ ssize_t wlp_tx_inflight_store(struct i1480u_tx_inflight *inflight, | |||
226 | * (CLASS_DEVICE_ATTR or DEVICE_ATTR) and i1480u_ATTR_NAME produces a | 226 | * (CLASS_DEVICE_ATTR or DEVICE_ATTR) and i1480u_ATTR_NAME produces a |
227 | * class_device_attr_NAME or device_attr_NAME (for group registration). | 227 | * class_device_attr_NAME or device_attr_NAME (for group registration). |
228 | */ | 228 | */ |
229 | #include <linux/version.h> | ||
230 | 229 | ||
231 | #define i1480u_SHOW(name, fn, param) \ | 230 | #define i1480u_SHOW(name, fn, param) \ |
232 | static ssize_t i1480u_show_##name(struct device *dev, \ | 231 | static ssize_t i1480u_show_##name(struct device *dev, \ |
diff --git a/drivers/uwb/ie-rcv.c b/drivers/uwb/ie-rcv.c new file mode 100644 index 000000000000..917e6d78a798 --- /dev/null +++ b/drivers/uwb/ie-rcv.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Ultra Wide Band | ||
3 | * IE Received notification handling. | ||
4 | * | ||
5 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License version | ||
9 | * 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/errno.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <linux/bitmap.h> | ||
24 | #include "uwb-internal.h" | ||
25 | |||
26 | /* | ||
27 | * Process an incoming IE Received notification. | ||
28 | */ | ||
29 | int uwbd_evt_handle_rc_ie_rcv(struct uwb_event *evt) | ||
30 | { | ||
31 | int result = -EINVAL; | ||
32 | struct device *dev = &evt->rc->uwb_dev.dev; | ||
33 | struct uwb_rc_evt_ie_rcv *iercv; | ||
34 | size_t iesize; | ||
35 | |||
36 | /* Is there enough data to decode it? */ | ||
37 | if (evt->notif.size < sizeof(*iercv)) { | ||
38 | dev_err(dev, "IE Received notification: Not enough data to " | ||
39 | "decode (%zu vs %zu bytes needed)\n", | ||
40 | evt->notif.size, sizeof(*iercv)); | ||
41 | goto error; | ||
42 | } | ||
43 | iercv = container_of(evt->notif.rceb, struct uwb_rc_evt_ie_rcv, rceb); | ||
44 | iesize = le16_to_cpu(iercv->wIELength); | ||
45 | |||
46 | dev_dbg(dev, "IE received, element ID=%d\n", iercv->IEData[0]); | ||
47 | |||
48 | if (iercv->IEData[0] == UWB_RELINQUISH_REQUEST_IE) { | ||
49 | dev_warn(dev, "unhandled Relinquish Request IE\n"); | ||
50 | } | ||
51 | |||
52 | return 0; | ||
53 | error: | ||
54 | return result; | ||
55 | } | ||
diff --git a/drivers/uwb/ie.c b/drivers/uwb/ie.c index cf6f3d152b9d..ab976686175b 100644 --- a/drivers/uwb/ie.c +++ b/drivers/uwb/ie.c | |||
@@ -25,8 +25,6 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include "uwb-internal.h" | 27 | #include "uwb-internal.h" |
28 | #define D_LOCAL 0 | ||
29 | #include <linux/uwb/debug.h> | ||
30 | 28 | ||
31 | /** | 29 | /** |
32 | * uwb_ie_next - get the next IE in a buffer | 30 | * uwb_ie_next - get the next IE in a buffer |
@@ -61,6 +59,42 @@ struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len) | |||
61 | EXPORT_SYMBOL_GPL(uwb_ie_next); | 59 | EXPORT_SYMBOL_GPL(uwb_ie_next); |
62 | 60 | ||
63 | /** | 61 | /** |
62 | * uwb_ie_dump_hex - print IEs to a character buffer | ||
63 | * @ies: the IEs to print. | ||
64 | * @len: length of all the IEs. | ||
65 | * @buf: the destination buffer. | ||
66 | * @size: size of @buf. | ||
67 | * | ||
68 | * Returns the number of characters written. | ||
69 | */ | ||
70 | int uwb_ie_dump_hex(const struct uwb_ie_hdr *ies, size_t len, | ||
71 | char *buf, size_t size) | ||
72 | { | ||
73 | void *ptr; | ||
74 | const struct uwb_ie_hdr *ie; | ||
75 | int r = 0; | ||
76 | u8 *d; | ||
77 | |||
78 | ptr = (void *)ies; | ||
79 | for (;;) { | ||
80 | ie = uwb_ie_next(&ptr, &len); | ||
81 | if (!ie) | ||
82 | break; | ||
83 | |||
84 | r += scnprintf(buf + r, size - r, "%02x %02x", | ||
85 | (unsigned)ie->element_id, | ||
86 | (unsigned)ie->length); | ||
87 | d = (uint8_t *)ie + sizeof(struct uwb_ie_hdr); | ||
88 | while (d != ptr && r < size) | ||
89 | r += scnprintf(buf + r, size - r, " %02x", (unsigned)*d++); | ||
90 | if (r < size) | ||
91 | buf[r++] = '\n'; | ||
92 | }; | ||
93 | |||
94 | return r; | ||
95 | } | ||
96 | |||
97 | /** | ||
64 | * Get the IEs that a radio controller is sending in its beacon | 98 | * Get the IEs that a radio controller is sending in its beacon |
65 | * | 99 | * |
66 | * @uwb_rc: UWB Radio Controller | 100 | * @uwb_rc: UWB Radio Controller |
@@ -70,6 +104,7 @@ EXPORT_SYMBOL_GPL(uwb_ie_next); | |||
70 | * anything. Once done with the iedata buffer, call | 104 | * anything. Once done with the iedata buffer, call |
71 | * uwb_rc_ie_release(iedata). Don't call kfree on it. | 105 | * uwb_rc_ie_release(iedata). Don't call kfree on it. |
72 | */ | 106 | */ |
107 | static | ||
73 | ssize_t uwb_rc_get_ie(struct uwb_rc *uwb_rc, struct uwb_rc_evt_get_ie **pget_ie) | 108 | ssize_t uwb_rc_get_ie(struct uwb_rc *uwb_rc, struct uwb_rc_evt_get_ie **pget_ie) |
74 | { | 109 | { |
75 | ssize_t result; | 110 | ssize_t result; |
@@ -78,148 +113,35 @@ ssize_t uwb_rc_get_ie(struct uwb_rc *uwb_rc, struct uwb_rc_evt_get_ie **pget_ie) | |||
78 | struct uwb_rceb *reply = NULL; | 113 | struct uwb_rceb *reply = NULL; |
79 | struct uwb_rc_evt_get_ie *get_ie; | 114 | struct uwb_rc_evt_get_ie *get_ie; |
80 | 115 | ||
81 | d_fnstart(3, dev, "(%p, %p)\n", uwb_rc, pget_ie); | ||
82 | result = -ENOMEM; | ||
83 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 116 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
84 | if (cmd == NULL) | 117 | if (cmd == NULL) |
85 | goto error_kzalloc; | 118 | return -ENOMEM; |
119 | |||
86 | cmd->bCommandType = UWB_RC_CET_GENERAL; | 120 | cmd->bCommandType = UWB_RC_CET_GENERAL; |
87 | cmd->wCommand = cpu_to_le16(UWB_RC_CMD_GET_IE); | 121 | cmd->wCommand = cpu_to_le16(UWB_RC_CMD_GET_IE); |
88 | result = uwb_rc_vcmd(uwb_rc, "GET_IE", cmd, sizeof(*cmd), | 122 | result = uwb_rc_vcmd(uwb_rc, "GET_IE", cmd, sizeof(*cmd), |
89 | UWB_RC_CET_GENERAL, UWB_RC_CMD_GET_IE, | 123 | UWB_RC_CET_GENERAL, UWB_RC_CMD_GET_IE, |
90 | &reply); | 124 | &reply); |
125 | kfree(cmd); | ||
91 | if (result < 0) | 126 | if (result < 0) |
92 | goto error_cmd; | 127 | return result; |
128 | |||
93 | get_ie = container_of(reply, struct uwb_rc_evt_get_ie, rceb); | 129 | get_ie = container_of(reply, struct uwb_rc_evt_get_ie, rceb); |
94 | if (result < sizeof(*get_ie)) { | 130 | if (result < sizeof(*get_ie)) { |
95 | dev_err(dev, "not enough data returned for decoding GET IE " | 131 | dev_err(dev, "not enough data returned for decoding GET IE " |
96 | "(%zu bytes received vs %zu needed)\n", | 132 | "(%zu bytes received vs %zu needed)\n", |
97 | result, sizeof(*get_ie)); | 133 | result, sizeof(*get_ie)); |
98 | result = -EINVAL; | 134 | return -EINVAL; |
99 | } else if (result < sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)) { | 135 | } else if (result < sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)) { |
100 | dev_err(dev, "not enough data returned for decoding GET IE " | 136 | dev_err(dev, "not enough data returned for decoding GET IE " |
101 | "payload (%zu bytes received vs %zu needed)\n", result, | 137 | "payload (%zu bytes received vs %zu needed)\n", result, |
102 | sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)); | 138 | sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)); |
103 | result = -EINVAL; | ||
104 | } else | ||
105 | *pget_ie = get_ie; | ||
106 | error_cmd: | ||
107 | kfree(cmd); | ||
108 | error_kzalloc: | ||
109 | d_fnend(3, dev, "(%p, %p) = %d\n", uwb_rc, pget_ie, (int)result); | ||
110 | return result; | ||
111 | } | ||
112 | EXPORT_SYMBOL_GPL(uwb_rc_get_ie); | ||
113 | |||
114 | |||
115 | /* | ||
116 | * Given a pointer to an IE, print it in ASCII/hex followed by a new line | ||
117 | * | ||
118 | * @ie_hdr: pointer to the IE header. Length is in there, and it is | ||
119 | * guaranteed that the ie_hdr->length bytes following it are | ||
120 | * safely accesible. | ||
121 | * | ||
122 | * @_data: context data passed from uwb_ie_for_each(), an struct output_ctx | ||
123 | */ | ||
124 | int uwb_ie_dump_hex(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr, | ||
125 | size_t offset, void *_ctx) | ||
126 | { | ||
127 | struct uwb_buf_ctx *ctx = _ctx; | ||
128 | const u8 *pl = (void *)(ie_hdr + 1); | ||
129 | u8 pl_itr; | ||
130 | |||
131 | ctx->bytes += scnprintf(ctx->buf + ctx->bytes, ctx->size - ctx->bytes, | ||
132 | "%02x %02x ", (unsigned) ie_hdr->element_id, | ||
133 | (unsigned) ie_hdr->length); | ||
134 | pl_itr = 0; | ||
135 | while (pl_itr < ie_hdr->length && ctx->bytes < ctx->size) | ||
136 | ctx->bytes += scnprintf(ctx->buf + ctx->bytes, | ||
137 | ctx->size - ctx->bytes, | ||
138 | "%02x ", (unsigned) pl[pl_itr++]); | ||
139 | if (ctx->bytes < ctx->size) | ||
140 | ctx->buf[ctx->bytes++] = '\n'; | ||
141 | return 0; | ||
142 | } | ||
143 | EXPORT_SYMBOL_GPL(uwb_ie_dump_hex); | ||
144 | |||
145 | |||
146 | /** | ||
147 | * Verify that a pointer in a buffer points to valid IE | ||
148 | * | ||
149 | * @start: pointer to start of buffer in which IE appears | ||
150 | * @itr: pointer to IE inside buffer that will be verified | ||
151 | * @top: pointer to end of buffer | ||
152 | * | ||
153 | * @returns: 0 if IE is valid, <0 otherwise | ||
154 | * | ||
155 | * Verification involves checking that the buffer can contain a | ||
156 | * header and the amount of data reported in the IE header can be found in | ||
157 | * the buffer. | ||
158 | */ | ||
159 | static | ||
160 | int uwb_rc_ie_verify(struct uwb_dev *uwb_dev, const void *start, | ||
161 | const void *itr, const void *top) | ||
162 | { | ||
163 | struct device *dev = &uwb_dev->dev; | ||
164 | const struct uwb_ie_hdr *ie_hdr; | ||
165 | |||
166 | if (top - itr < sizeof(*ie_hdr)) { | ||
167 | dev_err(dev, "Bad IE: no data to decode header " | ||
168 | "(%zu bytes left vs %zu needed) at offset %zu\n", | ||
169 | top - itr, sizeof(*ie_hdr), itr - start); | ||
170 | return -EINVAL; | ||
171 | } | ||
172 | ie_hdr = itr; | ||
173 | itr += sizeof(*ie_hdr); | ||
174 | if (top - itr < ie_hdr->length) { | ||
175 | dev_err(dev, "Bad IE: not enough data for payload " | ||
176 | "(%zu bytes left vs %zu needed) at offset %zu\n", | ||
177 | top - itr, (size_t)ie_hdr->length, | ||
178 | (void *)ie_hdr - start); | ||
179 | return -EINVAL; | 139 | return -EINVAL; |
180 | } | 140 | } |
181 | return 0; | ||
182 | } | ||
183 | 141 | ||
184 | 142 | *pget_ie = get_ie; | |
185 | /** | ||
186 | * Walk a buffer filled with consecutive IE's a buffer | ||
187 | * | ||
188 | * @uwb_dev: UWB device this IEs belong to (for err messages mainly) | ||
189 | * | ||
190 | * @fn: function to call with each IE; if it returns 0, we keep | ||
191 | * traversing the buffer. If it returns !0, we'll stop and return | ||
192 | * that value. | ||
193 | * | ||
194 | * @data: pointer passed to @fn | ||
195 | * | ||
196 | * @buf: buffer where the consecutive IEs are located | ||
197 | * | ||
198 | * @size: size of @buf | ||
199 | * | ||
200 | * Each IE is checked for basic correctness (there is space left for | ||
201 | * the header and the payload). If that test is failed, we stop | ||
202 | * processing. For every good IE, @fn is called. | ||
203 | */ | ||
204 | ssize_t uwb_ie_for_each(struct uwb_dev *uwb_dev, uwb_ie_f fn, void *data, | ||
205 | const void *buf, size_t size) | ||
206 | { | ||
207 | ssize_t result = 0; | ||
208 | const struct uwb_ie_hdr *ie_hdr; | ||
209 | const void *itr = buf, *top = itr + size; | ||
210 | |||
211 | while (itr < top) { | ||
212 | if (uwb_rc_ie_verify(uwb_dev, buf, itr, top) != 0) | ||
213 | break; | ||
214 | ie_hdr = itr; | ||
215 | itr += sizeof(*ie_hdr) + ie_hdr->length; | ||
216 | result = fn(uwb_dev, ie_hdr, itr - buf, data); | ||
217 | if (result != 0) | ||
218 | break; | ||
219 | } | ||
220 | return result; | 143 | return result; |
221 | } | 144 | } |
222 | EXPORT_SYMBOL_GPL(uwb_ie_for_each); | ||
223 | 145 | ||
224 | 146 | ||
225 | /** | 147 | /** |
@@ -256,70 +178,6 @@ error_cmd: | |||
256 | return result; | 178 | return result; |
257 | } | 179 | } |
258 | 180 | ||
259 | /** | ||
260 | * Determine by IE id if IE is host settable | ||
261 | * WUSB 1.0 [8.6.2.8 Table 8.85] | ||
262 | * | ||
263 | * EXCEPTION: | ||
264 | * All but UWB_IE_WLP appears in Table 8.85 from WUSB 1.0. Setting this IE | ||
265 | * is required for the WLP substack to perform association with its WSS so | ||
266 | * we hope that the WUSB spec will be changed to reflect this. | ||
267 | */ | ||
268 | static | ||
269 | int uwb_rc_ie_is_host_settable(enum uwb_ie element_id) | ||
270 | { | ||
271 | if (element_id == UWB_PCA_AVAILABILITY || | ||
272 | element_id == UWB_BP_SWITCH_IE || | ||
273 | element_id == UWB_MAC_CAPABILITIES_IE || | ||
274 | element_id == UWB_PHY_CAPABILITIES_IE || | ||
275 | element_id == UWB_APP_SPEC_PROBE_IE || | ||
276 | element_id == UWB_IDENTIFICATION_IE || | ||
277 | element_id == UWB_MASTER_KEY_ID_IE || | ||
278 | element_id == UWB_IE_WLP || | ||
279 | element_id == UWB_APP_SPEC_IE) | ||
280 | return 1; | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | |||
285 | /** | ||
286 | * Extract Host Settable IEs from IE | ||
287 | * | ||
288 | * @ie_data: pointer to buffer containing all IEs | ||
289 | * @size: size of buffer | ||
290 | * | ||
291 | * @returns: length of buffer that only includes host settable IEs | ||
292 | * | ||
293 | * Given a buffer of IEs we move all Host Settable IEs to front of buffer | ||
294 | * by overwriting the IEs that are not Host Settable. | ||
295 | * Buffer length is adjusted accordingly. | ||
296 | */ | ||
297 | static | ||
298 | ssize_t uwb_rc_parse_host_settable_ie(struct uwb_dev *uwb_dev, | ||
299 | void *ie_data, size_t size) | ||
300 | { | ||
301 | size_t new_len = size; | ||
302 | struct uwb_ie_hdr *ie_hdr; | ||
303 | size_t ie_length; | ||
304 | void *itr = ie_data, *top = itr + size; | ||
305 | |||
306 | while (itr < top) { | ||
307 | if (uwb_rc_ie_verify(uwb_dev, ie_data, itr, top) != 0) | ||
308 | break; | ||
309 | ie_hdr = itr; | ||
310 | ie_length = sizeof(*ie_hdr) + ie_hdr->length; | ||
311 | if (uwb_rc_ie_is_host_settable(ie_hdr->element_id)) { | ||
312 | itr += ie_length; | ||
313 | } else { | ||
314 | memmove(itr, itr + ie_length, top - (itr + ie_length)); | ||
315 | new_len -= ie_length; | ||
316 | top -= ie_length; | ||
317 | } | ||
318 | } | ||
319 | return new_len; | ||
320 | } | ||
321 | |||
322 | |||
323 | /* Cleanup the whole IE management subsystem */ | 181 | /* Cleanup the whole IE management subsystem */ |
324 | void uwb_rc_ie_init(struct uwb_rc *uwb_rc) | 182 | void uwb_rc_ie_init(struct uwb_rc *uwb_rc) |
325 | { | 183 | { |
@@ -328,49 +186,34 @@ void uwb_rc_ie_init(struct uwb_rc *uwb_rc) | |||
328 | 186 | ||
329 | 187 | ||
330 | /** | 188 | /** |
331 | * Set up cache for host settable IEs currently being transmitted | 189 | * uwb_rc_ie_setup - setup a radio controller's IE manager |
190 | * @uwb_rc: the radio controller. | ||
332 | * | 191 | * |
333 | * First we just call GET-IE to get the current IEs being transmitted | 192 | * The current set of IEs are obtained from the hardware with a GET-IE |
334 | * (or we workaround and pretend we did) and (because the format is | 193 | * command (since the radio controller is not yet beaconing this will |
335 | * the same) reuse that as the IE cache (with the command prefix, as | 194 | * be just the hardware's MAC and PHY Capability IEs). |
336 | * explained in 'struct uwb_rc'). | ||
337 | * | 195 | * |
338 | * @returns: size of cache created | 196 | * Returns 0 on success; -ve on an error. |
339 | */ | 197 | */ |
340 | ssize_t uwb_rc_ie_setup(struct uwb_rc *uwb_rc) | 198 | int uwb_rc_ie_setup(struct uwb_rc *uwb_rc) |
341 | { | 199 | { |
342 | struct device *dev = &uwb_rc->uwb_dev.dev; | 200 | struct uwb_rc_evt_get_ie *ie_info = NULL; |
343 | ssize_t result; | 201 | int capacity; |
344 | size_t capacity; | 202 | |
345 | struct uwb_rc_evt_get_ie *ie_info; | 203 | capacity = uwb_rc_get_ie(uwb_rc, &ie_info); |
204 | if (capacity < 0) | ||
205 | return capacity; | ||
346 | 206 | ||
347 | d_fnstart(3, dev, "(%p)\n", uwb_rc); | ||
348 | mutex_lock(&uwb_rc->ies_mutex); | 207 | mutex_lock(&uwb_rc->ies_mutex); |
349 | result = uwb_rc_get_ie(uwb_rc, &ie_info); | 208 | |
350 | if (result < 0) | 209 | uwb_rc->ies = (struct uwb_rc_cmd_set_ie *)ie_info; |
351 | goto error_get_ie; | ||
352 | capacity = result; | ||
353 | d_printf(5, dev, "Got IEs %zu bytes (%zu long at %p)\n", result, | ||
354 | (size_t)le16_to_cpu(ie_info->wIELength), ie_info); | ||
355 | |||
356 | /* Remove IEs that host should not set. */ | ||
357 | result = uwb_rc_parse_host_settable_ie(&uwb_rc->uwb_dev, | ||
358 | ie_info->IEData, le16_to_cpu(ie_info->wIELength)); | ||
359 | if (result < 0) | ||
360 | goto error_parse; | ||
361 | d_printf(5, dev, "purged non-settable IEs to %zu bytes\n", result); | ||
362 | uwb_rc->ies = (void *) ie_info; | ||
363 | uwb_rc->ies->rccb.bCommandType = UWB_RC_CET_GENERAL; | 210 | uwb_rc->ies->rccb.bCommandType = UWB_RC_CET_GENERAL; |
364 | uwb_rc->ies->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SET_IE); | 211 | uwb_rc->ies->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SET_IE); |
365 | uwb_rc->ies_capacity = capacity; | 212 | uwb_rc->ies_capacity = capacity; |
366 | d_printf(5, dev, "IE cache at %p %zu bytes, %zu capacity\n", | 213 | |
367 | ie_info, result, capacity); | ||
368 | result = 0; | ||
369 | error_parse: | ||
370 | error_get_ie: | ||
371 | mutex_unlock(&uwb_rc->ies_mutex); | 214 | mutex_unlock(&uwb_rc->ies_mutex); |
372 | d_fnend(3, dev, "(%p) = %zu\n", uwb_rc, result); | 215 | |
373 | return result; | 216 | return 0; |
374 | } | 217 | } |
375 | 218 | ||
376 | 219 | ||
@@ -383,26 +226,47 @@ void uwb_rc_ie_release(struct uwb_rc *uwb_rc) | |||
383 | } | 226 | } |
384 | 227 | ||
385 | 228 | ||
386 | static | 229 | static int uwb_rc_ie_add_one(struct uwb_rc *rc, const struct uwb_ie_hdr *new_ie) |
387 | int __acc_size(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr, | ||
388 | size_t offset, void *_ctx) | ||
389 | { | 230 | { |
390 | size_t *acc_size = _ctx; | 231 | struct uwb_rc_cmd_set_ie *new_ies; |
391 | *acc_size += sizeof(*ie_hdr) + ie_hdr->length; | 232 | void *ptr, *prev_ie; |
392 | d_printf(6, &uwb_dev->dev, "new acc size %zu\n", *acc_size); | 233 | struct uwb_ie_hdr *ie; |
234 | size_t length, new_ie_len, new_capacity, size, prev_size; | ||
235 | |||
236 | length = le16_to_cpu(rc->ies->wIELength); | ||
237 | new_ie_len = sizeof(struct uwb_ie_hdr) + new_ie->length; | ||
238 | new_capacity = sizeof(struct uwb_rc_cmd_set_ie) + length + new_ie_len; | ||
239 | |||
240 | if (new_capacity > rc->ies_capacity) { | ||
241 | new_ies = krealloc(rc->ies, new_capacity, GFP_KERNEL); | ||
242 | if (!new_ies) | ||
243 | return -ENOMEM; | ||
244 | rc->ies = new_ies; | ||
245 | } | ||
246 | |||
247 | ptr = rc->ies->IEData; | ||
248 | size = length; | ||
249 | for (;;) { | ||
250 | prev_ie = ptr; | ||
251 | prev_size = size; | ||
252 | ie = uwb_ie_next(&ptr, &size); | ||
253 | if (!ie || ie->element_id > new_ie->element_id) | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | memmove(prev_ie + new_ie_len, prev_ie, prev_size); | ||
258 | memcpy(prev_ie, new_ie, new_ie_len); | ||
259 | rc->ies->wIELength = cpu_to_le16(length + new_ie_len); | ||
260 | |||
393 | return 0; | 261 | return 0; |
394 | } | 262 | } |
395 | 263 | ||
396 | |||
397 | /** | 264 | /** |
398 | * Add a new IE to IEs currently being transmitted by device | 265 | * uwb_rc_ie_add - add new IEs to the radio controller's beacon |
399 | * | 266 | * @uwb_rc: the radio controller. |
400 | * @ies: the buffer containing the new IE or IEs to be added to | 267 | * @ies: the buffer containing the new IE or IEs to be added to |
401 | * the device's beacon. The buffer will be verified for | 268 | * the device's beacon. |
402 | * consistence (meaning the headers should be right) and | 269 | * @size: length of all the IEs. |
403 | * consistent with the buffer size. | ||
404 | * @size: size of @ies (in bytes, total buffer size) | ||
405 | * @returns: 0 if ok, <0 errno code on error | ||
406 | * | 270 | * |
407 | * According to WHCI 0.95 [4.13.6] the driver will only receive the RCEB | 271 | * According to WHCI 0.95 [4.13.6] the driver will only receive the RCEB |
408 | * after the device sent the first beacon that includes the IEs specified | 272 | * after the device sent the first beacon that includes the IEs specified |
@@ -411,66 +275,40 @@ int __acc_size(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr, | |||
411 | * we start beaconing. | 275 | * we start beaconing. |
412 | * | 276 | * |
413 | * Setting an IE on the device will overwrite all current IEs in device. So | 277 | * Setting an IE on the device will overwrite all current IEs in device. So |
414 | * we take the current IEs being transmitted by the device, append the | 278 | * we take the current IEs being transmitted by the device, insert the |
415 | * new one, and call SET IE with all the IEs needed. | 279 | * new one, and call SET IE with all the IEs needed. |
416 | * | 280 | * |
417 | * The local IE cache will only be updated with the new IE if SET IE | 281 | * Returns 0 on success; or -ENOMEM. |
418 | * completed successfully. | ||
419 | */ | 282 | */ |
420 | int uwb_rc_ie_add(struct uwb_rc *uwb_rc, | 283 | int uwb_rc_ie_add(struct uwb_rc *uwb_rc, |
421 | const struct uwb_ie_hdr *ies, size_t size) | 284 | const struct uwb_ie_hdr *ies, size_t size) |
422 | { | 285 | { |
423 | int result = 0; | 286 | int result = 0; |
424 | struct device *dev = &uwb_rc->uwb_dev.dev; | 287 | void *ptr; |
425 | struct uwb_rc_cmd_set_ie *new_ies; | 288 | const struct uwb_ie_hdr *ie; |
426 | size_t ies_size, total_size, acc_size = 0; | 289 | |
427 | |||
428 | if (uwb_rc->ies == NULL) | ||
429 | return -ESHUTDOWN; | ||
430 | uwb_ie_for_each(&uwb_rc->uwb_dev, __acc_size, &acc_size, ies, size); | ||
431 | if (acc_size != size) { | ||
432 | dev_err(dev, "BUG: bad IEs, misconstructed headers " | ||
433 | "[%zu bytes reported vs %zu calculated]\n", | ||
434 | size, acc_size); | ||
435 | WARN_ON(1); | ||
436 | return -EINVAL; | ||
437 | } | ||
438 | mutex_lock(&uwb_rc->ies_mutex); | 290 | mutex_lock(&uwb_rc->ies_mutex); |
439 | ies_size = le16_to_cpu(uwb_rc->ies->wIELength); | 291 | |
440 | total_size = sizeof(*uwb_rc->ies) + ies_size; | 292 | ptr = (void *)ies; |
441 | if (total_size + size > uwb_rc->ies_capacity) { | 293 | for (;;) { |
442 | d_printf(4, dev, "Reallocating IE cache from %p capacity %zu " | 294 | ie = uwb_ie_next(&ptr, &size); |
443 | "to capacity %zu\n", uwb_rc->ies, uwb_rc->ies_capacity, | 295 | if (!ie) |
444 | total_size + size); | 296 | break; |
445 | new_ies = kzalloc(total_size + size, GFP_KERNEL); | 297 | |
446 | if (new_ies == NULL) { | 298 | result = uwb_rc_ie_add_one(uwb_rc, ie); |
447 | dev_err(dev, "No memory for adding new IE\n"); | 299 | if (result < 0) |
448 | result = -ENOMEM; | 300 | break; |
449 | goto error_alloc; | ||
450 | } | ||
451 | memcpy(new_ies, uwb_rc->ies, total_size); | ||
452 | uwb_rc->ies_capacity = total_size + size; | ||
453 | kfree(uwb_rc->ies); | ||
454 | uwb_rc->ies = new_ies; | ||
455 | d_printf(4, dev, "New IE cache at %p capacity %zu\n", | ||
456 | uwb_rc->ies, uwb_rc->ies_capacity); | ||
457 | } | 301 | } |
458 | memcpy((void *)uwb_rc->ies + total_size, ies, size); | 302 | if (result >= 0) { |
459 | uwb_rc->ies->wIELength = cpu_to_le16(ies_size + size); | 303 | if (size == 0) { |
460 | if (uwb_rc->beaconing != -1) { | 304 | if (uwb_rc->beaconing != -1) |
461 | result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); | 305 | result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); |
462 | if (result < 0) { | ||
463 | dev_err(dev, "Cannot set new IE on device: %d\n", | ||
464 | result); | ||
465 | uwb_rc->ies->wIELength = cpu_to_le16(ies_size); | ||
466 | } else | 306 | } else |
467 | result = 0; | 307 | result = -EINVAL; |
468 | } | 308 | } |
469 | d_printf(4, dev, "IEs now occupy %hu bytes of %zu capacity at %p\n", | 309 | |
470 | le16_to_cpu(uwb_rc->ies->wIELength), uwb_rc->ies_capacity, | ||
471 | uwb_rc->ies); | ||
472 | error_alloc: | ||
473 | mutex_unlock(&uwb_rc->ies_mutex); | 310 | mutex_unlock(&uwb_rc->ies_mutex); |
311 | |||
474 | return result; | 312 | return result; |
475 | } | 313 | } |
476 | EXPORT_SYMBOL_GPL(uwb_rc_ie_add); | 314 | EXPORT_SYMBOL_GPL(uwb_rc_ie_add); |
@@ -489,53 +327,52 @@ EXPORT_SYMBOL_GPL(uwb_rc_ie_add); | |||
489 | * beacon. We don't reallocate, we just mark the size smaller. | 327 | * beacon. We don't reallocate, we just mark the size smaller. |
490 | */ | 328 | */ |
491 | static | 329 | static |
492 | int uwb_rc_ie_cache_rm(struct uwb_rc *uwb_rc, enum uwb_ie to_remove) | 330 | void uwb_rc_ie_cache_rm(struct uwb_rc *uwb_rc, enum uwb_ie to_remove) |
493 | { | 331 | { |
494 | struct uwb_ie_hdr *ie_hdr; | 332 | struct uwb_ie_hdr *ie; |
495 | size_t new_len = le16_to_cpu(uwb_rc->ies->wIELength); | 333 | size_t len = le16_to_cpu(uwb_rc->ies->wIELength); |
496 | void *itr = uwb_rc->ies->IEData; | 334 | void *ptr; |
497 | void *top = itr + new_len; | 335 | size_t size; |
498 | 336 | ||
499 | while (itr < top) { | 337 | ptr = uwb_rc->ies->IEData; |
500 | ie_hdr = itr; | 338 | size = len; |
501 | if (ie_hdr->element_id != to_remove) { | 339 | for (;;) { |
502 | itr += sizeof(*ie_hdr) + ie_hdr->length; | 340 | ie = uwb_ie_next(&ptr, &size); |
503 | } else { | 341 | if (!ie) |
504 | int ie_length; | 342 | break; |
505 | ie_length = sizeof(*ie_hdr) + ie_hdr->length; | 343 | if (ie->element_id == to_remove) { |
506 | if (top - itr != ie_length) | 344 | len -= sizeof(struct uwb_ie_hdr) + ie->length; |
507 | memmove(itr, itr + ie_length, top - itr + ie_length); | 345 | memmove(ie, ptr, size); |
508 | top -= ie_length; | 346 | ptr = ie; |
509 | new_len -= ie_length; | ||
510 | } | 347 | } |
511 | } | 348 | } |
512 | uwb_rc->ies->wIELength = cpu_to_le16(new_len); | 349 | uwb_rc->ies->wIELength = cpu_to_le16(len); |
513 | return 0; | ||
514 | } | 350 | } |
515 | 351 | ||
516 | 352 | ||
517 | /** | 353 | /** |
518 | * Remove an IE currently being transmitted by device | 354 | * uwb_rc_ie_rm - remove an IE from the radio controller's beacon |
355 | * @uwb_rc: the radio controller. | ||
356 | * @element_id: the element ID of the IE to remove. | ||
519 | * | 357 | * |
520 | * @element_id: id of IE to be removed from device's beacon | 358 | * Only IEs previously added with uwb_rc_ie_add() may be removed. |
359 | * | ||
360 | * Returns 0 on success; or -ve the SET-IE command to the radio | ||
361 | * controller failed. | ||
521 | */ | 362 | */ |
522 | int uwb_rc_ie_rm(struct uwb_rc *uwb_rc, enum uwb_ie element_id) | 363 | int uwb_rc_ie_rm(struct uwb_rc *uwb_rc, enum uwb_ie element_id) |
523 | { | 364 | { |
524 | struct device *dev = &uwb_rc->uwb_dev.dev; | 365 | int result = 0; |
525 | int result; | ||
526 | 366 | ||
527 | if (uwb_rc->ies == NULL) | ||
528 | return -ESHUTDOWN; | ||
529 | mutex_lock(&uwb_rc->ies_mutex); | 367 | mutex_lock(&uwb_rc->ies_mutex); |
530 | result = uwb_rc_ie_cache_rm(uwb_rc, element_id); | 368 | |
531 | if (result < 0) | 369 | uwb_rc_ie_cache_rm(uwb_rc, element_id); |
532 | dev_err(dev, "Cannot remove IE from cache.\n"); | 370 | |
533 | if (uwb_rc->beaconing != -1) { | 371 | if (uwb_rc->beaconing != -1) |
534 | result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); | 372 | result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); |
535 | if (result < 0) | 373 | |
536 | dev_err(dev, "Cannot set new IE on device.\n"); | ||
537 | } | ||
538 | mutex_unlock(&uwb_rc->ies_mutex); | 374 | mutex_unlock(&uwb_rc->ies_mutex); |
375 | |||
539 | return result; | 376 | return result; |
540 | } | 377 | } |
541 | EXPORT_SYMBOL_GPL(uwb_rc_ie_rm); | 378 | EXPORT_SYMBOL_GPL(uwb_rc_ie_rm); |
diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c index ee5772f00d42..9cf21e6bb624 100644 --- a/drivers/uwb/lc-rc.c +++ b/drivers/uwb/lc-rc.c | |||
@@ -36,8 +36,6 @@ | |||
36 | #include <linux/etherdevice.h> | 36 | #include <linux/etherdevice.h> |
37 | #include <linux/usb.h> | 37 | #include <linux/usb.h> |
38 | 38 | ||
39 | #define D_LOCAL 1 | ||
40 | #include <linux/uwb/debug.h> | ||
41 | #include "uwb-internal.h" | 39 | #include "uwb-internal.h" |
42 | 40 | ||
43 | static int uwb_rc_index_match(struct device *dev, void *data) | 41 | static int uwb_rc_index_match(struct device *dev, void *data) |
@@ -81,9 +79,7 @@ static void uwb_rc_sys_release(struct device *dev) | |||
81 | struct uwb_dev *uwb_dev = container_of(dev, struct uwb_dev, dev); | 79 | struct uwb_dev *uwb_dev = container_of(dev, struct uwb_dev, dev); |
82 | struct uwb_rc *rc = container_of(uwb_dev, struct uwb_rc, uwb_dev); | 80 | struct uwb_rc *rc = container_of(uwb_dev, struct uwb_rc, uwb_dev); |
83 | 81 | ||
84 | uwb_rc_neh_destroy(rc); | ||
85 | uwb_rc_ie_release(rc); | 82 | uwb_rc_ie_release(rc); |
86 | d_printf(1, dev, "freed uwb_rc %p\n", rc); | ||
87 | kfree(rc); | 83 | kfree(rc); |
88 | } | 84 | } |
89 | 85 | ||
@@ -100,6 +96,8 @@ void uwb_rc_init(struct uwb_rc *rc) | |||
100 | rc->scan_type = UWB_SCAN_DISABLED; | 96 | rc->scan_type = UWB_SCAN_DISABLED; |
101 | INIT_LIST_HEAD(&rc->notifs_chain.list); | 97 | INIT_LIST_HEAD(&rc->notifs_chain.list); |
102 | mutex_init(&rc->notifs_chain.mutex); | 98 | mutex_init(&rc->notifs_chain.mutex); |
99 | INIT_LIST_HEAD(&rc->uwb_beca.list); | ||
100 | mutex_init(&rc->uwb_beca.mutex); | ||
103 | uwb_drp_avail_init(rc); | 101 | uwb_drp_avail_init(rc); |
104 | uwb_rc_ie_init(rc); | 102 | uwb_rc_ie_init(rc); |
105 | uwb_rsv_init(rc); | 103 | uwb_rsv_init(rc); |
@@ -191,9 +189,9 @@ static int uwb_rc_setup(struct uwb_rc *rc) | |||
191 | int result; | 189 | int result; |
192 | struct device *dev = &rc->uwb_dev.dev; | 190 | struct device *dev = &rc->uwb_dev.dev; |
193 | 191 | ||
194 | result = uwb_rc_reset(rc); | 192 | result = uwb_radio_setup(rc); |
195 | if (result < 0) { | 193 | if (result < 0) { |
196 | dev_err(dev, "cannot reset UWB radio: %d\n", result); | 194 | dev_err(dev, "cannot setup UWB radio: %d\n", result); |
197 | goto error; | 195 | goto error; |
198 | } | 196 | } |
199 | result = uwb_rc_mac_addr_setup(rc); | 197 | result = uwb_rc_mac_addr_setup(rc); |
@@ -250,6 +248,12 @@ int uwb_rc_add(struct uwb_rc *rc, struct device *parent_dev, void *priv) | |||
250 | 248 | ||
251 | rc->priv = priv; | 249 | rc->priv = priv; |
252 | 250 | ||
251 | init_waitqueue_head(&rc->uwbd.wq); | ||
252 | INIT_LIST_HEAD(&rc->uwbd.event_list); | ||
253 | spin_lock_init(&rc->uwbd.event_list_lock); | ||
254 | |||
255 | uwbd_start(rc); | ||
256 | |||
253 | result = rc->start(rc); | 257 | result = rc->start(rc); |
254 | if (result < 0) | 258 | if (result < 0) |
255 | goto error_rc_start; | 259 | goto error_rc_start; |
@@ -284,7 +288,7 @@ error_sys_add: | |||
284 | error_dev_add: | 288 | error_dev_add: |
285 | error_rc_setup: | 289 | error_rc_setup: |
286 | rc->stop(rc); | 290 | rc->stop(rc); |
287 | uwbd_flush(rc); | 291 | uwbd_stop(rc); |
288 | error_rc_start: | 292 | error_rc_start: |
289 | return result; | 293 | return result; |
290 | } | 294 | } |
@@ -306,25 +310,24 @@ void uwb_rc_rm(struct uwb_rc *rc) | |||
306 | rc->ready = 0; | 310 | rc->ready = 0; |
307 | 311 | ||
308 | uwb_dbg_del_rc(rc); | 312 | uwb_dbg_del_rc(rc); |
309 | uwb_rsv_cleanup(rc); | 313 | uwb_rsv_remove_all(rc); |
310 | uwb_rc_ie_rm(rc, UWB_IDENTIFICATION_IE); | 314 | uwb_radio_shutdown(rc); |
311 | if (rc->beaconing >= 0) | ||
312 | uwb_rc_beacon(rc, -1, 0); | ||
313 | if (rc->scan_type != UWB_SCAN_DISABLED) | ||
314 | uwb_rc_scan(rc, rc->scanning, UWB_SCAN_DISABLED, 0); | ||
315 | uwb_rc_reset(rc); | ||
316 | 315 | ||
317 | rc->stop(rc); | 316 | rc->stop(rc); |
318 | uwbd_flush(rc); | 317 | |
318 | uwbd_stop(rc); | ||
319 | uwb_rc_neh_destroy(rc); | ||
319 | 320 | ||
320 | uwb_dev_lock(&rc->uwb_dev); | 321 | uwb_dev_lock(&rc->uwb_dev); |
321 | rc->priv = NULL; | 322 | rc->priv = NULL; |
322 | rc->cmd = NULL; | 323 | rc->cmd = NULL; |
323 | uwb_dev_unlock(&rc->uwb_dev); | 324 | uwb_dev_unlock(&rc->uwb_dev); |
324 | mutex_lock(&uwb_beca.mutex); | 325 | mutex_lock(&rc->uwb_beca.mutex); |
325 | uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); | 326 | uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); |
326 | __uwb_rc_sys_rm(rc); | 327 | __uwb_rc_sys_rm(rc); |
327 | mutex_unlock(&uwb_beca.mutex); | 328 | mutex_unlock(&rc->uwb_beca.mutex); |
329 | uwb_rsv_cleanup(rc); | ||
330 | uwb_beca_release(rc); | ||
328 | uwb_dev_rm(&rc->uwb_dev); | 331 | uwb_dev_rm(&rc->uwb_dev); |
329 | } | 332 | } |
330 | EXPORT_SYMBOL_GPL(uwb_rc_rm); | 333 | EXPORT_SYMBOL_GPL(uwb_rc_rm); |
@@ -468,28 +471,3 @@ void uwb_rc_put(struct uwb_rc *rc) | |||
468 | __uwb_rc_put(rc); | 471 | __uwb_rc_put(rc); |
469 | } | 472 | } |
470 | EXPORT_SYMBOL_GPL(uwb_rc_put); | 473 | EXPORT_SYMBOL_GPL(uwb_rc_put); |
471 | |||
472 | /* | ||
473 | * | ||
474 | * | ||
475 | */ | ||
476 | ssize_t uwb_rc_print_IEs(struct uwb_rc *uwb_rc, char *buf, size_t size) | ||
477 | { | ||
478 | ssize_t result; | ||
479 | struct uwb_rc_evt_get_ie *ie_info; | ||
480 | struct uwb_buf_ctx ctx; | ||
481 | |||
482 | result = uwb_rc_get_ie(uwb_rc, &ie_info); | ||
483 | if (result < 0) | ||
484 | goto error_get_ie; | ||
485 | ctx.buf = buf; | ||
486 | ctx.size = size; | ||
487 | ctx.bytes = 0; | ||
488 | uwb_ie_for_each(&uwb_rc->uwb_dev, uwb_ie_dump_hex, &ctx, | ||
489 | ie_info->IEData, result - sizeof(*ie_info)); | ||
490 | result = ctx.bytes; | ||
491 | kfree(ie_info); | ||
492 | error_get_ie: | ||
493 | return result; | ||
494 | } | ||
495 | |||
diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c index 9b4eb64327ac..48b4ece1a627 100644 --- a/drivers/uwb/neh.c +++ b/drivers/uwb/neh.c | |||
@@ -254,7 +254,6 @@ error_kzalloc: | |||
254 | 254 | ||
255 | static void __uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) | 255 | static void __uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) |
256 | { | 256 | { |
257 | del_timer(&neh->timer); | ||
258 | __uwb_rc_ctx_put(rc, neh); | 257 | __uwb_rc_ctx_put(rc, neh); |
259 | list_del(&neh->list_node); | 258 | list_del(&neh->list_node); |
260 | } | 259 | } |
@@ -275,6 +274,7 @@ void uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) | |||
275 | __uwb_rc_neh_rm(rc, neh); | 274 | __uwb_rc_neh_rm(rc, neh); |
276 | spin_unlock_irqrestore(&rc->neh_lock, flags); | 275 | spin_unlock_irqrestore(&rc->neh_lock, flags); |
277 | 276 | ||
277 | del_timer_sync(&neh->timer); | ||
278 | uwb_rc_neh_put(neh); | 278 | uwb_rc_neh_put(neh); |
279 | } | 279 | } |
280 | 280 | ||
@@ -438,9 +438,10 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size | |||
438 | rceb->bEventContext, size); | 438 | rceb->bEventContext, size); |
439 | } else { | 439 | } else { |
440 | neh = uwb_rc_neh_lookup(rc, rceb); | 440 | neh = uwb_rc_neh_lookup(rc, rceb); |
441 | if (neh) | 441 | if (neh) { |
442 | del_timer_sync(&neh->timer); | ||
442 | uwb_rc_neh_cb(neh, rceb, size); | 443 | uwb_rc_neh_cb(neh, rceb, size); |
443 | else | 444 | } else |
444 | dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n", | 445 | dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n", |
445 | rceb->bEventType, le16_to_cpu(rceb->wEvent), | 446 | rceb->bEventType, le16_to_cpu(rceb->wEvent), |
446 | rceb->bEventContext, size); | 447 | rceb->bEventContext, size); |
@@ -562,16 +563,22 @@ EXPORT_SYMBOL_GPL(uwb_rc_neh_grok); | |||
562 | */ | 563 | */ |
563 | void uwb_rc_neh_error(struct uwb_rc *rc, int error) | 564 | void uwb_rc_neh_error(struct uwb_rc *rc, int error) |
564 | { | 565 | { |
565 | struct uwb_rc_neh *neh, *next; | 566 | struct uwb_rc_neh *neh; |
566 | unsigned long flags; | 567 | unsigned long flags; |
567 | 568 | ||
568 | BUG_ON(error >= 0); | 569 | for (;;) { |
569 | spin_lock_irqsave(&rc->neh_lock, flags); | 570 | spin_lock_irqsave(&rc->neh_lock, flags); |
570 | list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) { | 571 | if (list_empty(&rc->neh_list)) { |
572 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
573 | break; | ||
574 | } | ||
575 | neh = list_first_entry(&rc->neh_list, struct uwb_rc_neh, list_node); | ||
571 | __uwb_rc_neh_rm(rc, neh); | 576 | __uwb_rc_neh_rm(rc, neh); |
577 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
578 | |||
579 | del_timer_sync(&neh->timer); | ||
572 | uwb_rc_neh_cb(neh, NULL, error); | 580 | uwb_rc_neh_cb(neh, NULL, error); |
573 | } | 581 | } |
574 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
575 | } | 582 | } |
576 | EXPORT_SYMBOL_GPL(uwb_rc_neh_error); | 583 | EXPORT_SYMBOL_GPL(uwb_rc_neh_error); |
577 | 584 | ||
@@ -583,10 +590,14 @@ static void uwb_rc_neh_timer(unsigned long arg) | |||
583 | unsigned long flags; | 590 | unsigned long flags; |
584 | 591 | ||
585 | spin_lock_irqsave(&rc->neh_lock, flags); | 592 | spin_lock_irqsave(&rc->neh_lock, flags); |
586 | __uwb_rc_neh_rm(rc, neh); | 593 | if (neh->context) |
594 | __uwb_rc_neh_rm(rc, neh); | ||
595 | else | ||
596 | neh = NULL; | ||
587 | spin_unlock_irqrestore(&rc->neh_lock, flags); | 597 | spin_unlock_irqrestore(&rc->neh_lock, flags); |
588 | 598 | ||
589 | uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT); | 599 | if (neh) |
600 | uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT); | ||
590 | } | 601 | } |
591 | 602 | ||
592 | /** Initializes the @rc's neh subsystem | 603 | /** Initializes the @rc's neh subsystem |
@@ -605,12 +616,19 @@ void uwb_rc_neh_create(struct uwb_rc *rc) | |||
605 | void uwb_rc_neh_destroy(struct uwb_rc *rc) | 616 | void uwb_rc_neh_destroy(struct uwb_rc *rc) |
606 | { | 617 | { |
607 | unsigned long flags; | 618 | unsigned long flags; |
608 | struct uwb_rc_neh *neh, *next; | 619 | struct uwb_rc_neh *neh; |
609 | 620 | ||
610 | spin_lock_irqsave(&rc->neh_lock, flags); | 621 | for (;;) { |
611 | list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) { | 622 | spin_lock_irqsave(&rc->neh_lock, flags); |
623 | if (list_empty(&rc->neh_list)) { | ||
624 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
625 | break; | ||
626 | } | ||
627 | neh = list_first_entry(&rc->neh_list, struct uwb_rc_neh, list_node); | ||
612 | __uwb_rc_neh_rm(rc, neh); | 628 | __uwb_rc_neh_rm(rc, neh); |
629 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
630 | |||
631 | del_timer_sync(&neh->timer); | ||
613 | uwb_rc_neh_put(neh); | 632 | uwb_rc_neh_put(neh); |
614 | } | 633 | } |
615 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
616 | } | 634 | } |
diff --git a/drivers/uwb/pal.c b/drivers/uwb/pal.c index 1afb38eacb9a..99a19c199095 100644 --- a/drivers/uwb/pal.c +++ b/drivers/uwb/pal.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/debugfs.h> | ||
19 | #include <linux/uwb.h> | 20 | #include <linux/uwb.h> |
20 | 21 | ||
21 | #include "uwb-internal.h" | 22 | #include "uwb-internal.h" |
@@ -32,13 +33,13 @@ EXPORT_SYMBOL_GPL(uwb_pal_init); | |||
32 | 33 | ||
33 | /** | 34 | /** |
34 | * uwb_pal_register - register a UWB PAL | 35 | * uwb_pal_register - register a UWB PAL |
35 | * @rc: the radio controller the PAL will be using | ||
36 | * @pal: the PAL | 36 | * @pal: the PAL |
37 | * | 37 | * |
38 | * The PAL must be initialized with uwb_pal_init(). | 38 | * The PAL must be initialized with uwb_pal_init(). |
39 | */ | 39 | */ |
40 | int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal) | 40 | int uwb_pal_register(struct uwb_pal *pal) |
41 | { | 41 | { |
42 | struct uwb_rc *rc = pal->rc; | ||
42 | int ret; | 43 | int ret; |
43 | 44 | ||
44 | if (pal->device) { | 45 | if (pal->device) { |
@@ -54,9 +55,11 @@ int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal) | |||
54 | } | 55 | } |
55 | } | 56 | } |
56 | 57 | ||
57 | spin_lock(&rc->pal_lock); | 58 | pal->debugfs_dir = uwb_dbg_create_pal_dir(pal); |
59 | |||
60 | mutex_lock(&rc->uwb_dev.mutex); | ||
58 | list_add(&pal->node, &rc->pals); | 61 | list_add(&pal->node, &rc->pals); |
59 | spin_unlock(&rc->pal_lock); | 62 | mutex_unlock(&rc->uwb_dev.mutex); |
60 | 63 | ||
61 | return 0; | 64 | return 0; |
62 | } | 65 | } |
@@ -64,14 +67,19 @@ EXPORT_SYMBOL_GPL(uwb_pal_register); | |||
64 | 67 | ||
65 | /** | 68 | /** |
66 | * uwb_pal_register - unregister a UWB PAL | 69 | * uwb_pal_register - unregister a UWB PAL |
67 | * @rc: the radio controller the PAL was using | ||
68 | * @pal: the PAL | 70 | * @pal: the PAL |
69 | */ | 71 | */ |
70 | void uwb_pal_unregister(struct uwb_rc *rc, struct uwb_pal *pal) | 72 | void uwb_pal_unregister(struct uwb_pal *pal) |
71 | { | 73 | { |
72 | spin_lock(&rc->pal_lock); | 74 | struct uwb_rc *rc = pal->rc; |
75 | |||
76 | uwb_radio_stop(pal); | ||
77 | |||
78 | mutex_lock(&rc->uwb_dev.mutex); | ||
73 | list_del(&pal->node); | 79 | list_del(&pal->node); |
74 | spin_unlock(&rc->pal_lock); | 80 | mutex_unlock(&rc->uwb_dev.mutex); |
81 | |||
82 | debugfs_remove(pal->debugfs_dir); | ||
75 | 83 | ||
76 | if (pal->device) { | 84 | if (pal->device) { |
77 | sysfs_remove_link(&rc->uwb_dev.dev.kobj, pal->name); | 85 | sysfs_remove_link(&rc->uwb_dev.dev.kobj, pal->name); |
@@ -86,6 +94,5 @@ EXPORT_SYMBOL_GPL(uwb_pal_unregister); | |||
86 | */ | 94 | */ |
87 | void uwb_rc_pal_init(struct uwb_rc *rc) | 95 | void uwb_rc_pal_init(struct uwb_rc *rc) |
88 | { | 96 | { |
89 | spin_lock_init(&rc->pal_lock); | ||
90 | INIT_LIST_HEAD(&rc->pals); | 97 | INIT_LIST_HEAD(&rc->pals); |
91 | } | 98 | } |
diff --git a/drivers/uwb/radio.c b/drivers/uwb/radio.c new file mode 100644 index 000000000000..f0d55495f5e9 --- /dev/null +++ b/drivers/uwb/radio.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * UWB radio (channel) management. | ||
3 | * | ||
4 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/uwb.h> | ||
20 | |||
21 | #include "uwb-internal.h" | ||
22 | |||
23 | |||
24 | static int uwb_radio_select_channel(struct uwb_rc *rc) | ||
25 | { | ||
26 | /* | ||
27 | * Default to channel 9 (BG1, TFC1) unless the user has | ||
28 | * selected a specific channel or there are no active PALs. | ||
29 | */ | ||
30 | if (rc->active_pals == 0) | ||
31 | return -1; | ||
32 | if (rc->beaconing_forced) | ||
33 | return rc->beaconing_forced; | ||
34 | return 9; | ||
35 | } | ||
36 | |||
37 | |||
38 | /* | ||
39 | * Notify all active PALs that the channel has changed. | ||
40 | */ | ||
41 | static void uwb_radio_channel_changed(struct uwb_rc *rc, int channel) | ||
42 | { | ||
43 | struct uwb_pal *pal; | ||
44 | |||
45 | list_for_each_entry(pal, &rc->pals, node) { | ||
46 | if (pal->channel && channel != pal->channel) { | ||
47 | pal->channel = channel; | ||
48 | if (pal->channel_changed) | ||
49 | pal->channel_changed(pal, pal->channel); | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Change to a new channel and notify any active PALs of the new | ||
56 | * channel. | ||
57 | * | ||
58 | * When stopping the radio, PALs need to be notified first so they can | ||
59 | * terminate any active reservations. | ||
60 | */ | ||
61 | static int uwb_radio_change_channel(struct uwb_rc *rc, int channel) | ||
62 | { | ||
63 | int ret = 0; | ||
64 | |||
65 | if (channel == -1) | ||
66 | uwb_radio_channel_changed(rc, channel); | ||
67 | |||
68 | if (channel != rc->beaconing) { | ||
69 | if (rc->beaconing != -1 && channel != -1) { | ||
70 | /* | ||
71 | * FIXME: should signal the channel change | ||
72 | * with a Channel Change IE. | ||
73 | */ | ||
74 | ret = uwb_radio_change_channel(rc, -1); | ||
75 | if (ret < 0) | ||
76 | return ret; | ||
77 | } | ||
78 | ret = uwb_rc_beacon(rc, channel, 0); | ||
79 | } | ||
80 | |||
81 | if (channel != -1) | ||
82 | uwb_radio_channel_changed(rc, rc->beaconing); | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * uwb_radio_start - request that the radio be started | ||
89 | * @pal: the PAL making the request. | ||
90 | * | ||
91 | * If the radio is not already active, aa suitable channel is selected | ||
92 | * and beacons are started. | ||
93 | */ | ||
94 | int uwb_radio_start(struct uwb_pal *pal) | ||
95 | { | ||
96 | struct uwb_rc *rc = pal->rc; | ||
97 | int ret = 0; | ||
98 | |||
99 | mutex_lock(&rc->uwb_dev.mutex); | ||
100 | |||
101 | if (!pal->channel) { | ||
102 | pal->channel = -1; | ||
103 | rc->active_pals++; | ||
104 | ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc)); | ||
105 | } | ||
106 | |||
107 | mutex_unlock(&rc->uwb_dev.mutex); | ||
108 | return ret; | ||
109 | } | ||
110 | EXPORT_SYMBOL_GPL(uwb_radio_start); | ||
111 | |||
112 | /** | ||
113 | * uwb_radio_stop - request tha the radio be stopped. | ||
114 | * @pal: the PAL making the request. | ||
115 | * | ||
116 | * Stops the radio if no other PAL is making use of it. | ||
117 | */ | ||
118 | void uwb_radio_stop(struct uwb_pal *pal) | ||
119 | { | ||
120 | struct uwb_rc *rc = pal->rc; | ||
121 | |||
122 | mutex_lock(&rc->uwb_dev.mutex); | ||
123 | |||
124 | if (pal->channel) { | ||
125 | rc->active_pals--; | ||
126 | uwb_radio_change_channel(rc, uwb_radio_select_channel(rc)); | ||
127 | pal->channel = 0; | ||
128 | } | ||
129 | |||
130 | mutex_unlock(&rc->uwb_dev.mutex); | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(uwb_radio_stop); | ||
133 | |||
134 | /* | ||
135 | * uwb_radio_force_channel - force a specific channel to be used | ||
136 | * @rc: the radio controller. | ||
137 | * @channel: the channel to use; -1 to force the radio to stop; 0 to | ||
138 | * use the default channel selection algorithm. | ||
139 | */ | ||
140 | int uwb_radio_force_channel(struct uwb_rc *rc, int channel) | ||
141 | { | ||
142 | int ret = 0; | ||
143 | |||
144 | mutex_lock(&rc->uwb_dev.mutex); | ||
145 | |||
146 | rc->beaconing_forced = channel; | ||
147 | ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc)); | ||
148 | |||
149 | mutex_unlock(&rc->uwb_dev.mutex); | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * uwb_radio_setup - setup the radio manager | ||
155 | * @rc: the radio controller. | ||
156 | * | ||
157 | * The radio controller is reset to ensure it's in a known state | ||
158 | * before it's used. | ||
159 | */ | ||
160 | int uwb_radio_setup(struct uwb_rc *rc) | ||
161 | { | ||
162 | return uwb_rc_reset(rc); | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * uwb_radio_reset_state - reset any radio manager state | ||
167 | * @rc: the radio controller. | ||
168 | * | ||
169 | * All internal radio manager state is reset to values corresponding | ||
170 | * to a reset radio controller. | ||
171 | */ | ||
172 | void uwb_radio_reset_state(struct uwb_rc *rc) | ||
173 | { | ||
174 | struct uwb_pal *pal; | ||
175 | |||
176 | mutex_lock(&rc->uwb_dev.mutex); | ||
177 | |||
178 | list_for_each_entry(pal, &rc->pals, node) { | ||
179 | if (pal->channel) { | ||
180 | pal->channel = -1; | ||
181 | if (pal->channel_changed) | ||
182 | pal->channel_changed(pal, -1); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | rc->beaconing = -1; | ||
187 | rc->scanning = -1; | ||
188 | |||
189 | mutex_unlock(&rc->uwb_dev.mutex); | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * uwb_radio_shutdown - shutdown the radio manager | ||
194 | * @rc: the radio controller. | ||
195 | * | ||
196 | * The radio controller is reset. | ||
197 | */ | ||
198 | void uwb_radio_shutdown(struct uwb_rc *rc) | ||
199 | { | ||
200 | uwb_radio_reset_state(rc); | ||
201 | uwb_rc_reset(rc); | ||
202 | } | ||
diff --git a/drivers/uwb/reset.c b/drivers/uwb/reset.c index 8de856fa7958..ce8283cc8098 100644 --- a/drivers/uwb/reset.c +++ b/drivers/uwb/reset.c | |||
@@ -323,17 +323,16 @@ int uwbd_msg_handle_reset(struct uwb_event *evt) | |||
323 | struct uwb_rc *rc = evt->rc; | 323 | struct uwb_rc *rc = evt->rc; |
324 | int ret; | 324 | int ret; |
325 | 325 | ||
326 | /* Need to prevent the RC hardware module going away while in | ||
327 | the rc->reset() call. */ | ||
328 | if (!try_module_get(rc->owner)) | ||
329 | return 0; | ||
330 | |||
331 | dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); | 326 | dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); |
332 | ret = rc->reset(rc); | 327 | ret = rc->reset(rc); |
333 | if (ret) | 328 | if (ret) { |
334 | dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); | 329 | dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); |
335 | 330 | goto error; | |
336 | module_put(rc->owner); | 331 | } |
332 | return 0; | ||
333 | error: | ||
334 | /* Nothing can be done except try the reset again. */ | ||
335 | uwb_rc_reset_all(rc); | ||
337 | return ret; | 336 | return ret; |
338 | } | 337 | } |
339 | 338 | ||
@@ -360,3 +359,33 @@ void uwb_rc_reset_all(struct uwb_rc *rc) | |||
360 | uwbd_event_queue(evt); | 359 | uwbd_event_queue(evt); |
361 | } | 360 | } |
362 | EXPORT_SYMBOL_GPL(uwb_rc_reset_all); | 361 | EXPORT_SYMBOL_GPL(uwb_rc_reset_all); |
362 | |||
363 | void uwb_rc_pre_reset(struct uwb_rc *rc) | ||
364 | { | ||
365 | rc->stop(rc); | ||
366 | uwbd_flush(rc); | ||
367 | |||
368 | uwb_radio_reset_state(rc); | ||
369 | uwb_rsv_remove_all(rc); | ||
370 | } | ||
371 | EXPORT_SYMBOL_GPL(uwb_rc_pre_reset); | ||
372 | |||
373 | void uwb_rc_post_reset(struct uwb_rc *rc) | ||
374 | { | ||
375 | int ret; | ||
376 | |||
377 | ret = rc->start(rc); | ||
378 | if (ret) | ||
379 | goto error; | ||
380 | ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr); | ||
381 | if (ret) | ||
382 | goto error; | ||
383 | ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr); | ||
384 | if (ret) | ||
385 | goto error; | ||
386 | return; | ||
387 | error: | ||
388 | /* Nothing can be done except try the reset again. */ | ||
389 | uwb_rc_reset_all(rc); | ||
390 | } | ||
391 | EXPORT_SYMBOL_GPL(uwb_rc_post_reset); | ||
diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c index bae16204576d..1cd84f927540 100644 --- a/drivers/uwb/rsv.c +++ b/drivers/uwb/rsv.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/version.h> | ||
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/uwb.h> | 19 | #include <linux/uwb.h> |
21 | 20 | ||
@@ -82,6 +81,23 @@ static void uwb_rsv_dump(struct uwb_rsv *rsv) | |||
82 | dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state)); | 81 | dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state)); |
83 | } | 82 | } |
84 | 83 | ||
84 | static void uwb_rsv_release(struct kref *kref) | ||
85 | { | ||
86 | struct uwb_rsv *rsv = container_of(kref, struct uwb_rsv, kref); | ||
87 | |||
88 | kfree(rsv); | ||
89 | } | ||
90 | |||
91 | static void uwb_rsv_get(struct uwb_rsv *rsv) | ||
92 | { | ||
93 | kref_get(&rsv->kref); | ||
94 | } | ||
95 | |||
96 | static void uwb_rsv_put(struct uwb_rsv *rsv) | ||
97 | { | ||
98 | kref_put(&rsv->kref, uwb_rsv_release); | ||
99 | } | ||
100 | |||
85 | /* | 101 | /* |
86 | * Get a free stream index for a reservation. | 102 | * Get a free stream index for a reservation. |
87 | * | 103 | * |
@@ -285,7 +301,8 @@ void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) | |||
285 | switch (new_state) { | 301 | switch (new_state) { |
286 | case UWB_RSV_STATE_NONE: | 302 | case UWB_RSV_STATE_NONE: |
287 | uwb_drp_avail_release(rsv->rc, &rsv->mas); | 303 | uwb_drp_avail_release(rsv->rc, &rsv->mas); |
288 | uwb_rsv_put_stream(rsv); | 304 | if (uwb_rsv_is_owner(rsv)) |
305 | uwb_rsv_put_stream(rsv); | ||
289 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_NONE); | 306 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_NONE); |
290 | uwb_rsv_callback(rsv); | 307 | uwb_rsv_callback(rsv); |
291 | break; | 308 | break; |
@@ -324,6 +341,7 @@ static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc) | |||
324 | 341 | ||
325 | INIT_LIST_HEAD(&rsv->rc_node); | 342 | INIT_LIST_HEAD(&rsv->rc_node); |
326 | INIT_LIST_HEAD(&rsv->pal_node); | 343 | INIT_LIST_HEAD(&rsv->pal_node); |
344 | kref_init(&rsv->kref); | ||
327 | init_timer(&rsv->timer); | 345 | init_timer(&rsv->timer); |
328 | rsv->timer.function = uwb_rsv_timer; | 346 | rsv->timer.function = uwb_rsv_timer; |
329 | rsv->timer.data = (unsigned long)rsv; | 347 | rsv->timer.data = (unsigned long)rsv; |
@@ -333,14 +351,6 @@ static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc) | |||
333 | return rsv; | 351 | return rsv; |
334 | } | 352 | } |
335 | 353 | ||
336 | static void uwb_rsv_free(struct uwb_rsv *rsv) | ||
337 | { | ||
338 | uwb_dev_put(rsv->owner); | ||
339 | if (rsv->target.type == UWB_RSV_TARGET_DEV) | ||
340 | uwb_dev_put(rsv->target.dev); | ||
341 | kfree(rsv); | ||
342 | } | ||
343 | |||
344 | /** | 354 | /** |
345 | * uwb_rsv_create - allocate and initialize a UWB reservation structure | 355 | * uwb_rsv_create - allocate and initialize a UWB reservation structure |
346 | * @rc: the radio controller | 356 | * @rc: the radio controller |
@@ -374,23 +384,23 @@ void uwb_rsv_remove(struct uwb_rsv *rsv) | |||
374 | if (rsv->state != UWB_RSV_STATE_NONE) | 384 | if (rsv->state != UWB_RSV_STATE_NONE) |
375 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | 385 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); |
376 | del_timer_sync(&rsv->timer); | 386 | del_timer_sync(&rsv->timer); |
377 | list_del(&rsv->rc_node); | 387 | uwb_dev_put(rsv->owner); |
378 | uwb_rsv_free(rsv); | 388 | if (rsv->target.type == UWB_RSV_TARGET_DEV) |
389 | uwb_dev_put(rsv->target.dev); | ||
390 | |||
391 | list_del_init(&rsv->rc_node); | ||
392 | uwb_rsv_put(rsv); | ||
379 | } | 393 | } |
380 | 394 | ||
381 | /** | 395 | /** |
382 | * uwb_rsv_destroy - free a UWB reservation structure | 396 | * uwb_rsv_destroy - free a UWB reservation structure |
383 | * @rsv: the reservation to free | 397 | * @rsv: the reservation to free |
384 | * | 398 | * |
385 | * The reservation will be terminated if it is pending or established. | 399 | * The reservation must already be terminated. |
386 | */ | 400 | */ |
387 | void uwb_rsv_destroy(struct uwb_rsv *rsv) | 401 | void uwb_rsv_destroy(struct uwb_rsv *rsv) |
388 | { | 402 | { |
389 | struct uwb_rc *rc = rsv->rc; | 403 | uwb_rsv_put(rsv); |
390 | |||
391 | mutex_lock(&rc->rsvs_mutex); | ||
392 | uwb_rsv_remove(rsv); | ||
393 | mutex_unlock(&rc->rsvs_mutex); | ||
394 | } | 404 | } |
395 | EXPORT_SYMBOL_GPL(uwb_rsv_destroy); | 405 | EXPORT_SYMBOL_GPL(uwb_rsv_destroy); |
396 | 406 | ||
@@ -422,6 +432,7 @@ int uwb_rsv_establish(struct uwb_rsv *rsv) | |||
422 | goto out; | 432 | goto out; |
423 | } | 433 | } |
424 | 434 | ||
435 | uwb_rsv_get(rsv); | ||
425 | list_add_tail(&rsv->rc_node, &rc->reservations); | 436 | list_add_tail(&rsv->rc_node, &rc->reservations); |
426 | rsv->owner = &rc->uwb_dev; | 437 | rsv->owner = &rc->uwb_dev; |
427 | uwb_dev_get(rsv->owner); | 438 | uwb_dev_get(rsv->owner); |
@@ -477,9 +488,14 @@ EXPORT_SYMBOL_GPL(uwb_rsv_terminate); | |||
477 | * | 488 | * |
478 | * Reservation requests from peers are denied unless a PAL accepts it | 489 | * Reservation requests from peers are denied unless a PAL accepts it |
479 | * by calling this function. | 490 | * by calling this function. |
491 | * | ||
492 | * The PAL call uwb_rsv_destroy() for all accepted reservations before | ||
493 | * calling uwb_pal_unregister(). | ||
480 | */ | 494 | */ |
481 | void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv) | 495 | void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv) |
482 | { | 496 | { |
497 | uwb_rsv_get(rsv); | ||
498 | |||
483 | rsv->callback = cb; | 499 | rsv->callback = cb; |
484 | rsv->pal_priv = pal_priv; | 500 | rsv->pal_priv = pal_priv; |
485 | rsv->state = UWB_RSV_STATE_T_ACCEPTED; | 501 | rsv->state = UWB_RSV_STATE_T_ACCEPTED; |
@@ -532,7 +548,6 @@ static struct uwb_rsv *uwb_rsv_new_target(struct uwb_rc *rc, | |||
532 | rsv->target.dev = &rc->uwb_dev; | 548 | rsv->target.dev = &rc->uwb_dev; |
533 | rsv->type = uwb_ie_drp_type(drp_ie); | 549 | rsv->type = uwb_ie_drp_type(drp_ie); |
534 | rsv->stream = uwb_ie_drp_stream_index(drp_ie); | 550 | rsv->stream = uwb_ie_drp_stream_index(drp_ie); |
535 | set_bit(rsv->stream, rsv->owner->streams); | ||
536 | uwb_drp_ie_to_bm(&rsv->mas, drp_ie); | 551 | uwb_drp_ie_to_bm(&rsv->mas, drp_ie); |
537 | 552 | ||
538 | /* | 553 | /* |
@@ -540,14 +555,14 @@ static struct uwb_rsv *uwb_rsv_new_target(struct uwb_rc *rc, | |||
540 | * deny the request. | 555 | * deny the request. |
541 | */ | 556 | */ |
542 | rsv->state = UWB_RSV_STATE_T_DENIED; | 557 | rsv->state = UWB_RSV_STATE_T_DENIED; |
543 | spin_lock(&rc->pal_lock); | 558 | mutex_lock(&rc->uwb_dev.mutex); |
544 | list_for_each_entry(pal, &rc->pals, node) { | 559 | list_for_each_entry(pal, &rc->pals, node) { |
545 | if (pal->new_rsv) | 560 | if (pal->new_rsv) |
546 | pal->new_rsv(rsv); | 561 | pal->new_rsv(pal, rsv); |
547 | if (rsv->state == UWB_RSV_STATE_T_ACCEPTED) | 562 | if (rsv->state == UWB_RSV_STATE_T_ACCEPTED) |
548 | break; | 563 | break; |
549 | } | 564 | } |
550 | spin_unlock(&rc->pal_lock); | 565 | mutex_unlock(&rc->uwb_dev.mutex); |
551 | 566 | ||
552 | list_add_tail(&rsv->rc_node, &rc->reservations); | 567 | list_add_tail(&rsv->rc_node, &rc->reservations); |
553 | state = rsv->state; | 568 | state = rsv->state; |
@@ -644,6 +659,25 @@ static void uwb_rsv_timer(unsigned long arg) | |||
644 | uwb_rsv_sched_update(rsv->rc); | 659 | uwb_rsv_sched_update(rsv->rc); |
645 | } | 660 | } |
646 | 661 | ||
662 | /** | ||
663 | * uwb_rsv_remove_all - remove all reservations | ||
664 | * @rc: the radio controller | ||
665 | * | ||
666 | * A DRP IE update is not done. | ||
667 | */ | ||
668 | void uwb_rsv_remove_all(struct uwb_rc *rc) | ||
669 | { | ||
670 | struct uwb_rsv *rsv, *t; | ||
671 | |||
672 | mutex_lock(&rc->rsvs_mutex); | ||
673 | list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { | ||
674 | uwb_rsv_remove(rsv); | ||
675 | } | ||
676 | mutex_unlock(&rc->rsvs_mutex); | ||
677 | |||
678 | cancel_work_sync(&rc->rsv_update_work); | ||
679 | } | ||
680 | |||
647 | void uwb_rsv_init(struct uwb_rc *rc) | 681 | void uwb_rsv_init(struct uwb_rc *rc) |
648 | { | 682 | { |
649 | INIT_LIST_HEAD(&rc->reservations); | 683 | INIT_LIST_HEAD(&rc->reservations); |
@@ -667,14 +701,6 @@ int uwb_rsv_setup(struct uwb_rc *rc) | |||
667 | 701 | ||
668 | void uwb_rsv_cleanup(struct uwb_rc *rc) | 702 | void uwb_rsv_cleanup(struct uwb_rc *rc) |
669 | { | 703 | { |
670 | struct uwb_rsv *rsv, *t; | 704 | uwb_rsv_remove_all(rc); |
671 | |||
672 | mutex_lock(&rc->rsvs_mutex); | ||
673 | list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { | ||
674 | uwb_rsv_remove(rsv); | ||
675 | } | ||
676 | mutex_unlock(&rc->rsvs_mutex); | ||
677 | |||
678 | cancel_work_sync(&rc->rsv_update_work); | ||
679 | destroy_workqueue(rc->rsv_workq); | 705 | destroy_workqueue(rc->rsv_workq); |
680 | } | 706 | } |
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c index 2d8d62d9f53e..5ad36164c13b 100644 --- a/drivers/uwb/umc-bus.c +++ b/drivers/uwb/umc-bus.c | |||
@@ -11,23 +11,48 @@ | |||
11 | #include <linux/uwb/umc.h> | 11 | #include <linux/uwb/umc.h> |
12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
13 | 13 | ||
14 | static int umc_bus_unbind_helper(struct device *dev, void *data) | 14 | static int umc_bus_pre_reset_helper(struct device *dev, void *data) |
15 | { | 15 | { |
16 | struct device *parent = data; | 16 | int ret = 0; |
17 | 17 | ||
18 | if (dev->parent == parent && dev->driver) | 18 | if (dev->driver) { |
19 | device_release_driver(dev); | 19 | struct umc_dev *umc = to_umc_dev(dev); |
20 | return 0; | 20 | struct umc_driver *umc_drv = to_umc_driver(dev->driver); |
21 | |||
22 | if (umc_drv->pre_reset) | ||
23 | ret = umc_drv->pre_reset(umc); | ||
24 | else | ||
25 | device_release_driver(dev); | ||
26 | } | ||
27 | return ret; | ||
28 | } | ||
29 | |||
30 | static int umc_bus_post_reset_helper(struct device *dev, void *data) | ||
31 | { | ||
32 | int ret = 0; | ||
33 | |||
34 | if (dev->driver) { | ||
35 | struct umc_dev *umc = to_umc_dev(dev); | ||
36 | struct umc_driver *umc_drv = to_umc_driver(dev->driver); | ||
37 | |||
38 | if (umc_drv->post_reset) | ||
39 | ret = umc_drv->post_reset(umc); | ||
40 | } else | ||
41 | ret = device_attach(dev); | ||
42 | |||
43 | return ret; | ||
21 | } | 44 | } |
22 | 45 | ||
23 | /** | 46 | /** |
24 | * umc_controller_reset - reset the whole UMC controller | 47 | * umc_controller_reset - reset the whole UMC controller |
25 | * @umc: the UMC device for the radio controller. | 48 | * @umc: the UMC device for the radio controller. |
26 | * | 49 | * |
27 | * Drivers will be unbound from all UMC devices belonging to the | 50 | * Drivers or all capabilities of the controller will have their |
28 | * controller and then the radio controller will be rebound. The | 51 | * pre_reset methods called or be unbound from their device. Then all |
29 | * radio controller is expected to do a full hardware reset when it is | 52 | * post_reset methods will be called or the drivers will be rebound. |
30 | * probed. | 53 | * |
54 | * Radio controllers must provide pre_reset and post_reset methods and | ||
55 | * reset the hardware in their start method. | ||
31 | * | 56 | * |
32 | * If this is called while a probe() or remove() is in progress it | 57 | * If this is called while a probe() or remove() is in progress it |
33 | * will return -EAGAIN and not perform the reset. | 58 | * will return -EAGAIN and not perform the reset. |
@@ -35,14 +60,13 @@ static int umc_bus_unbind_helper(struct device *dev, void *data) | |||
35 | int umc_controller_reset(struct umc_dev *umc) | 60 | int umc_controller_reset(struct umc_dev *umc) |
36 | { | 61 | { |
37 | struct device *parent = umc->dev.parent; | 62 | struct device *parent = umc->dev.parent; |
38 | int ret; | 63 | int ret = 0; |
39 | 64 | ||
40 | if (down_trylock(&parent->sem)) | 65 | if(down_trylock(&parent->sem)) |
41 | return -EAGAIN; | 66 | return -EAGAIN; |
42 | bus_for_each_dev(&umc_bus_type, NULL, parent, umc_bus_unbind_helper); | 67 | ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper); |
43 | ret = device_attach(&umc->dev); | 68 | if (ret >= 0) |
44 | if (ret == 1) | 69 | device_for_each_child(parent, parent, umc_bus_post_reset_helper); |
45 | ret = 0; | ||
46 | up(&parent->sem); | 70 | up(&parent->sem); |
47 | 71 | ||
48 | return ret; | 72 | return ret; |
@@ -75,10 +99,10 @@ static int umc_bus_rescan_helper(struct device *dev, void *data) | |||
75 | if (!dev->driver) | 99 | if (!dev->driver) |
76 | ret = device_attach(dev); | 100 | ret = device_attach(dev); |
77 | 101 | ||
78 | return ret < 0 ? ret : 0; | 102 | return ret; |
79 | } | 103 | } |
80 | 104 | ||
81 | static void umc_bus_rescan(void) | 105 | static void umc_bus_rescan(struct device *parent) |
82 | { | 106 | { |
83 | int err; | 107 | int err; |
84 | 108 | ||
@@ -86,7 +110,7 @@ static void umc_bus_rescan(void) | |||
86 | * We can't use bus_rescan_devices() here as it deadlocks when | 110 | * We can't use bus_rescan_devices() here as it deadlocks when |
87 | * it tries to retake the dev->parent semaphore. | 111 | * it tries to retake the dev->parent semaphore. |
88 | */ | 112 | */ |
89 | err = bus_for_each_dev(&umc_bus_type, NULL, NULL, umc_bus_rescan_helper); | 113 | err = device_for_each_child(parent, NULL, umc_bus_rescan_helper); |
90 | if (err < 0) | 114 | if (err < 0) |
91 | printk(KERN_WARNING "%s: rescan of bus failed: %d\n", | 115 | printk(KERN_WARNING "%s: rescan of bus failed: %d\n", |
92 | KBUILD_MODNAME, err); | 116 | KBUILD_MODNAME, err); |
@@ -120,7 +144,7 @@ static int umc_device_probe(struct device *dev) | |||
120 | if (err) | 144 | if (err) |
121 | put_device(dev); | 145 | put_device(dev); |
122 | else | 146 | else |
123 | umc_bus_rescan(); | 147 | umc_bus_rescan(dev->parent); |
124 | 148 | ||
125 | return err; | 149 | return err; |
126 | } | 150 | } |
diff --git a/drivers/uwb/umc-dev.c b/drivers/uwb/umc-dev.c index aa44e1c1a102..53207e14cd8f 100644 --- a/drivers/uwb/umc-dev.c +++ b/drivers/uwb/umc-dev.c | |||
@@ -31,8 +31,7 @@ struct umc_dev *umc_device_create(struct device *parent, int n) | |||
31 | 31 | ||
32 | umc = kzalloc(sizeof(struct umc_dev), GFP_KERNEL); | 32 | umc = kzalloc(sizeof(struct umc_dev), GFP_KERNEL); |
33 | if (umc) { | 33 | if (umc) { |
34 | snprintf(umc->dev.bus_id, sizeof(umc->dev.bus_id), "%s-%d", | 34 | dev_set_name(&umc->dev, "%s-%d", dev_name(parent), n); |
35 | parent->bus_id, n); | ||
36 | umc->dev.parent = parent; | 35 | umc->dev.parent = parent; |
37 | umc->dev.bus = &umc_bus_type; | 36 | umc->dev.bus = &umc_bus_type; |
38 | umc->dev.release = umc_device_release; | 37 | umc->dev.release = umc_device_release; |
diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c index 6d232c35d07d..a6debb9baf38 100644 --- a/drivers/uwb/uwb-debug.c +++ b/drivers/uwb/uwb-debug.c | |||
@@ -33,8 +33,6 @@ | |||
33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
34 | 34 | ||
35 | #include <linux/uwb/debug-cmd.h> | 35 | #include <linux/uwb/debug-cmd.h> |
36 | #define D_LOCAL 0 | ||
37 | #include <linux/uwb/debug.h> | ||
38 | 36 | ||
39 | #include "uwb-internal.h" | 37 | #include "uwb-internal.h" |
40 | 38 | ||
@@ -104,6 +102,11 @@ static void uwb_dbg_rsv_cb(struct uwb_rsv *rsv) | |||
104 | 102 | ||
105 | dev_dbg(dev, "debug: rsv %s -> %s: %s\n", | 103 | dev_dbg(dev, "debug: rsv %s -> %s: %s\n", |
106 | owner, target, uwb_rsv_state_str(rsv->state)); | 104 | owner, target, uwb_rsv_state_str(rsv->state)); |
105 | |||
106 | if (rsv->state == UWB_RSV_STATE_NONE) { | ||
107 | list_del(&rsv->pal_node); | ||
108 | uwb_rsv_destroy(rsv); | ||
109 | } | ||
107 | } | 110 | } |
108 | 111 | ||
109 | static int cmd_rsv_establish(struct uwb_rc *rc, | 112 | static int cmd_rsv_establish(struct uwb_rc *rc, |
@@ -119,7 +122,7 @@ static int cmd_rsv_establish(struct uwb_rc *rc, | |||
119 | if (target == NULL) | 122 | if (target == NULL) |
120 | return -ENODEV; | 123 | return -ENODEV; |
121 | 124 | ||
122 | rsv = uwb_rsv_create(rc, uwb_dbg_rsv_cb, NULL); | 125 | rsv = uwb_rsv_create(rc, uwb_dbg_rsv_cb, rc->dbg); |
123 | if (rsv == NULL) { | 126 | if (rsv == NULL) { |
124 | uwb_dev_put(target); | 127 | uwb_dev_put(target); |
125 | return -ENOMEM; | 128 | return -ENOMEM; |
@@ -153,16 +156,28 @@ static int cmd_rsv_terminate(struct uwb_rc *rc, | |||
153 | found = rsv; | 156 | found = rsv; |
154 | break; | 157 | break; |
155 | } | 158 | } |
159 | i++; | ||
156 | } | 160 | } |
157 | if (!found) | 161 | if (!found) |
158 | return -EINVAL; | 162 | return -EINVAL; |
159 | 163 | ||
160 | list_del(&found->pal_node); | ||
161 | uwb_rsv_terminate(found); | 164 | uwb_rsv_terminate(found); |
162 | 165 | ||
163 | return 0; | 166 | return 0; |
164 | } | 167 | } |
165 | 168 | ||
169 | static int cmd_ie_add(struct uwb_rc *rc, struct uwb_dbg_cmd_ie *ie_to_add) | ||
170 | { | ||
171 | return uwb_rc_ie_add(rc, | ||
172 | (const struct uwb_ie_hdr *) ie_to_add->data, | ||
173 | ie_to_add->len); | ||
174 | } | ||
175 | |||
176 | static int cmd_ie_rm(struct uwb_rc *rc, struct uwb_dbg_cmd_ie *ie_to_rm) | ||
177 | { | ||
178 | return uwb_rc_ie_rm(rc, ie_to_rm->data[0]); | ||
179 | } | ||
180 | |||
166 | static int command_open(struct inode *inode, struct file *file) | 181 | static int command_open(struct inode *inode, struct file *file) |
167 | { | 182 | { |
168 | file->private_data = inode->i_private; | 183 | file->private_data = inode->i_private; |
@@ -175,7 +190,7 @@ static ssize_t command_write(struct file *file, const char __user *buf, | |||
175 | { | 190 | { |
176 | struct uwb_rc *rc = file->private_data; | 191 | struct uwb_rc *rc = file->private_data; |
177 | struct uwb_dbg_cmd cmd; | 192 | struct uwb_dbg_cmd cmd; |
178 | int ret; | 193 | int ret = 0; |
179 | 194 | ||
180 | if (len != sizeof(struct uwb_dbg_cmd)) | 195 | if (len != sizeof(struct uwb_dbg_cmd)) |
181 | return -EINVAL; | 196 | return -EINVAL; |
@@ -190,6 +205,18 @@ static ssize_t command_write(struct file *file, const char __user *buf, | |||
190 | case UWB_DBG_CMD_RSV_TERMINATE: | 205 | case UWB_DBG_CMD_RSV_TERMINATE: |
191 | ret = cmd_rsv_terminate(rc, &cmd.rsv_terminate); | 206 | ret = cmd_rsv_terminate(rc, &cmd.rsv_terminate); |
192 | break; | 207 | break; |
208 | case UWB_DBG_CMD_IE_ADD: | ||
209 | ret = cmd_ie_add(rc, &cmd.ie_add); | ||
210 | break; | ||
211 | case UWB_DBG_CMD_IE_RM: | ||
212 | ret = cmd_ie_rm(rc, &cmd.ie_rm); | ||
213 | break; | ||
214 | case UWB_DBG_CMD_RADIO_START: | ||
215 | ret = uwb_radio_start(&rc->dbg->pal); | ||
216 | break; | ||
217 | case UWB_DBG_CMD_RADIO_STOP: | ||
218 | uwb_radio_stop(&rc->dbg->pal); | ||
219 | break; | ||
193 | default: | 220 | default: |
194 | return -EINVAL; | 221 | return -EINVAL; |
195 | } | 222 | } |
@@ -283,12 +310,24 @@ static struct file_operations drp_avail_fops = { | |||
283 | .owner = THIS_MODULE, | 310 | .owner = THIS_MODULE, |
284 | }; | 311 | }; |
285 | 312 | ||
286 | static void uwb_dbg_new_rsv(struct uwb_rsv *rsv) | 313 | static void uwb_dbg_channel_changed(struct uwb_pal *pal, int channel) |
287 | { | 314 | { |
288 | struct uwb_rc *rc = rsv->rc; | 315 | struct device *dev = &pal->rc->uwb_dev.dev; |
289 | 316 | ||
290 | if (rc->dbg->accept) | 317 | if (channel > 0) |
291 | uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, NULL); | 318 | dev_info(dev, "debug: channel %d started\n", channel); |
319 | else | ||
320 | dev_info(dev, "debug: channel stopped\n"); | ||
321 | } | ||
322 | |||
323 | static void uwb_dbg_new_rsv(struct uwb_pal *pal, struct uwb_rsv *rsv) | ||
324 | { | ||
325 | struct uwb_dbg *dbg = container_of(pal, struct uwb_dbg, pal); | ||
326 | |||
327 | if (dbg->accept) { | ||
328 | list_add_tail(&rsv->pal_node, &dbg->rsvs); | ||
329 | uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, dbg); | ||
330 | } | ||
292 | } | 331 | } |
293 | 332 | ||
294 | /** | 333 | /** |
@@ -304,8 +343,11 @@ void uwb_dbg_add_rc(struct uwb_rc *rc) | |||
304 | INIT_LIST_HEAD(&rc->dbg->rsvs); | 343 | INIT_LIST_HEAD(&rc->dbg->rsvs); |
305 | 344 | ||
306 | uwb_pal_init(&rc->dbg->pal); | 345 | uwb_pal_init(&rc->dbg->pal); |
346 | rc->dbg->pal.rc = rc; | ||
347 | rc->dbg->pal.channel_changed = uwb_dbg_channel_changed; | ||
307 | rc->dbg->pal.new_rsv = uwb_dbg_new_rsv; | 348 | rc->dbg->pal.new_rsv = uwb_dbg_new_rsv; |
308 | uwb_pal_register(rc, &rc->dbg->pal); | 349 | uwb_pal_register(&rc->dbg->pal); |
350 | |||
309 | if (root_dir) { | 351 | if (root_dir) { |
310 | rc->dbg->root_d = debugfs_create_dir(dev_name(&rc->uwb_dev.dev), | 352 | rc->dbg->root_d = debugfs_create_dir(dev_name(&rc->uwb_dev.dev), |
311 | root_dir); | 353 | root_dir); |
@@ -325,7 +367,7 @@ void uwb_dbg_add_rc(struct uwb_rc *rc) | |||
325 | } | 367 | } |
326 | 368 | ||
327 | /** | 369 | /** |
328 | * uwb_dbg_add_rc - remove a radio controller's debug interface | 370 | * uwb_dbg_del_rc - remove a radio controller's debug interface |
329 | * @rc: the radio controller | 371 | * @rc: the radio controller |
330 | */ | 372 | */ |
331 | void uwb_dbg_del_rc(struct uwb_rc *rc) | 373 | void uwb_dbg_del_rc(struct uwb_rc *rc) |
@@ -336,10 +378,10 @@ void uwb_dbg_del_rc(struct uwb_rc *rc) | |||
336 | return; | 378 | return; |
337 | 379 | ||
338 | list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) { | 380 | list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) { |
339 | uwb_rsv_destroy(rsv); | 381 | uwb_rsv_terminate(rsv); |
340 | } | 382 | } |
341 | 383 | ||
342 | uwb_pal_unregister(rc, &rc->dbg->pal); | 384 | uwb_pal_unregister(&rc->dbg->pal); |
343 | 385 | ||
344 | if (root_dir) { | 386 | if (root_dir) { |
345 | debugfs_remove(rc->dbg->drp_avail_f); | 387 | debugfs_remove(rc->dbg->drp_avail_f); |
@@ -365,3 +407,16 @@ void uwb_dbg_exit(void) | |||
365 | { | 407 | { |
366 | debugfs_remove(root_dir); | 408 | debugfs_remove(root_dir); |
367 | } | 409 | } |
410 | |||
411 | /** | ||
412 | * uwb_dbg_create_pal_dir - create a debugfs directory for a PAL | ||
413 | * @pal: The PAL. | ||
414 | */ | ||
415 | struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal) | ||
416 | { | ||
417 | struct uwb_rc *rc = pal->rc; | ||
418 | |||
419 | if (root_dir && rc->dbg && rc->dbg->root_d && pal->name) | ||
420 | return debugfs_create_dir(pal->name, rc->dbg->root_d); | ||
421 | return NULL; | ||
422 | } | ||
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h index 2ad307d12961..f0f21f406bf0 100644 --- a/drivers/uwb/uwb-internal.h +++ b/drivers/uwb/uwb-internal.h | |||
@@ -66,14 +66,14 @@ extern int uwb_rc_scan(struct uwb_rc *rc, | |||
66 | unsigned channel, enum uwb_scan_type type, | 66 | unsigned channel, enum uwb_scan_type type, |
67 | unsigned bpst_offset); | 67 | unsigned bpst_offset); |
68 | extern int uwb_rc_send_all_drp_ie(struct uwb_rc *rc); | 68 | extern int uwb_rc_send_all_drp_ie(struct uwb_rc *rc); |
69 | extern ssize_t uwb_rc_print_IEs(struct uwb_rc *rc, char *, size_t); | 69 | |
70 | extern void uwb_rc_ie_init(struct uwb_rc *); | 70 | void uwb_rc_ie_init(struct uwb_rc *); |
71 | extern void uwb_rc_ie_init(struct uwb_rc *); | 71 | int uwb_rc_ie_setup(struct uwb_rc *); |
72 | extern ssize_t uwb_rc_ie_setup(struct uwb_rc *); | 72 | void uwb_rc_ie_release(struct uwb_rc *); |
73 | extern void uwb_rc_ie_release(struct uwb_rc *); | 73 | int uwb_ie_dump_hex(const struct uwb_ie_hdr *ies, size_t len, |
74 | extern int uwb_rc_ie_add(struct uwb_rc *, | 74 | char *buf, size_t size); |
75 | const struct uwb_ie_hdr *, size_t); | 75 | int uwb_rc_set_ie(struct uwb_rc *, struct uwb_rc_cmd_set_ie *); |
76 | extern int uwb_rc_ie_rm(struct uwb_rc *, enum uwb_ie); | 76 | |
77 | 77 | ||
78 | extern const char *uwb_rc_strerror(unsigned code); | 78 | extern const char *uwb_rc_strerror(unsigned code); |
79 | 79 | ||
@@ -160,13 +160,14 @@ struct uwb_event { | |||
160 | }; | 160 | }; |
161 | }; | 161 | }; |
162 | 162 | ||
163 | extern void uwbd_start(void); | 163 | extern void uwbd_start(struct uwb_rc *rc); |
164 | extern void uwbd_stop(void); | 164 | extern void uwbd_stop(struct uwb_rc *rc); |
165 | extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask); | 165 | extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask); |
166 | extern void uwbd_event_queue(struct uwb_event *); | 166 | extern void uwbd_event_queue(struct uwb_event *); |
167 | void uwbd_flush(struct uwb_rc *rc); | 167 | void uwbd_flush(struct uwb_rc *rc); |
168 | 168 | ||
169 | /* UWB event handlers */ | 169 | /* UWB event handlers */ |
170 | extern int uwbd_evt_handle_rc_ie_rcv(struct uwb_event *); | ||
170 | extern int uwbd_evt_handle_rc_beacon(struct uwb_event *); | 171 | extern int uwbd_evt_handle_rc_beacon(struct uwb_event *); |
171 | extern int uwbd_evt_handle_rc_beacon_size(struct uwb_event *); | 172 | extern int uwbd_evt_handle_rc_beacon_size(struct uwb_event *); |
172 | extern int uwbd_evt_handle_rc_bpoie_change(struct uwb_event *); | 173 | extern int uwbd_evt_handle_rc_bpoie_change(struct uwb_event *); |
@@ -193,15 +194,6 @@ int uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt); | |||
193 | 194 | ||
194 | extern unsigned long beacon_timeout_ms; | 195 | extern unsigned long beacon_timeout_ms; |
195 | 196 | ||
196 | /** Beacon cache list */ | ||
197 | struct uwb_beca { | ||
198 | struct list_head list; | ||
199 | size_t entries; | ||
200 | struct mutex mutex; | ||
201 | }; | ||
202 | |||
203 | extern struct uwb_beca uwb_beca; | ||
204 | |||
205 | /** | 197 | /** |
206 | * Beacon cache entry | 198 | * Beacon cache entry |
207 | * | 199 | * |
@@ -228,9 +220,6 @@ struct uwb_beca_e { | |||
228 | struct uwb_beacon_frame; | 220 | struct uwb_beacon_frame; |
229 | extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *, | 221 | extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *, |
230 | char *, size_t); | 222 | char *, size_t); |
231 | extern struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *, | ||
232 | struct uwb_beacon_frame *, | ||
233 | unsigned long); | ||
234 | 223 | ||
235 | extern void uwb_bce_kfree(struct kref *_bce); | 224 | extern void uwb_bce_kfree(struct kref *_bce); |
236 | static inline void uwb_bce_get(struct uwb_beca_e *bce) | 225 | static inline void uwb_bce_get(struct uwb_beca_e *bce) |
@@ -241,14 +230,19 @@ static inline void uwb_bce_put(struct uwb_beca_e *bce) | |||
241 | { | 230 | { |
242 | kref_put(&bce->refcnt, uwb_bce_kfree); | 231 | kref_put(&bce->refcnt, uwb_bce_kfree); |
243 | } | 232 | } |
244 | extern void uwb_beca_purge(void); | 233 | extern void uwb_beca_purge(struct uwb_rc *rc); |
245 | extern void uwb_beca_release(void); | 234 | extern void uwb_beca_release(struct uwb_rc *rc); |
246 | 235 | ||
247 | struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, | 236 | struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, |
248 | const struct uwb_dev_addr *devaddr); | 237 | const struct uwb_dev_addr *devaddr); |
249 | struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, | 238 | struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, |
250 | const struct uwb_mac_addr *macaddr); | 239 | const struct uwb_mac_addr *macaddr); |
251 | 240 | ||
241 | int uwb_radio_setup(struct uwb_rc *rc); | ||
242 | void uwb_radio_reset_state(struct uwb_rc *rc); | ||
243 | void uwb_radio_shutdown(struct uwb_rc *rc); | ||
244 | int uwb_radio_force_channel(struct uwb_rc *rc, int channel); | ||
245 | |||
252 | /* -- UWB Sysfs representation */ | 246 | /* -- UWB Sysfs representation */ |
253 | extern struct class uwb_rc_class; | 247 | extern struct class uwb_rc_class; |
254 | extern struct device_attribute dev_attr_mac_address; | 248 | extern struct device_attribute dev_attr_mac_address; |
@@ -259,6 +253,7 @@ extern struct device_attribute dev_attr_scan; | |||
259 | void uwb_rsv_init(struct uwb_rc *rc); | 253 | void uwb_rsv_init(struct uwb_rc *rc); |
260 | int uwb_rsv_setup(struct uwb_rc *rc); | 254 | int uwb_rsv_setup(struct uwb_rc *rc); |
261 | void uwb_rsv_cleanup(struct uwb_rc *rc); | 255 | void uwb_rsv_cleanup(struct uwb_rc *rc); |
256 | void uwb_rsv_remove_all(struct uwb_rc *rc); | ||
262 | 257 | ||
263 | void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state); | 258 | void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state); |
264 | void uwb_rsv_remove(struct uwb_rsv *rsv); | 259 | void uwb_rsv_remove(struct uwb_rsv *rsv); |
@@ -289,8 +284,7 @@ void uwb_dbg_init(void); | |||
289 | void uwb_dbg_exit(void); | 284 | void uwb_dbg_exit(void); |
290 | void uwb_dbg_add_rc(struct uwb_rc *rc); | 285 | void uwb_dbg_add_rc(struct uwb_rc *rc); |
291 | void uwb_dbg_del_rc(struct uwb_rc *rc); | 286 | void uwb_dbg_del_rc(struct uwb_rc *rc); |
292 | 287 | struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal); | |
293 | /* Workarounds for version specific stuff */ | ||
294 | 288 | ||
295 | static inline void uwb_dev_lock(struct uwb_dev *uwb_dev) | 289 | static inline void uwb_dev_lock(struct uwb_dev *uwb_dev) |
296 | { | 290 | { |
diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c index 78908416e42c..ec42ce92dbce 100644 --- a/drivers/uwb/uwbd.c +++ b/drivers/uwb/uwbd.c | |||
@@ -104,6 +104,10 @@ struct uwbd_event { | |||
104 | /** Table of handlers for and properties of the UWBD Radio Control Events */ | 104 | /** Table of handlers for and properties of the UWBD Radio Control Events */ |
105 | static | 105 | static |
106 | struct uwbd_event uwbd_events[] = { | 106 | struct uwbd_event uwbd_events[] = { |
107 | [UWB_RC_EVT_IE_RCV] = { | ||
108 | .handler = uwbd_evt_handle_rc_ie_rcv, | ||
109 | .name = "IE_RECEIVED" | ||
110 | }, | ||
107 | [UWB_RC_EVT_BEACON] = { | 111 | [UWB_RC_EVT_BEACON] = { |
108 | .handler = uwbd_evt_handle_rc_beacon, | 112 | .handler = uwbd_evt_handle_rc_beacon, |
109 | .name = "BEACON_RECEIVED" | 113 | .name = "BEACON_RECEIVED" |
@@ -166,8 +170,6 @@ static const struct uwbd_event uwbd_message_handlers[] = { | |||
166 | }, | 170 | }, |
167 | }; | 171 | }; |
168 | 172 | ||
169 | static DEFINE_MUTEX(uwbd_event_mutex); | ||
170 | |||
171 | /** | 173 | /** |
172 | * Handle an URC event passed to the UWB Daemon | 174 | * Handle an URC event passed to the UWB Daemon |
173 | * | 175 | * |
@@ -231,19 +233,10 @@ static void uwbd_event_handle_message(struct uwb_event *evt) | |||
231 | return; | 233 | return; |
232 | } | 234 | } |
233 | 235 | ||
234 | /* If this is a reset event we need to drop the | ||
235 | * uwbd_event_mutex or it deadlocks when the reset handler | ||
236 | * attempts to flush the uwbd events. */ | ||
237 | if (evt->message == UWB_EVT_MSG_RESET) | ||
238 | mutex_unlock(&uwbd_event_mutex); | ||
239 | |||
240 | result = uwbd_message_handlers[evt->message].handler(evt); | 236 | result = uwbd_message_handlers[evt->message].handler(evt); |
241 | if (result < 0) | 237 | if (result < 0) |
242 | dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n", | 238 | dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n", |
243 | uwbd_message_handlers[evt->message].name, result); | 239 | uwbd_message_handlers[evt->message].name, result); |
244 | |||
245 | if (evt->message == UWB_EVT_MSG_RESET) | ||
246 | mutex_lock(&uwbd_event_mutex); | ||
247 | } | 240 | } |
248 | 241 | ||
249 | static void uwbd_event_handle(struct uwb_event *evt) | 242 | static void uwbd_event_handle(struct uwb_event *evt) |
@@ -271,20 +264,6 @@ static void uwbd_event_handle(struct uwb_event *evt) | |||
271 | 264 | ||
272 | __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */ | 265 | __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */ |
273 | } | 266 | } |
274 | /* The UWB Daemon */ | ||
275 | |||
276 | |||
277 | /** Daemon's PID: used to decide if we can queue or not */ | ||
278 | static int uwbd_pid; | ||
279 | /** Daemon's task struct for managing the kthread */ | ||
280 | static struct task_struct *uwbd_task; | ||
281 | /** Daemon's waitqueue for waiting for new events */ | ||
282 | static DECLARE_WAIT_QUEUE_HEAD(uwbd_wq); | ||
283 | /** Daemon's list of events; we queue/dequeue here */ | ||
284 | static struct list_head uwbd_event_list = LIST_HEAD_INIT(uwbd_event_list); | ||
285 | /** Daemon's list lock to protect concurent access */ | ||
286 | static DEFINE_SPINLOCK(uwbd_event_list_lock); | ||
287 | |||
288 | 267 | ||
289 | /** | 268 | /** |
290 | * UWB Daemon | 269 | * UWB Daemon |
@@ -298,65 +277,58 @@ static DEFINE_SPINLOCK(uwbd_event_list_lock); | |||
298 | * FIXME: should change so we don't have a 1HZ timer all the time, but | 277 | * FIXME: should change so we don't have a 1HZ timer all the time, but |
299 | * only if there are devices. | 278 | * only if there are devices. |
300 | */ | 279 | */ |
301 | static int uwbd(void *unused) | 280 | static int uwbd(void *param) |
302 | { | 281 | { |
282 | struct uwb_rc *rc = param; | ||
303 | unsigned long flags; | 283 | unsigned long flags; |
304 | struct list_head list = LIST_HEAD_INIT(list); | 284 | struct uwb_event *evt; |
305 | struct uwb_event *evt, *nxt; | ||
306 | int should_stop = 0; | 285 | int should_stop = 0; |
286 | |||
307 | while (1) { | 287 | while (1) { |
308 | wait_event_interruptible_timeout( | 288 | wait_event_interruptible_timeout( |
309 | uwbd_wq, | 289 | rc->uwbd.wq, |
310 | !list_empty(&uwbd_event_list) | 290 | !list_empty(&rc->uwbd.event_list) |
311 | || (should_stop = kthread_should_stop()), | 291 | || (should_stop = kthread_should_stop()), |
312 | HZ); | 292 | HZ); |
313 | if (should_stop) | 293 | if (should_stop) |
314 | break; | 294 | break; |
315 | try_to_freeze(); | 295 | try_to_freeze(); |
316 | 296 | ||
317 | mutex_lock(&uwbd_event_mutex); | 297 | spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); |
318 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | 298 | if (!list_empty(&rc->uwbd.event_list)) { |
319 | list_splice_init(&uwbd_event_list, &list); | 299 | evt = list_first_entry(&rc->uwbd.event_list, struct uwb_event, list_node); |
320 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | ||
321 | list_for_each_entry_safe(evt, nxt, &list, list_node) { | ||
322 | list_del(&evt->list_node); | 300 | list_del(&evt->list_node); |
301 | } else | ||
302 | evt = NULL; | ||
303 | spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); | ||
304 | |||
305 | if (evt) { | ||
323 | uwbd_event_handle(evt); | 306 | uwbd_event_handle(evt); |
324 | kfree(evt); | 307 | kfree(evt); |
325 | } | 308 | } |
326 | mutex_unlock(&uwbd_event_mutex); | ||
327 | 309 | ||
328 | uwb_beca_purge(); /* Purge devices that left */ | 310 | uwb_beca_purge(rc); /* Purge devices that left */ |
329 | } | 311 | } |
330 | return 0; | 312 | return 0; |
331 | } | 313 | } |
332 | 314 | ||
333 | 315 | ||
334 | /** Start the UWB daemon */ | 316 | /** Start the UWB daemon */ |
335 | void uwbd_start(void) | 317 | void uwbd_start(struct uwb_rc *rc) |
336 | { | 318 | { |
337 | uwbd_task = kthread_run(uwbd, NULL, "uwbd"); | 319 | rc->uwbd.task = kthread_run(uwbd, rc, "uwbd"); |
338 | if (uwbd_task == NULL) | 320 | if (rc->uwbd.task == NULL) |
339 | printk(KERN_ERR "UWB: Cannot start management daemon; " | 321 | printk(KERN_ERR "UWB: Cannot start management daemon; " |
340 | "UWB won't work\n"); | 322 | "UWB won't work\n"); |
341 | else | 323 | else |
342 | uwbd_pid = uwbd_task->pid; | 324 | rc->uwbd.pid = rc->uwbd.task->pid; |
343 | } | 325 | } |
344 | 326 | ||
345 | /* Stop the UWB daemon and free any unprocessed events */ | 327 | /* Stop the UWB daemon and free any unprocessed events */ |
346 | void uwbd_stop(void) | 328 | void uwbd_stop(struct uwb_rc *rc) |
347 | { | 329 | { |
348 | unsigned long flags; | 330 | kthread_stop(rc->uwbd.task); |
349 | struct uwb_event *evt, *nxt; | 331 | uwbd_flush(rc); |
350 | kthread_stop(uwbd_task); | ||
351 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | ||
352 | uwbd_pid = 0; | ||
353 | list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { | ||
354 | if (evt->type == UWB_EVT_TYPE_NOTIF) | ||
355 | kfree(evt->notif.rceb); | ||
356 | kfree(evt); | ||
357 | } | ||
358 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | ||
359 | uwb_beca_release(); | ||
360 | } | 332 | } |
361 | 333 | ||
362 | /* | 334 | /* |
@@ -373,18 +345,20 @@ void uwbd_stop(void) | |||
373 | */ | 345 | */ |
374 | void uwbd_event_queue(struct uwb_event *evt) | 346 | void uwbd_event_queue(struct uwb_event *evt) |
375 | { | 347 | { |
348 | struct uwb_rc *rc = evt->rc; | ||
376 | unsigned long flags; | 349 | unsigned long flags; |
377 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | 350 | |
378 | if (uwbd_pid != 0) { | 351 | spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); |
379 | list_add(&evt->list_node, &uwbd_event_list); | 352 | if (rc->uwbd.pid != 0) { |
380 | wake_up_all(&uwbd_wq); | 353 | list_add(&evt->list_node, &rc->uwbd.event_list); |
354 | wake_up_all(&rc->uwbd.wq); | ||
381 | } else { | 355 | } else { |
382 | __uwb_rc_put(evt->rc); | 356 | __uwb_rc_put(evt->rc); |
383 | if (evt->type == UWB_EVT_TYPE_NOTIF) | 357 | if (evt->type == UWB_EVT_TYPE_NOTIF) |
384 | kfree(evt->notif.rceb); | 358 | kfree(evt->notif.rceb); |
385 | kfree(evt); | 359 | kfree(evt); |
386 | } | 360 | } |
387 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | 361 | spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); |
388 | return; | 362 | return; |
389 | } | 363 | } |
390 | 364 | ||
@@ -392,10 +366,8 @@ void uwbd_flush(struct uwb_rc *rc) | |||
392 | { | 366 | { |
393 | struct uwb_event *evt, *nxt; | 367 | struct uwb_event *evt, *nxt; |
394 | 368 | ||
395 | mutex_lock(&uwbd_event_mutex); | 369 | spin_lock_irq(&rc->uwbd.event_list_lock); |
396 | 370 | list_for_each_entry_safe(evt, nxt, &rc->uwbd.event_list, list_node) { | |
397 | spin_lock_irq(&uwbd_event_list_lock); | ||
398 | list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { | ||
399 | if (evt->rc == rc) { | 371 | if (evt->rc == rc) { |
400 | __uwb_rc_put(rc); | 372 | __uwb_rc_put(rc); |
401 | list_del(&evt->list_node); | 373 | list_del(&evt->list_node); |
@@ -404,7 +376,5 @@ void uwbd_flush(struct uwb_rc *rc) | |||
404 | kfree(evt); | 376 | kfree(evt); |
405 | } | 377 | } |
406 | } | 378 | } |
407 | spin_unlock_irq(&uwbd_event_list_lock); | 379 | spin_unlock_irq(&rc->uwbd.event_list_lock); |
408 | |||
409 | mutex_unlock(&uwbd_event_mutex); | ||
410 | } | 380 | } |
diff --git a/drivers/uwb/whc-rc.c b/drivers/uwb/whc-rc.c index 1711deadb114..5f00386e26c7 100644 --- a/drivers/uwb/whc-rc.c +++ b/drivers/uwb/whc-rc.c | |||
@@ -39,7 +39,6 @@ | |||
39 | * them to the hw and transfer the replies/notifications back to the | 39 | * them to the hw and transfer the replies/notifications back to the |
40 | * UWB stack through the UWB daemon (UWBD). | 40 | * UWB stack through the UWB daemon (UWBD). |
41 | */ | 41 | */ |
42 | #include <linux/version.h> | ||
43 | #include <linux/init.h> | 42 | #include <linux/init.h> |
44 | #include <linux/module.h> | 43 | #include <linux/module.h> |
45 | #include <linux/pci.h> | 44 | #include <linux/pci.h> |
@@ -333,47 +332,23 @@ void whcrc_release_rc_umc(struct whcrc *whcrc) | |||
333 | static int whcrc_start_rc(struct uwb_rc *rc) | 332 | static int whcrc_start_rc(struct uwb_rc *rc) |
334 | { | 333 | { |
335 | struct whcrc *whcrc = rc->priv; | 334 | struct whcrc *whcrc = rc->priv; |
336 | int result = 0; | ||
337 | struct device *dev = &whcrc->umc_dev->dev; | 335 | struct device *dev = &whcrc->umc_dev->dev; |
338 | unsigned long start, duration; | ||
339 | 336 | ||
340 | /* Reset the thing */ | 337 | /* Reset the thing */ |
341 | le_writel(URCCMD_RESET, whcrc->rc_base + URCCMD); | 338 | le_writel(URCCMD_RESET, whcrc->rc_base + URCCMD); |
342 | if (d_test(3)) | ||
343 | start = jiffies; | ||
344 | if (whci_wait_for(dev, whcrc->rc_base + URCCMD, URCCMD_RESET, 0, | 339 | if (whci_wait_for(dev, whcrc->rc_base + URCCMD, URCCMD_RESET, 0, |
345 | 5000, "device to reset at init") < 0) { | 340 | 5000, "hardware reset") < 0) |
346 | result = -EBUSY; | 341 | return -EBUSY; |
347 | goto error; | ||
348 | } else if (d_test(3)) { | ||
349 | duration = jiffies - start; | ||
350 | if (duration > msecs_to_jiffies(40)) | ||
351 | dev_err(dev, "Device took %ums to " | ||
352 | "reset. MAX expected: 40ms\n", | ||
353 | jiffies_to_msecs(duration)); | ||
354 | } | ||
355 | 342 | ||
356 | /* Set the event buffer, start the controller (enable IRQs later) */ | 343 | /* Set the event buffer, start the controller (enable IRQs later) */ |
357 | le_writel(0, whcrc->rc_base + URCINTR); | 344 | le_writel(0, whcrc->rc_base + URCINTR); |
358 | le_writel(URCCMD_RS, whcrc->rc_base + URCCMD); | 345 | le_writel(URCCMD_RS, whcrc->rc_base + URCCMD); |
359 | result = -ETIMEDOUT; | ||
360 | if (d_test(3)) | ||
361 | start = jiffies; | ||
362 | if (whci_wait_for(dev, whcrc->rc_base + URCSTS, URCSTS_HALTED, 0, | 346 | if (whci_wait_for(dev, whcrc->rc_base + URCSTS, URCSTS_HALTED, 0, |
363 | 5000, "device to start") < 0) | 347 | 5000, "radio controller start") < 0) |
364 | goto error; | 348 | return -ETIMEDOUT; |
365 | if (d_test(3)) { | ||
366 | duration = jiffies - start; | ||
367 | if (duration > msecs_to_jiffies(40)) | ||
368 | dev_err(dev, "Device took %ums to start. " | ||
369 | "MAX expected: 40ms\n", | ||
370 | jiffies_to_msecs(duration)); | ||
371 | } | ||
372 | whcrc_enable_events(whcrc); | 349 | whcrc_enable_events(whcrc); |
373 | result = 0; | ||
374 | le_writel(URCINTR_EN_ALL, whcrc->rc_base + URCINTR); | 350 | le_writel(URCINTR_EN_ALL, whcrc->rc_base + URCINTR); |
375 | error: | 351 | return 0; |
376 | return result; | ||
377 | } | 352 | } |
378 | 353 | ||
379 | 354 | ||
@@ -395,7 +370,7 @@ void whcrc_stop_rc(struct uwb_rc *rc) | |||
395 | 370 | ||
396 | le_writel(0, whcrc->rc_base + URCCMD); | 371 | le_writel(0, whcrc->rc_base + URCCMD); |
397 | whci_wait_for(&umc_dev->dev, whcrc->rc_base + URCSTS, | 372 | whci_wait_for(&umc_dev->dev, whcrc->rc_base + URCSTS, |
398 | URCSTS_HALTED, 0, 40, "URCSTS.HALTED"); | 373 | URCSTS_HALTED, URCSTS_HALTED, 100, "radio controller stop"); |
399 | } | 374 | } |
400 | 375 | ||
401 | static void whcrc_init(struct whcrc *whcrc) | 376 | static void whcrc_init(struct whcrc *whcrc) |
@@ -489,6 +464,24 @@ static void whcrc_remove(struct umc_dev *umc_dev) | |||
489 | d_printf(1, &umc_dev->dev, "freed whcrc %p\n", whcrc); | 464 | d_printf(1, &umc_dev->dev, "freed whcrc %p\n", whcrc); |
490 | } | 465 | } |
491 | 466 | ||
467 | static int whcrc_pre_reset(struct umc_dev *umc) | ||
468 | { | ||
469 | struct whcrc *whcrc = umc_get_drvdata(umc); | ||
470 | struct uwb_rc *uwb_rc = whcrc->uwb_rc; | ||
471 | |||
472 | uwb_rc_pre_reset(uwb_rc); | ||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static int whcrc_post_reset(struct umc_dev *umc) | ||
477 | { | ||
478 | struct whcrc *whcrc = umc_get_drvdata(umc); | ||
479 | struct uwb_rc *uwb_rc = whcrc->uwb_rc; | ||
480 | |||
481 | uwb_rc_post_reset(uwb_rc); | ||
482 | return 0; | ||
483 | } | ||
484 | |||
492 | /* PCI device ID's that we handle [so it gets loaded] */ | 485 | /* PCI device ID's that we handle [so it gets loaded] */ |
493 | static struct pci_device_id whcrc_id_table[] = { | 486 | static struct pci_device_id whcrc_id_table[] = { |
494 | { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) }, | 487 | { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) }, |
@@ -497,10 +490,12 @@ static struct pci_device_id whcrc_id_table[] = { | |||
497 | MODULE_DEVICE_TABLE(pci, whcrc_id_table); | 490 | MODULE_DEVICE_TABLE(pci, whcrc_id_table); |
498 | 491 | ||
499 | static struct umc_driver whcrc_driver = { | 492 | static struct umc_driver whcrc_driver = { |
500 | .name = "whc-rc", | 493 | .name = "whc-rc", |
501 | .cap_id = UMC_CAP_ID_WHCI_RC, | 494 | .cap_id = UMC_CAP_ID_WHCI_RC, |
502 | .probe = whcrc_probe, | 495 | .probe = whcrc_probe, |
503 | .remove = whcrc_remove, | 496 | .remove = whcrc_remove, |
497 | .pre_reset = whcrc_pre_reset, | ||
498 | .post_reset = whcrc_post_reset, | ||
504 | }; | 499 | }; |
505 | 500 | ||
506 | static int __init whcrc_driver_init(void) | 501 | static int __init whcrc_driver_init(void) |
diff --git a/drivers/uwb/whci.c b/drivers/uwb/whci.c index 3df2388f908f..1f8964ed9882 100644 --- a/drivers/uwb/whci.c +++ b/drivers/uwb/whci.c | |||
@@ -67,11 +67,11 @@ int whci_wait_for(struct device *dev, u32 __iomem *reg, u32 mask, u32 result, | |||
67 | val = le_readl(reg); | 67 | val = le_readl(reg); |
68 | if ((val & mask) == result) | 68 | if ((val & mask) == result) |
69 | break; | 69 | break; |
70 | msleep(10); | ||
71 | if (t >= max_ms) { | 70 | if (t >= max_ms) { |
72 | dev_err(dev, "timed out waiting for %s ", tag); | 71 | dev_err(dev, "%s timed out\n", tag); |
73 | return -ETIMEDOUT; | 72 | return -ETIMEDOUT; |
74 | } | 73 | } |
74 | msleep(10); | ||
75 | t += 10; | 75 | t += 10; |
76 | } | 76 | } |
77 | return 0; | 77 | return 0; |
@@ -111,7 +111,7 @@ static int whci_add_cap(struct whci_card *card, int n) | |||
111 | + UWBCAPDATA_TO_OFFSET(capdata); | 111 | + UWBCAPDATA_TO_OFFSET(capdata); |
112 | umc->resource.end = umc->resource.start | 112 | umc->resource.end = umc->resource.start |
113 | + (n == 0 ? 0x20 : UWBCAPDATA_TO_SIZE(capdata)) - 1; | 113 | + (n == 0 ? 0x20 : UWBCAPDATA_TO_SIZE(capdata)) - 1; |
114 | umc->resource.name = umc->dev.bus_id; | 114 | umc->resource.name = dev_name(&umc->dev); |
115 | umc->resource.flags = card->pci->resource[bar].flags; | 115 | umc->resource.flags = card->pci->resource[bar].flags; |
116 | umc->resource.parent = &card->pci->resource[bar]; | 116 | umc->resource.parent = &card->pci->resource[bar]; |
117 | umc->irq = card->pci->irq; | 117 | umc->irq = card->pci->irq; |
diff --git a/drivers/uwb/wlp/wlp-internal.h b/drivers/uwb/wlp/wlp-internal.h index 1c94fabfb1a7..3e8d5de7c5b9 100644 --- a/drivers/uwb/wlp/wlp-internal.h +++ b/drivers/uwb/wlp/wlp-internal.h | |||
@@ -42,10 +42,6 @@ enum wlp_wss_connect { | |||
42 | extern struct kobj_type wss_ktype; | 42 | extern struct kobj_type wss_ktype; |
43 | extern struct attribute_group wss_attr_group; | 43 | extern struct attribute_group wss_attr_group; |
44 | 44 | ||
45 | extern int uwb_rc_ie_add(struct uwb_rc *, const struct uwb_ie_hdr *, size_t); | ||
46 | extern int uwb_rc_ie_rm(struct uwb_rc *, enum uwb_ie); | ||
47 | |||
48 | |||
49 | /* This should be changed to a dynamic array where entries are sorted | 45 | /* This should be changed to a dynamic array where entries are sorted |
50 | * by eth_addr and search is done in a binary form | 46 | * by eth_addr and search is done in a binary form |
51 | * | 47 | * |
diff --git a/drivers/uwb/wlp/wlp-lc.c b/drivers/uwb/wlp/wlp-lc.c index 0799402e73fb..e531093c4162 100644 --- a/drivers/uwb/wlp/wlp-lc.c +++ b/drivers/uwb/wlp/wlp-lc.c | |||
@@ -526,7 +526,17 @@ void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev, | |||
526 | } | 526 | } |
527 | } | 527 | } |
528 | 528 | ||
529 | int wlp_setup(struct wlp *wlp, struct uwb_rc *rc) | 529 | static void wlp_channel_changed(struct uwb_pal *pal, int channel) |
530 | { | ||
531 | struct wlp *wlp = container_of(pal, struct wlp, pal); | ||
532 | |||
533 | if (channel < 0) | ||
534 | netif_carrier_off(wlp->ndev); | ||
535 | else | ||
536 | netif_carrier_on(wlp->ndev); | ||
537 | } | ||
538 | |||
539 | int wlp_setup(struct wlp *wlp, struct uwb_rc *rc, struct net_device *ndev) | ||
530 | { | 540 | { |
531 | struct device *dev = &rc->uwb_dev.dev; | 541 | struct device *dev = &rc->uwb_dev.dev; |
532 | int result; | 542 | int result; |
@@ -537,13 +547,16 @@ int wlp_setup(struct wlp *wlp, struct uwb_rc *rc) | |||
537 | BUG_ON(wlp->stop_queue == NULL); | 547 | BUG_ON(wlp->stop_queue == NULL); |
538 | BUG_ON(wlp->start_queue == NULL); | 548 | BUG_ON(wlp->start_queue == NULL); |
539 | wlp->rc = rc; | 549 | wlp->rc = rc; |
550 | wlp->ndev = ndev; | ||
540 | wlp_eda_init(&wlp->eda);/* Set up address cache */ | 551 | wlp_eda_init(&wlp->eda);/* Set up address cache */ |
541 | wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb; | 552 | wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb; |
542 | wlp->uwb_notifs_handler.data = wlp; | 553 | wlp->uwb_notifs_handler.data = wlp; |
543 | uwb_notifs_register(rc, &wlp->uwb_notifs_handler); | 554 | uwb_notifs_register(rc, &wlp->uwb_notifs_handler); |
544 | 555 | ||
545 | uwb_pal_init(&wlp->pal); | 556 | uwb_pal_init(&wlp->pal); |
546 | result = uwb_pal_register(rc, &wlp->pal); | 557 | wlp->pal.rc = rc; |
558 | wlp->pal.channel_changed = wlp_channel_changed; | ||
559 | result = uwb_pal_register(&wlp->pal); | ||
547 | if (result < 0) | 560 | if (result < 0) |
548 | uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); | 561 | uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); |
549 | 562 | ||
@@ -557,7 +570,7 @@ void wlp_remove(struct wlp *wlp) | |||
557 | struct device *dev = &wlp->rc->uwb_dev.dev; | 570 | struct device *dev = &wlp->rc->uwb_dev.dev; |
558 | d_fnstart(6, dev, "wlp %p\n", wlp); | 571 | d_fnstart(6, dev, "wlp %p\n", wlp); |
559 | wlp_neighbors_release(wlp); | 572 | wlp_neighbors_release(wlp); |
560 | uwb_pal_unregister(wlp->rc, &wlp->pal); | 573 | uwb_pal_unregister(&wlp->pal); |
561 | uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); | 574 | uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); |
562 | wlp_eda_release(&wlp->eda); | 575 | wlp_eda_release(&wlp->eda); |
563 | mutex_lock(&wlp->mutex); | 576 | mutex_lock(&wlp->mutex); |