Bluetooth: Add timer for automatically disabling the service cache
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / include / net / bluetooth / hci_core.h
index e7b2e25397d7b93e42a1fa5278816ee19492fdcc..105eaa251034c263423e385a312ab2a5deaf34d3 100644 (file)
@@ -61,18 +61,11 @@ struct inquiry_cache {
 
 struct hci_conn_hash {
        struct list_head list;
-       spinlock_t       lock;
        unsigned int     acl_num;
        unsigned int     sco_num;
        unsigned int     le_num;
 };
 
-struct hci_chan_hash {
-       struct list_head list;
-       spinlock_t       lock;
-       unsigned int     num;
-};
-
 struct bdaddr_list {
        struct list_head list;
        bdaddr_t bdaddr;
@@ -124,7 +117,7 @@ struct adv_entry {
 #define NUM_REASSEMBLY 4
 struct hci_dev {
        struct list_head list;
-       spinlock_t      lock;
+       struct mutex    lock;
        atomic_t        refcnt;
 
        char            name[8];
@@ -170,6 +163,8 @@ struct hci_dev {
        __u32           amp_max_flush_to;
        __u32           amp_be_flush_to;
 
+       __u8            flow_ctl_mode;
+
        unsigned int    auto_accept_delay;
 
        unsigned long   quirks;
@@ -198,10 +193,13 @@ struct hci_dev {
        __u16                   discov_timeout;
        struct delayed_work     discov_off;
 
+       struct delayed_work     service_cache;
+
        struct timer_list       cmd_timer;
-       struct tasklet_struct   cmd_task;
-       struct tasklet_struct   rx_task;
-       struct tasklet_struct   tx_task;
+
+       struct work_struct      rx_work;
+       struct work_struct      cmd_work;
+       struct work_struct      tx_work;
 
        struct sk_buff_head     rx_q;
        struct sk_buff_head     raw_q;
@@ -230,7 +228,7 @@ struct hci_dev {
        struct list_head        remote_oob_data;
 
        struct list_head        adv_entries;
-       struct timer_list       adv_timer;
+       struct delayed_work     adv_work;
 
        struct hci_dev_stats    stat;
 
@@ -250,6 +248,8 @@ struct hci_dev {
 
        struct module           *owner;
 
+       unsigned long           dev_flags;
+
        int (*open)(struct hci_dev *hdev);
        int (*close)(struct hci_dev *hdev);
        int (*flush)(struct hci_dev *hdev);
@@ -297,15 +297,12 @@ struct hci_conn {
        unsigned int    sent;
 
        struct sk_buff_head data_q;
-       struct hci_chan_hash chan_hash;
+       struct list_head chan_list;
 
-       struct timer_list disc_timer;
+       struct delayed_work disc_work;
        struct timer_list idle_timer;
        struct timer_list auto_accept_timer;
 
-       struct work_struct work_add;
-       struct work_struct work_del;
-
        struct device   dev;
        atomic_t        devref;
 
@@ -386,15 +383,15 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
        INIT_LIST_HEAD(&h->list);
-       spin_lock_init(&h->lock);
        h->acl_num = 0;
        h->sco_num = 0;
+       h->le_num = 0;
 }
 
 static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       list_add(&c->list, &h->list);
+       list_add_rcu(&c->list, &h->list);
        switch (c->type) {
        case ACL_LINK:
                h->acl_num++;
@@ -412,7 +409,10 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
 static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       list_del(&c->list);
+
+       list_del_rcu(&c->list);
+       synchronize_rcu();
+
        switch (c->type) {
        case ACL_LINK:
                h->acl_num--;
@@ -447,14 +447,18 @@ static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
                                                                __u16 handle)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       struct list_head *p;
        struct hci_conn  *c;
 
-       list_for_each(p, &h->list) {
-               c = list_entry(p, struct hci_conn, list);
-               if (c->handle == handle)
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(c, &h->list, list) {
+               if (c->handle == handle) {
+                       rcu_read_unlock();
                        return c;
+               }
        }
+       rcu_read_unlock();
+
        return NULL;
 }
 
@@ -462,14 +466,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
                                                        __u8 type, bdaddr_t *ba)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       struct list_head *p;
        struct hci_conn  *c;
 
-       list_for_each(p, &h->list) {
-               c = list_entry(p, struct hci_conn, list);
-               if (c->type == type && !bacmp(&c->dst, ba))
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(c, &h->list, list) {
+               if (c->type == type && !bacmp(&c->dst, ba)) {
+                       rcu_read_unlock();
                        return c;
+               }
        }
+
+       rcu_read_unlock();
+
        return NULL;
 }
 
@@ -477,37 +486,20 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
                                                        __u8 type, __u16 state)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       struct list_head *p;
        struct hci_conn  *c;
 
-       list_for_each(p, &h->list) {
-               c = list_entry(p, struct hci_conn, list);
-               if (c->type == type && c->state == state)
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(c, &h->list, list) {
+               if (c->type == type && c->state == state) {
+                       rcu_read_unlock();
                        return c;
+               }
        }
-       return NULL;
-}
-
-static inline void hci_chan_hash_init(struct hci_conn *c)
-{
-       struct hci_chan_hash *h = &c->chan_hash;
-       INIT_LIST_HEAD(&h->list);
-       spin_lock_init(&h->lock);
-       h->num = 0;
-}
 
-static inline void hci_chan_hash_add(struct hci_conn *c, struct hci_chan *chan)
-{
-       struct hci_chan_hash *h = &c->chan_hash;
-       list_add(&chan->list, &h->list);
-       h->num++;
-}
+       rcu_read_unlock();
 
-static inline void hci_chan_hash_del(struct hci_conn *c, struct hci_chan *chan)
-{
-       struct hci_chan_hash *h = &c->chan_hash;
-       list_del(&chan->list);
-       h->num--;
+       return NULL;
 }
 
 void hci_acl_connect(struct hci_conn *conn);
@@ -523,7 +515,7 @@ void hci_conn_check_pending(struct hci_dev *hdev);
 
 struct hci_chan *hci_chan_create(struct hci_conn *conn);
 int hci_chan_del(struct hci_chan *chan);
-void hci_chan_hash_flush(struct hci_conn *conn);
+void hci_chan_list_flush(struct hci_conn *conn);
 
 struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
                                                __u8 sec_level, __u8 auth_type);
@@ -534,7 +526,6 @@ int hci_conn_change_link_key(struct hci_conn *conn);
 int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
 
 void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
-void hci_conn_enter_sniff_mode(struct hci_conn *conn);
 
 void hci_conn_hold_device(struct hci_conn *conn);
 void hci_conn_put_device(struct hci_conn *conn);
@@ -542,7 +533,7 @@ void hci_conn_put_device(struct hci_conn *conn);
 static inline void hci_conn_hold(struct hci_conn *conn)
 {
        atomic_inc(&conn->refcnt);
-       del_timer(&conn->disc_timer);
+       cancel_delayed_work_sync(&conn->disc_work);
 }
 
 static inline void hci_conn_put(struct hci_conn *conn)
@@ -561,7 +552,9 @@ static inline void hci_conn_put(struct hci_conn *conn)
                } else {
                        timeo = msecs_to_jiffies(10);
                }
-               mod_timer(&conn->disc_timer, jiffies + timeo);
+               cancel_delayed_work_sync(&conn->disc_work);
+               queue_delayed_work(conn->hdev->workqueue,
+                                       &conn->disc_work, jiffies + timeo);
        }
 }
 
@@ -591,10 +584,8 @@ static inline struct hci_dev *hci_dev_hold(struct hci_dev *d)
        return NULL;
 }
 
-#define hci_dev_lock(d)                spin_lock(&d->lock)
-#define hci_dev_unlock(d)      spin_unlock(&d->lock)
-#define hci_dev_lock_bh(d)     spin_lock_bh(&d->lock)
-#define hci_dev_unlock_bh(d)   spin_unlock_bh(&d->lock)
+#define hci_dev_lock(d)                mutex_lock(&d->lock)
+#define hci_dev_unlock(d)      mutex_unlock(&d->lock)
 
 struct hci_dev *hci_dev_get(int index);
 struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
@@ -954,12 +945,16 @@ int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
 /* HCI info for socket */
 #define hci_pi(sk) ((struct hci_pinfo *) sk)
 
+/* HCI socket flags */
+#define HCI_PI_MGMT_INIT       0
+
 struct hci_pinfo {
        struct bt_sock    bt;
        struct hci_dev    *hdev;
        struct hci_filter filter;
        __u32             cmsg_mask;
        unsigned short   channel;
+       unsigned long     flags;
 };
 
 /* HCI security filter */