diff options
| -rw-r--r-- | drivers/uwb/beacon.c | 61 | ||||
| -rw-r--r-- | drivers/uwb/driver.c | 2 | ||||
| -rw-r--r-- | drivers/uwb/lc-rc.c | 21 | ||||
| -rw-r--r-- | drivers/uwb/uwb-internal.h | 20 | ||||
| -rw-r--r-- | drivers/uwb/uwbd.c | 98 | ||||
| -rw-r--r-- | include/linux/uwb.h | 20 |
6 files changed, 100 insertions, 122 deletions
diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c index ad823987cede..d9f2a8acc593 100644 --- a/drivers/uwb/beacon.c +++ b/drivers/uwb/beacon.c | |||
| @@ -168,12 +168,6 @@ out_up: | |||
| 168 | * FIXME: use something faster for search than a list | 168 | * FIXME: use something faster for search than a list |
| 169 | */ | 169 | */ |
| 170 | 170 | ||
| 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) | 171 | void uwb_bce_kfree(struct kref *_bce) |
| 178 | { | 172 | { |
| 179 | struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt); | 173 | struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt); |
| @@ -185,10 +179,11 @@ void uwb_bce_kfree(struct kref *_bce) | |||
| 185 | 179 | ||
| 186 | /* Find a beacon by dev addr in the cache */ | 180 | /* Find a beacon by dev addr in the cache */ |
| 187 | static | 181 | static |
| 188 | struct uwb_beca_e *__uwb_beca_find_bydev(const struct uwb_dev_addr *dev_addr) | 182 | struct uwb_beca_e *__uwb_beca_find_bydev(struct uwb_rc *rc, |
| 183 | const struct uwb_dev_addr *dev_addr) | ||
| 189 | { | 184 | { |
| 190 | struct uwb_beca_e *bce, *next; | 185 | struct uwb_beca_e *bce, *next; |
| 191 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 186 | 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", | 187 | d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n", |
| 193 | dev_addr->data[0], dev_addr->data[1], | 188 | dev_addr->data[0], dev_addr->data[1], |
| 194 | bce->dev_addr.data[0], bce->dev_addr.data[1]); | 189 | bce->dev_addr.data[0], bce->dev_addr.data[1]); |
| @@ -202,10 +197,11 @@ out: | |||
| 202 | 197 | ||
| 203 | /* Find a beacon by dev addr in the cache */ | 198 | /* Find a beacon by dev addr in the cache */ |
| 204 | static | 199 | static |
| 205 | struct uwb_beca_e *__uwb_beca_find_bymac(const struct uwb_mac_addr *mac_addr) | 200 | struct uwb_beca_e *__uwb_beca_find_bymac(struct uwb_rc *rc, |
| 201 | const struct uwb_mac_addr *mac_addr) | ||
| 206 | { | 202 | { |
| 207 | struct uwb_beca_e *bce, *next; | 203 | struct uwb_beca_e *bce, *next; |
| 208 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 204 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
| 209 | if (!memcmp(bce->mac_addr, mac_addr->data, | 205 | if (!memcmp(bce->mac_addr, mac_addr->data, |
| 210 | sizeof(struct uwb_mac_addr))) | 206 | sizeof(struct uwb_mac_addr))) |
| 211 | goto out; | 207 | goto out; |
| @@ -229,11 +225,11 @@ struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, | |||
| 229 | struct uwb_dev *found = NULL; | 225 | struct uwb_dev *found = NULL; |
| 230 | struct uwb_beca_e *bce; | 226 | struct uwb_beca_e *bce; |
| 231 | 227 | ||
| 232 | mutex_lock(&uwb_beca.mutex); | 228 | mutex_lock(&rc->uwb_beca.mutex); |
| 233 | bce = __uwb_beca_find_bydev(devaddr); | 229 | bce = __uwb_beca_find_bydev(rc, devaddr); |
| 234 | if (bce) | 230 | if (bce) |
| 235 | found = uwb_dev_try_get(rc, bce->uwb_dev); | 231 | found = uwb_dev_try_get(rc, bce->uwb_dev); |
| 236 | mutex_unlock(&uwb_beca.mutex); | 232 | mutex_unlock(&rc->uwb_beca.mutex); |
| 237 | 233 | ||
| 238 | return found; | 234 | return found; |
| 239 | } | 235 | } |
| @@ -249,11 +245,11 @@ struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, | |||
| 249 | struct uwb_dev *found = NULL; | 245 | struct uwb_dev *found = NULL; |
| 250 | struct uwb_beca_e *bce; | 246 | struct uwb_beca_e *bce; |
| 251 | 247 | ||
| 252 | mutex_lock(&uwb_beca.mutex); | 248 | mutex_lock(&rc->uwb_beca.mutex); |
| 253 | bce = __uwb_beca_find_bymac(macaddr); | 249 | bce = __uwb_beca_find_bymac(rc, macaddr); |
| 254 | if (bce) | 250 | if (bce) |
| 255 | found = uwb_dev_try_get(rc, bce->uwb_dev); | 251 | found = uwb_dev_try_get(rc, bce->uwb_dev); |
| 256 | mutex_unlock(&uwb_beca.mutex); | 252 | mutex_unlock(&rc->uwb_beca.mutex); |
| 257 | 253 | ||
| 258 | return found; | 254 | return found; |
| 259 | } | 255 | } |
| @@ -274,7 +270,9 @@ static void uwb_beca_e_init(struct uwb_beca_e *bce) | |||
| 274 | * @bf: Beacon frame (part of b, really) | 270 | * @bf: Beacon frame (part of b, really) |
| 275 | * @ts_jiffies: Timestamp (in jiffies) when the beacon was received | 271 | * @ts_jiffies: Timestamp (in jiffies) when the beacon was received |
| 276 | */ | 272 | */ |
| 277 | struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | 273 | static |
| 274 | struct uwb_beca_e *__uwb_beca_add(struct uwb_rc *rc, | ||
| 275 | struct uwb_rc_evt_beacon *be, | ||
| 278 | struct uwb_beacon_frame *bf, | 276 | struct uwb_beacon_frame *bf, |
| 279 | unsigned long ts_jiffies) | 277 | unsigned long ts_jiffies) |
| 280 | { | 278 | { |
| @@ -286,7 +284,7 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | |||
| 286 | uwb_beca_e_init(bce); | 284 | uwb_beca_e_init(bce); |
| 287 | bce->ts_jiffies = ts_jiffies; | 285 | bce->ts_jiffies = ts_jiffies; |
| 288 | bce->uwb_dev = NULL; | 286 | bce->uwb_dev = NULL; |
| 289 | list_add(&bce->node, &uwb_beca.list); | 287 | list_add(&bce->node, &rc->uwb_beca.list); |
| 290 | return bce; | 288 | return bce; |
| 291 | } | 289 | } |
| 292 | 290 | ||
| @@ -295,13 +293,13 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | |||
| 295 | * | 293 | * |
| 296 | * Remove associated devicest too. | 294 | * Remove associated devicest too. |
| 297 | */ | 295 | */ |
| 298 | void uwb_beca_purge(void) | 296 | void uwb_beca_purge(struct uwb_rc *rc) |
| 299 | { | 297 | { |
| 300 | struct uwb_beca_e *bce, *next; | 298 | struct uwb_beca_e *bce, *next; |
| 301 | unsigned long expires; | 299 | unsigned long expires; |
| 302 | 300 | ||
| 303 | mutex_lock(&uwb_beca.mutex); | 301 | mutex_lock(&rc->uwb_beca.mutex); |
| 304 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 302 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
| 305 | expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms); | 303 | expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms); |
| 306 | if (time_after(jiffies, expires)) { | 304 | if (time_after(jiffies, expires)) { |
| 307 | uwbd_dev_offair(bce); | 305 | uwbd_dev_offair(bce); |
| @@ -309,19 +307,20 @@ void uwb_beca_purge(void) | |||
| 309 | uwb_bce_put(bce); | 307 | uwb_bce_put(bce); |
| 310 | } | 308 | } |
| 311 | } | 309 | } |
| 312 | mutex_unlock(&uwb_beca.mutex); | 310 | mutex_unlock(&rc->uwb_beca.mutex); |
| 313 | } | 311 | } |
| 314 | 312 | ||
| 315 | /* Clean up the whole beacon cache. Called on shutdown */ | 313 | /* Clean up the whole beacon cache. Called on shutdown */ |
| 316 | void uwb_beca_release(void) | 314 | void uwb_beca_release(struct uwb_rc *rc) |
| 317 | { | 315 | { |
| 318 | struct uwb_beca_e *bce, *next; | 316 | struct uwb_beca_e *bce, *next; |
| 319 | mutex_lock(&uwb_beca.mutex); | 317 | |
| 320 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 318 | mutex_lock(&rc->uwb_beca.mutex); |
| 319 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { | ||
| 321 | list_del(&bce->node); | 320 | list_del(&bce->node); |
| 322 | uwb_bce_put(bce); | 321 | uwb_bce_put(bce); |
| 323 | } | 322 | } |
| 324 | mutex_unlock(&uwb_beca.mutex); | 323 | mutex_unlock(&rc->uwb_beca.mutex); |
| 325 | } | 324 | } |
| 326 | 325 | ||
| 327 | static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be, | 326 | static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be, |
| @@ -437,18 +436,18 @@ int uwbd_evt_handle_rc_beacon(struct uwb_event *evt) | |||
| 437 | if (uwb_mac_addr_bcast(&bf->Device_Identifier)) | 436 | if (uwb_mac_addr_bcast(&bf->Device_Identifier)) |
| 438 | return 0; | 437 | return 0; |
| 439 | 438 | ||
| 440 | mutex_lock(&uwb_beca.mutex); | 439 | mutex_lock(&rc->uwb_beca.mutex); |
| 441 | bce = __uwb_beca_find_bymac(&bf->Device_Identifier); | 440 | bce = __uwb_beca_find_bymac(rc, &bf->Device_Identifier); |
| 442 | if (bce == NULL) { | 441 | if (bce == NULL) { |
| 443 | /* Not in there, a new device is pinging */ | 442 | /* Not in there, a new device is pinging */ |
| 444 | uwb_beacon_print(evt->rc, be, bf); | 443 | uwb_beacon_print(evt->rc, be, bf); |
| 445 | bce = __uwb_beca_add(be, bf, evt->ts_jiffies); | 444 | bce = __uwb_beca_add(rc, be, bf, evt->ts_jiffies); |
| 446 | if (bce == NULL) { | 445 | if (bce == NULL) { |
| 447 | mutex_unlock(&uwb_beca.mutex); | 446 | mutex_unlock(&rc->uwb_beca.mutex); |
| 448 | return -ENOMEM; | 447 | return -ENOMEM; |
| 449 | } | 448 | } |
| 450 | } | 449 | } |
| 451 | mutex_unlock(&uwb_beca.mutex); | 450 | mutex_unlock(&rc->uwb_beca.mutex); |
| 452 | 451 | ||
| 453 | mutex_lock(&bce->mutex); | 452 | mutex_lock(&bce->mutex); |
| 454 | /* purge old beacon data */ | 453 | /* purge old beacon data */ |
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/lc-rc.c b/drivers/uwb/lc-rc.c index 1129e8767b58..38e3d57ec8f7 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) |
| @@ -83,7 +81,6 @@ static void uwb_rc_sys_release(struct device *dev) | |||
| 83 | 81 | ||
| 84 | uwb_rc_neh_destroy(rc); | 82 | uwb_rc_neh_destroy(rc); |
| 85 | uwb_rc_ie_release(rc); | 83 | uwb_rc_ie_release(rc); |
| 86 | d_printf(1, dev, "freed uwb_rc %p\n", rc); | ||
| 87 | kfree(rc); | 84 | kfree(rc); |
| 88 | } | 85 | } |
| 89 | 86 | ||
| @@ -100,6 +97,8 @@ void uwb_rc_init(struct uwb_rc *rc) | |||
| 100 | rc->scan_type = UWB_SCAN_DISABLED; | 97 | rc->scan_type = UWB_SCAN_DISABLED; |
| 101 | INIT_LIST_HEAD(&rc->notifs_chain.list); | 98 | INIT_LIST_HEAD(&rc->notifs_chain.list); |
| 102 | mutex_init(&rc->notifs_chain.mutex); | 99 | mutex_init(&rc->notifs_chain.mutex); |
| 100 | INIT_LIST_HEAD(&rc->uwb_beca.list); | ||
| 101 | mutex_init(&rc->uwb_beca.mutex); | ||
| 103 | uwb_drp_avail_init(rc); | 102 | uwb_drp_avail_init(rc); |
| 104 | uwb_rc_ie_init(rc); | 103 | uwb_rc_ie_init(rc); |
| 105 | uwb_rsv_init(rc); | 104 | uwb_rsv_init(rc); |
| @@ -250,6 +249,12 @@ int uwb_rc_add(struct uwb_rc *rc, struct device *parent_dev, void *priv) | |||
| 250 | 249 | ||
| 251 | rc->priv = priv; | 250 | rc->priv = priv; |
| 252 | 251 | ||
| 252 | init_waitqueue_head(&rc->uwbd.wq); | ||
| 253 | INIT_LIST_HEAD(&rc->uwbd.event_list); | ||
| 254 | spin_lock_init(&rc->uwbd.event_list_lock); | ||
| 255 | |||
| 256 | uwbd_start(rc); | ||
| 257 | |||
| 253 | result = rc->start(rc); | 258 | result = rc->start(rc); |
| 254 | if (result < 0) | 259 | if (result < 0) |
| 255 | goto error_rc_start; | 260 | goto error_rc_start; |
| @@ -284,7 +289,7 @@ error_sys_add: | |||
| 284 | error_dev_add: | 289 | error_dev_add: |
| 285 | error_rc_setup: | 290 | error_rc_setup: |
| 286 | rc->stop(rc); | 291 | rc->stop(rc); |
| 287 | uwbd_flush(rc); | 292 | uwbd_stop(rc); |
| 288 | error_rc_start: | 293 | error_rc_start: |
| 289 | return result; | 294 | return result; |
| 290 | } | 295 | } |
| @@ -315,16 +320,18 @@ void uwb_rc_rm(struct uwb_rc *rc) | |||
| 315 | uwb_rc_reset(rc); | 320 | uwb_rc_reset(rc); |
| 316 | 321 | ||
| 317 | rc->stop(rc); | 322 | rc->stop(rc); |
| 318 | uwbd_flush(rc); | 323 | |
| 324 | uwbd_stop(rc); | ||
| 319 | 325 | ||
| 320 | uwb_dev_lock(&rc->uwb_dev); | 326 | uwb_dev_lock(&rc->uwb_dev); |
| 321 | rc->priv = NULL; | 327 | rc->priv = NULL; |
| 322 | rc->cmd = NULL; | 328 | rc->cmd = NULL; |
| 323 | uwb_dev_unlock(&rc->uwb_dev); | 329 | uwb_dev_unlock(&rc->uwb_dev); |
| 324 | mutex_lock(&uwb_beca.mutex); | 330 | mutex_lock(&rc->uwb_beca.mutex); |
| 325 | uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); | 331 | uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); |
| 326 | __uwb_rc_sys_rm(rc); | 332 | __uwb_rc_sys_rm(rc); |
| 327 | mutex_unlock(&uwb_beca.mutex); | 333 | mutex_unlock(&rc->uwb_beca.mutex); |
| 334 | uwb_beca_release(rc); | ||
| 328 | uwb_dev_rm(&rc->uwb_dev); | 335 | uwb_dev_rm(&rc->uwb_dev); |
| 329 | } | 336 | } |
| 330 | EXPORT_SYMBOL_GPL(uwb_rc_rm); | 337 | EXPORT_SYMBOL_GPL(uwb_rc_rm); |
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h index 031e8a885681..4c2449679978 100644 --- a/drivers/uwb/uwb-internal.h +++ b/drivers/uwb/uwb-internal.h | |||
| @@ -160,8 +160,8 @@ 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); |
| @@ -194,15 +194,6 @@ int uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt); | |||
| 194 | 194 | ||
| 195 | extern unsigned long beacon_timeout_ms; | 195 | extern unsigned long beacon_timeout_ms; |
| 196 | 196 | ||
| 197 | /** Beacon cache list */ | ||
| 198 | struct uwb_beca { | ||
| 199 | struct list_head list; | ||
| 200 | size_t entries; | ||
| 201 | struct mutex mutex; | ||
| 202 | }; | ||
| 203 | |||
| 204 | extern struct uwb_beca uwb_beca; | ||
| 205 | |||
| 206 | /** | 197 | /** |
| 207 | * Beacon cache entry | 198 | * Beacon cache entry |
| 208 | * | 199 | * |
| @@ -229,9 +220,6 @@ struct uwb_beca_e { | |||
| 229 | struct uwb_beacon_frame; | 220 | struct uwb_beacon_frame; |
| 230 | 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 *, |
| 231 | char *, size_t); | 222 | char *, size_t); |
| 232 | extern struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *, | ||
| 233 | struct uwb_beacon_frame *, | ||
| 234 | unsigned long); | ||
| 235 | 223 | ||
| 236 | extern void uwb_bce_kfree(struct kref *_bce); | 224 | extern void uwb_bce_kfree(struct kref *_bce); |
| 237 | static inline void uwb_bce_get(struct uwb_beca_e *bce) | 225 | static inline void uwb_bce_get(struct uwb_beca_e *bce) |
| @@ -242,8 +230,8 @@ static inline void uwb_bce_put(struct uwb_beca_e *bce) | |||
| 242 | { | 230 | { |
| 243 | kref_put(&bce->refcnt, uwb_bce_kfree); | 231 | kref_put(&bce->refcnt, uwb_bce_kfree); |
| 244 | } | 232 | } |
| 245 | extern void uwb_beca_purge(void); | 233 | extern void uwb_beca_purge(struct uwb_rc *rc); |
| 246 | extern void uwb_beca_release(void); | 234 | extern void uwb_beca_release(struct uwb_rc *rc); |
| 247 | 235 | ||
| 248 | 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, |
| 249 | const struct uwb_dev_addr *devaddr); | 237 | const struct uwb_dev_addr *devaddr); |
diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c index f75113571f4a..ec42ce92dbce 100644 --- a/drivers/uwb/uwbd.c +++ b/drivers/uwb/uwbd.c | |||
| @@ -170,8 +170,6 @@ static const struct uwbd_event uwbd_message_handlers[] = { | |||
| 170 | }, | 170 | }, |
| 171 | }; | 171 | }; |
| 172 | 172 | ||
| 173 | static DEFINE_MUTEX(uwbd_event_mutex); | ||
| 174 | |||
| 175 | /** | 173 | /** |
| 176 | * Handle an URC event passed to the UWB Daemon | 174 | * Handle an URC event passed to the UWB Daemon |
| 177 | * | 175 | * |
| @@ -235,19 +233,10 @@ static void uwbd_event_handle_message(struct uwb_event *evt) | |||
| 235 | return; | 233 | return; |
| 236 | } | 234 | } |
| 237 | 235 | ||
| 238 | /* If this is a reset event we need to drop the | ||
| 239 | * uwbd_event_mutex or it deadlocks when the reset handler | ||
| 240 | * attempts to flush the uwbd events. */ | ||
| 241 | if (evt->message == UWB_EVT_MSG_RESET) | ||
| 242 | mutex_unlock(&uwbd_event_mutex); | ||
| 243 | |||
| 244 | result = uwbd_message_handlers[evt->message].handler(evt); | 236 | result = uwbd_message_handlers[evt->message].handler(evt); |
| 245 | if (result < 0) | 237 | if (result < 0) |
| 246 | 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", |
| 247 | uwbd_message_handlers[evt->message].name, result); | 239 | uwbd_message_handlers[evt->message].name, result); |
| 248 | |||
| 249 | if (evt->message == UWB_EVT_MSG_RESET) | ||
| 250 | mutex_lock(&uwbd_event_mutex); | ||
| 251 | } | 240 | } |
| 252 | 241 | ||
| 253 | static void uwbd_event_handle(struct uwb_event *evt) | 242 | static void uwbd_event_handle(struct uwb_event *evt) |
| @@ -275,20 +264,6 @@ static void uwbd_event_handle(struct uwb_event *evt) | |||
| 275 | 264 | ||
| 276 | __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() */ |
| 277 | } | 266 | } |
| 278 | /* The UWB Daemon */ | ||
| 279 | |||
| 280 | |||
| 281 | /** Daemon's PID: used to decide if we can queue or not */ | ||
| 282 | static int uwbd_pid; | ||
| 283 | /** Daemon's task struct for managing the kthread */ | ||
| 284 | static struct task_struct *uwbd_task; | ||
| 285 | /** Daemon's waitqueue for waiting for new events */ | ||
| 286 | static DECLARE_WAIT_QUEUE_HEAD(uwbd_wq); | ||
| 287 | /** Daemon's list of events; we queue/dequeue here */ | ||
| 288 | static struct list_head uwbd_event_list = LIST_HEAD_INIT(uwbd_event_list); | ||
| 289 | /** Daemon's list lock to protect concurent access */ | ||
| 290 | static DEFINE_SPINLOCK(uwbd_event_list_lock); | ||
| 291 | |||
| 292 | 267 | ||
| 293 | /** | 268 | /** |
| 294 | * UWB Daemon | 269 | * UWB Daemon |
| @@ -302,65 +277,58 @@ static DEFINE_SPINLOCK(uwbd_event_list_lock); | |||
| 302 | * 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 |
| 303 | * only if there are devices. | 278 | * only if there are devices. |
| 304 | */ | 279 | */ |
| 305 | static int uwbd(void *unused) | 280 | static int uwbd(void *param) |
| 306 | { | 281 | { |
| 282 | struct uwb_rc *rc = param; | ||
| 307 | unsigned long flags; | 283 | unsigned long flags; |
| 308 | struct list_head list = LIST_HEAD_INIT(list); | 284 | struct uwb_event *evt; |
| 309 | struct uwb_event *evt, *nxt; | ||
| 310 | int should_stop = 0; | 285 | int should_stop = 0; |
| 286 | |||
| 311 | while (1) { | 287 | while (1) { |
| 312 | wait_event_interruptible_timeout( | 288 | wait_event_interruptible_timeout( |
| 313 | uwbd_wq, | 289 | rc->uwbd.wq, |
| 314 | !list_empty(&uwbd_event_list) | 290 | !list_empty(&rc->uwbd.event_list) |
| 315 | || (should_stop = kthread_should_stop()), | 291 | || (should_stop = kthread_should_stop()), |
| 316 | HZ); | 292 | HZ); |
| 317 | if (should_stop) | 293 | if (should_stop) |
| 318 | break; | 294 | break; |
| 319 | try_to_freeze(); | 295 | try_to_freeze(); |
| 320 | 296 | ||
| 321 | mutex_lock(&uwbd_event_mutex); | 297 | spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); |
| 322 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | 298 | if (!list_empty(&rc->uwbd.event_list)) { |
| 323 | list_splice_init(&uwbd_event_list, &list); | 299 | evt = list_first_entry(&rc->uwbd.event_list, struct uwb_event, list_node); |
| 324 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | ||
| 325 | list_for_each_entry_safe(evt, nxt, &list, list_node) { | ||
| 326 | 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) { | ||
| 327 | uwbd_event_handle(evt); | 306 | uwbd_event_handle(evt); |
| 328 | kfree(evt); | 307 | kfree(evt); |
| 329 | } | 308 | } |
| 330 | mutex_unlock(&uwbd_event_mutex); | ||
| 331 | 309 | ||
| 332 | uwb_beca_purge(); /* Purge devices that left */ | 310 | uwb_beca_purge(rc); /* Purge devices that left */ |
| 333 | } | 311 | } |
| 334 | return 0; | 312 | return 0; |
| 335 | } | 313 | } |
| 336 | 314 | ||
| 337 | 315 | ||
| 338 | /** Start the UWB daemon */ | 316 | /** Start the UWB daemon */ |
| 339 | void uwbd_start(void) | 317 | void uwbd_start(struct uwb_rc *rc) |
| 340 | { | 318 | { |
| 341 | uwbd_task = kthread_run(uwbd, NULL, "uwbd"); | 319 | rc->uwbd.task = kthread_run(uwbd, rc, "uwbd"); |
| 342 | if (uwbd_task == NULL) | 320 | if (rc->uwbd.task == NULL) |
| 343 | printk(KERN_ERR "UWB: Cannot start management daemon; " | 321 | printk(KERN_ERR "UWB: Cannot start management daemon; " |
| 344 | "UWB won't work\n"); | 322 | "UWB won't work\n"); |
| 345 | else | 323 | else |
| 346 | uwbd_pid = uwbd_task->pid; | 324 | rc->uwbd.pid = rc->uwbd.task->pid; |
| 347 | } | 325 | } |
| 348 | 326 | ||
| 349 | /* Stop the UWB daemon and free any unprocessed events */ | 327 | /* Stop the UWB daemon and free any unprocessed events */ |
| 350 | void uwbd_stop(void) | 328 | void uwbd_stop(struct uwb_rc *rc) |
| 351 | { | 329 | { |
| 352 | unsigned long flags; | 330 | kthread_stop(rc->uwbd.task); |
| 353 | struct uwb_event *evt, *nxt; | 331 | uwbd_flush(rc); |
| 354 | kthread_stop(uwbd_task); | ||
| 355 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | ||
| 356 | uwbd_pid = 0; | ||
| 357 | list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { | ||
| 358 | if (evt->type == UWB_EVT_TYPE_NOTIF) | ||
| 359 | kfree(evt->notif.rceb); | ||
| 360 | kfree(evt); | ||
| 361 | } | ||
| 362 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | ||
| 363 | uwb_beca_release(); | ||
| 364 | } | 332 | } |
| 365 | 333 | ||
| 366 | /* | 334 | /* |
| @@ -377,18 +345,20 @@ void uwbd_stop(void) | |||
| 377 | */ | 345 | */ |
| 378 | void uwbd_event_queue(struct uwb_event *evt) | 346 | void uwbd_event_queue(struct uwb_event *evt) |
| 379 | { | 347 | { |
| 348 | struct uwb_rc *rc = evt->rc; | ||
| 380 | unsigned long flags; | 349 | unsigned long flags; |
| 381 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | 350 | |
| 382 | if (uwbd_pid != 0) { | 351 | spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); |
| 383 | list_add(&evt->list_node, &uwbd_event_list); | 352 | if (rc->uwbd.pid != 0) { |
| 384 | wake_up_all(&uwbd_wq); | 353 | list_add(&evt->list_node, &rc->uwbd.event_list); |
| 354 | wake_up_all(&rc->uwbd.wq); | ||
| 385 | } else { | 355 | } else { |
| 386 | __uwb_rc_put(evt->rc); | 356 | __uwb_rc_put(evt->rc); |
| 387 | if (evt->type == UWB_EVT_TYPE_NOTIF) | 357 | if (evt->type == UWB_EVT_TYPE_NOTIF) |
| 388 | kfree(evt->notif.rceb); | 358 | kfree(evt->notif.rceb); |
| 389 | kfree(evt); | 359 | kfree(evt); |
| 390 | } | 360 | } |
| 391 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | 361 | spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); |
| 392 | return; | 362 | return; |
| 393 | } | 363 | } |
| 394 | 364 | ||
| @@ -396,10 +366,8 @@ void uwbd_flush(struct uwb_rc *rc) | |||
| 396 | { | 366 | { |
| 397 | struct uwb_event *evt, *nxt; | 367 | struct uwb_event *evt, *nxt; |
| 398 | 368 | ||
| 399 | mutex_lock(&uwbd_event_mutex); | 369 | spin_lock_irq(&rc->uwbd.event_list_lock); |
| 400 | 370 | list_for_each_entry_safe(evt, nxt, &rc->uwbd.event_list, list_node) { | |
| 401 | spin_lock_irq(&uwbd_event_list_lock); | ||
| 402 | list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { | ||
| 403 | if (evt->rc == rc) { | 371 | if (evt->rc == rc) { |
| 404 | __uwb_rc_put(rc); | 372 | __uwb_rc_put(rc); |
| 405 | list_del(&evt->list_node); | 373 | list_del(&evt->list_node); |
| @@ -408,7 +376,5 @@ void uwbd_flush(struct uwb_rc *rc) | |||
| 408 | kfree(evt); | 376 | kfree(evt); |
| 409 | } | 377 | } |
| 410 | } | 378 | } |
| 411 | spin_unlock_irq(&uwbd_event_list_lock); | 379 | spin_unlock_irq(&rc->uwbd.event_list_lock); |
| 412 | |||
| 413 | mutex_unlock(&uwbd_event_mutex); | ||
| 414 | } | 380 | } |
diff --git a/include/linux/uwb.h b/include/linux/uwb.h index 6d93f54b8879..881f0c5b6d28 100644 --- a/include/linux/uwb.h +++ b/include/linux/uwb.h | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/device.h> | 30 | #include <linux/device.h> |
| 31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
| 32 | #include <linux/timer.h> | 32 | #include <linux/timer.h> |
| 33 | #include <linux/wait.h> | ||
| 33 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
| 34 | #include <linux/uwb/spec.h> | 35 | #include <linux/uwb/spec.h> |
| 35 | 36 | ||
| @@ -86,6 +87,22 @@ struct uwb_notifs_chain { | |||
| 86 | struct mutex mutex; | 87 | struct mutex mutex; |
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| 90 | /* Beacon cache list */ | ||
| 91 | struct uwb_beca { | ||
| 92 | struct list_head list; | ||
| 93 | size_t entries; | ||
| 94 | struct mutex mutex; | ||
| 95 | }; | ||
| 96 | |||
| 97 | /* Event handling thread. */ | ||
| 98 | struct uwbd { | ||
| 99 | int pid; | ||
| 100 | struct task_struct *task; | ||
| 101 | wait_queue_head_t wq; | ||
| 102 | struct list_head event_list; | ||
| 103 | spinlock_t event_list_lock; | ||
| 104 | }; | ||
| 105 | |||
| 89 | /** | 106 | /** |
| 90 | * struct uwb_mas_bm - a bitmap of all MAS in a superframe | 107 | * struct uwb_mas_bm - a bitmap of all MAS in a superframe |
| 91 | * @bm: a bitmap of length #UWB_NUM_MAS | 108 | * @bm: a bitmap of length #UWB_NUM_MAS |
| @@ -342,6 +359,9 @@ struct uwb_rc { | |||
| 342 | enum uwb_scan_type scan_type:3; | 359 | enum uwb_scan_type scan_type:3; |
| 343 | unsigned ready:1; | 360 | unsigned ready:1; |
| 344 | struct uwb_notifs_chain notifs_chain; | 361 | struct uwb_notifs_chain notifs_chain; |
| 362 | struct uwb_beca uwb_beca; | ||
| 363 | |||
| 364 | struct uwbd uwbd; | ||
| 345 | 365 | ||
| 346 | struct uwb_drp_avail drp_avail; | 366 | struct uwb_drp_avail drp_avail; |
| 347 | struct list_head reservations; | 367 | struct list_head reservations; |
