diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-12-14 19:54:12 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-12-18 14:07:56 -0500 |
commit | bf4c63252490ba78fb833cc7acf1a5b1900c970f (patch) | |
tree | 628e5d6a2b0214a8d6d4c85ce61177a9fd59cbc5 /include | |
parent | 8192edef03f9b47f1cc1120724db525e63e218f3 (diff) |
Bluetooth: convert conn hash to RCU
Handling hci_conn_hash with RCU make us avoid some locking and disable
tasklets.
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'include')
-rw-r--r-- | include/net/bluetooth/hci_core.h | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 14b200b08d84..e83243318924 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -392,7 +392,7 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev) | |||
392 | static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) | 392 | static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) |
393 | { | 393 | { |
394 | struct hci_conn_hash *h = &hdev->conn_hash; | 394 | struct hci_conn_hash *h = &hdev->conn_hash; |
395 | list_add(&c->list, &h->list); | 395 | list_add_rcu(&c->list, &h->list); |
396 | switch (c->type) { | 396 | switch (c->type) { |
397 | case ACL_LINK: | 397 | case ACL_LINK: |
398 | h->acl_num++; | 398 | h->acl_num++; |
@@ -410,7 +410,10 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) | |||
410 | static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) | 410 | static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) |
411 | { | 411 | { |
412 | struct hci_conn_hash *h = &hdev->conn_hash; | 412 | struct hci_conn_hash *h = &hdev->conn_hash; |
413 | list_del(&c->list); | 413 | |
414 | list_del_rcu(&c->list); | ||
415 | synchronize_rcu(); | ||
416 | |||
414 | switch (c->type) { | 417 | switch (c->type) { |
415 | case ACL_LINK: | 418 | case ACL_LINK: |
416 | h->acl_num--; | 419 | h->acl_num--; |
@@ -445,14 +448,18 @@ static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, | |||
445 | __u16 handle) | 448 | __u16 handle) |
446 | { | 449 | { |
447 | struct hci_conn_hash *h = &hdev->conn_hash; | 450 | struct hci_conn_hash *h = &hdev->conn_hash; |
448 | struct list_head *p; | ||
449 | struct hci_conn *c; | 451 | struct hci_conn *c; |
450 | 452 | ||
451 | list_for_each(p, &h->list) { | 453 | rcu_read_lock(); |
452 | c = list_entry(p, struct hci_conn, list); | 454 | |
453 | if (c->handle == handle) | 455 | list_for_each_entry_rcu(c, &h->list, list) { |
456 | if (c->handle == handle) { | ||
457 | rcu_read_unlock(); | ||
454 | return c; | 458 | return c; |
459 | } | ||
455 | } | 460 | } |
461 | rcu_read_unlock(); | ||
462 | |||
456 | return NULL; | 463 | return NULL; |
457 | } | 464 | } |
458 | 465 | ||
@@ -460,14 +467,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev, | |||
460 | __u8 type, bdaddr_t *ba) | 467 | __u8 type, bdaddr_t *ba) |
461 | { | 468 | { |
462 | struct hci_conn_hash *h = &hdev->conn_hash; | 469 | struct hci_conn_hash *h = &hdev->conn_hash; |
463 | struct list_head *p; | ||
464 | struct hci_conn *c; | 470 | struct hci_conn *c; |
465 | 471 | ||
466 | list_for_each(p, &h->list) { | 472 | rcu_read_lock(); |
467 | c = list_entry(p, struct hci_conn, list); | 473 | |
468 | if (c->type == type && !bacmp(&c->dst, ba)) | 474 | list_for_each_entry_rcu(c, &h->list, list) { |
475 | if (c->type == type && !bacmp(&c->dst, ba)) { | ||
476 | rcu_read_unlock(); | ||
469 | return c; | 477 | return c; |
478 | } | ||
470 | } | 479 | } |
480 | |||
481 | rcu_read_unlock(); | ||
482 | |||
471 | return NULL; | 483 | return NULL; |
472 | } | 484 | } |
473 | 485 | ||
@@ -475,14 +487,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, | |||
475 | __u8 type, __u16 state) | 487 | __u8 type, __u16 state) |
476 | { | 488 | { |
477 | struct hci_conn_hash *h = &hdev->conn_hash; | 489 | struct hci_conn_hash *h = &hdev->conn_hash; |
478 | struct list_head *p; | ||
479 | struct hci_conn *c; | 490 | struct hci_conn *c; |
480 | 491 | ||
481 | list_for_each(p, &h->list) { | 492 | rcu_read_lock(); |
482 | c = list_entry(p, struct hci_conn, list); | 493 | |
483 | if (c->type == type && c->state == state) | 494 | list_for_each_entry_rcu(c, &h->list, list) { |
495 | if (c->type == type && c->state == state) { | ||
496 | rcu_read_unlock(); | ||
484 | return c; | 497 | return c; |
498 | } | ||
485 | } | 499 | } |
500 | |||
501 | rcu_read_unlock(); | ||
502 | |||
486 | return NULL; | 503 | return NULL; |
487 | } | 504 | } |
488 | 505 | ||