diff options
-rw-r--r-- | include/net/bluetooth/hci_core.h | 31 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 3 | ||||
-rw-r--r-- | net/bluetooth/hci_sysfs.c | 1 |
3 files changed, 32 insertions, 3 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 5590cc4412c6..d324b11a0c8f 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -600,6 +600,37 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role); | |||
600 | 600 | ||
601 | void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); | 601 | void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); |
602 | 602 | ||
603 | /* | ||
604 | * hci_conn_get() and hci_conn_put() are used to control the life-time of an | ||
605 | * "hci_conn" object. They do not guarantee that the hci_conn object is running, | ||
606 | * working or anything else. They just guarantee that the object is available | ||
607 | * and can be dereferenced. So you can use its locks, local variables and any | ||
608 | * other constant data. | ||
609 | * Before accessing runtime data, you _must_ lock the object and then check that | ||
610 | * it is still running. As soon as you release the locks, the connection might | ||
611 | * get dropped, though. | ||
612 | * | ||
613 | * On the other hand, hci_conn_hold() and hci_conn_drop() are used to control | ||
614 | * how long the underlying connection is held. So every channel that runs on the | ||
615 | * hci_conn object calls this to prevent the connection from disappearing. As | ||
616 | * long as you hold a device, you must also guarantee that you have a valid | ||
617 | * reference to the device via hci_conn_get() (or the initial reference from | ||
618 | * hci_conn_add()). | ||
619 | * The hold()/drop() ref-count is known to drop below 0 sometimes, which doesn't | ||
620 | * break because nobody cares for that. But this means, we cannot use | ||
621 | * _get()/_drop() in it, but require the caller to have a valid ref (FIXME). | ||
622 | */ | ||
623 | |||
624 | static inline void hci_conn_get(struct hci_conn *conn) | ||
625 | { | ||
626 | get_device(&conn->dev); | ||
627 | } | ||
628 | |||
629 | static inline void hci_conn_put(struct hci_conn *conn) | ||
630 | { | ||
631 | put_device(&conn->dev); | ||
632 | } | ||
633 | |||
603 | static inline void hci_conn_hold(struct hci_conn *conn) | 634 | static inline void hci_conn_hold(struct hci_conn *conn) |
604 | { | 635 | { |
605 | BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt)); | 636 | BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt)); |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 6b5b8e77cf0b..6c7f36379722 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -462,8 +462,7 @@ int hci_conn_del(struct hci_conn *conn) | |||
462 | 462 | ||
463 | hci_dev_put(hdev); | 463 | hci_dev_put(hdev); |
464 | 464 | ||
465 | if (conn->handle == 0) | 465 | hci_conn_put(conn); |
466 | kfree(conn); | ||
467 | 466 | ||
468 | return 0; | 467 | return 0; |
469 | } | 468 | } |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index ff38561385de..6fe15c822847 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -146,7 +146,6 @@ void hci_conn_del_sysfs(struct hci_conn *conn) | |||
146 | } | 146 | } |
147 | 147 | ||
148 | device_del(&conn->dev); | 148 | device_del(&conn->dev); |
149 | put_device(&conn->dev); | ||
150 | 149 | ||
151 | hci_dev_put(hdev); | 150 | hci_dev_put(hdev); |
152 | } | 151 | } |