aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h31
-rw-r--r--net/bluetooth/hci_conn.c3
-rw-r--r--net/bluetooth/hci_sysfs.c1
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
601void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); 601void 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
624static inline void hci_conn_get(struct hci_conn *conn)
625{
626 get_device(&conn->dev);
627}
628
629static inline void hci_conn_put(struct hci_conn *conn)
630{
631 put_device(&conn->dev);
632}
633
603static inline void hci_conn_hold(struct hci_conn *conn) 634static 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}