Bluetooth: AMP: Remote AMP ctrl definitions
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>
Thu, 27 Sep 2012 14:26:12 +0000 (17:26 +0300)
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>
Thu, 27 Sep 2012 20:12:46 +0000 (17:12 -0300)
Create remote AMP controllers structure. It is used to keep information
about discovered remote AMP controllers by A2MP protocol.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
include/net/bluetooth/a2mp.h
include/net/bluetooth/amp.h
net/bluetooth/a2mp.c
net/bluetooth/amp.c

index d5476719fa4c5bad9610776db3f87b7c74b32c39..99c7389b9189f5d424e7197384530449d61d5398 100644 (file)
@@ -33,6 +33,9 @@ struct amp_mgr {
        __u8                    handle;
        enum amp_mgr_state      state;
        unsigned long           flags;
+
+       struct list_head        amp_ctrls;
+       struct mutex            amp_ctrls_lock;
 };
 
 struct a2mp_cmd {
index 3414dfdc404c73cb3122657b537916c7a14877de..f57854f0786d6f1fc975779ba894f4723dad4344 100644 (file)
 #ifndef __AMP_H
 #define __AMP_H
 
+struct amp_ctrl {
+       struct list_head        list;
+       struct kref             kref;
+       __u8                    id;
+       __u16                   assoc_len_so_far;
+       __u16                   assoc_rem_len;
+       __u16                   assoc_len;
+       __u8                    *assoc;
+};
+
+int amp_ctrl_put(struct amp_ctrl *ctrl);
+struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr);
+struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
+void amp_ctrl_list_flush(struct amp_mgr *mgr);
+
 struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
                             u8 remote_id);
 
index f04c44146663c491b81444433652c5743d10cfce..35e188c7a4418d01fac6dbf5657e9c1bb639df8e 100644 (file)
@@ -594,6 +594,7 @@ static void amp_mgr_destroy(struct kref *kref)
        list_del(&mgr->list);
        mutex_unlock(&amp_mgr_list_lock);
 
+       amp_ctrl_list_flush(mgr);
        kfree(mgr);
 }
 
@@ -630,6 +631,10 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
 
        kref_init(&mgr->kref);
 
+       /* Remote AMP ctrl list initialization */
+       INIT_LIST_HEAD(&mgr->amp_ctrls);
+       mutex_init(&mgr->amp_ctrls_lock);
+
        mutex_lock(&amp_mgr_list_lock);
        list_add(&mgr->list, &amp_mgr_list);
        mutex_unlock(&amp_mgr_list_lock);
index 50a7b2fb8bf3ceeffb12e5380cbcde6877333bcd..8ef912c36224f35b567f3efab648a4f2c2762698 100644 (file)
 #include <net/bluetooth/a2mp.h>
 #include <net/bluetooth/amp.h>
 
+/* Remote AMP Controllers interface */
+static void amp_ctrl_get(struct amp_ctrl *ctrl)
+{
+       BT_DBG("ctrl %p orig refcnt %d", ctrl,
+              atomic_read(&ctrl->kref.refcount));
+
+       kref_get(&ctrl->kref);
+}
+
+static void amp_ctrl_destroy(struct kref *kref)
+{
+       struct amp_ctrl *ctrl = container_of(kref, struct amp_ctrl, kref);
+
+       BT_DBG("ctrl %p", ctrl);
+
+       kfree(ctrl->assoc);
+       kfree(ctrl);
+}
+
+int amp_ctrl_put(struct amp_ctrl *ctrl)
+{
+       BT_DBG("ctrl %p orig refcnt %d", ctrl,
+              atomic_read(&ctrl->kref.refcount));
+
+       return kref_put(&ctrl->kref, &amp_ctrl_destroy);
+}
+
+struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr)
+{
+       struct amp_ctrl *ctrl;
+
+       ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+       if (!ctrl)
+               return NULL;
+
+       mutex_lock(&mgr->amp_ctrls_lock);
+       list_add(&ctrl->list, &mgr->amp_ctrls);
+       mutex_unlock(&mgr->amp_ctrls_lock);
+
+       kref_init(&ctrl->kref);
+
+       BT_DBG("mgr %p ctrl %p", mgr, ctrl);
+
+       return ctrl;
+}
+
+void amp_ctrl_list_flush(struct amp_mgr *mgr)
+{
+       struct amp_ctrl *ctrl, *n;
+
+       BT_DBG("mgr %p", mgr);
+
+       mutex_lock(&mgr->amp_ctrls_lock);
+       list_for_each_entry_safe(ctrl, n, &mgr->amp_ctrls, list) {
+               list_del(&ctrl->list);
+               amp_ctrl_put(ctrl);
+       }
+       mutex_unlock(&mgr->amp_ctrls_lock);
+}
+
+struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id)
+{
+       struct amp_ctrl *ctrl;
+
+       BT_DBG("mgr %p id %d", mgr, id);
+
+       mutex_lock(&mgr->amp_ctrls_lock);
+       list_for_each_entry(ctrl, &mgr->amp_ctrls, list) {
+               if (ctrl->id == id) {
+                       amp_ctrl_get(ctrl);
+                       mutex_unlock(&mgr->amp_ctrls_lock);
+                       return ctrl;
+               }
+       }
+       mutex_unlock(&mgr->amp_ctrls_lock);
+
+       return NULL;
+}
+
 /* Physical Link interface */
 static u8 __next_handle(struct amp_mgr *mgr)
 {