Bluetooth: mgmt: Fix device_connected sending order
[linux-flexiantxendom0-3.2.10.git] / net / bluetooth / hci_core.c
index fabca08..d6dc44c 100644 (file)
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
-#include <linux/notifier.h>
 #include <linux/rfkill.h>
 #include <linux/timer.h>
 #include <linux/crypto.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
@@ -55,8 +53,6 @@
 
 #define AUTO_OFF_TIMEOUT 2000
 
-bool enable_hs;
-
 static void hci_rx_work(struct work_struct *work);
 static void hci_cmd_work(struct work_struct *work);
 static void hci_tx_work(struct work_struct *work);
@@ -69,24 +65,11 @@ DEFINE_RWLOCK(hci_dev_list_lock);
 LIST_HEAD(hci_cb_list);
 DEFINE_RWLOCK(hci_cb_list_lock);
 
-/* HCI notifiers list */
-static ATOMIC_NOTIFIER_HEAD(hci_notifier);
-
 /* ---- HCI notifications ---- */
 
-int hci_register_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&hci_notifier, nb);
-}
-
-int hci_unregister_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&hci_notifier, nb);
-}
-
 static void hci_notify(struct hci_dev *hdev, int event)
 {
-       atomic_notifier_call_chain(&hci_notifier, event, hdev);
+       hci_sock_dev_event(hdev, event);
 }
 
 /* ---- HCI requests ---- */
@@ -98,8 +81,28 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result)
        /* If this is the init phase check if the completed command matches
         * the last init command, and if not just return.
         */
-       if (test_bit(HCI_INIT, &hdev->flags) && hdev->init_last_cmd != cmd)
+       if (test_bit(HCI_INIT, &hdev->flags) && hdev->init_last_cmd != cmd) {
+               struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data;
+               struct sk_buff *skb;
+
+               /* Some CSR based controllers generate a spontaneous
+                * reset complete event during init and any pending
+                * command will never be completed. In such a case we
+                * need to resend whatever was the last sent
+                * command.
+                */
+
+               if (cmd != HCI_OP_RESET || sent->opcode == HCI_OP_RESET)
+                       return;
+
+               skb = skb_clone(hdev->sent_cmd, GFP_ATOMIC);
+               if (skb) {
+                       skb_queue_head(&hdev->cmd_q, skb);
+                       queue_work(hdev->workqueue, &hdev->cmd_work);
+               }
+
                return;
+       }
 
        if (hdev->req_status == HCI_REQ_PEND) {
                hdev->req_result = result;
@@ -379,10 +382,9 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
 
        switch (state) {
        case DISCOVERY_STOPPED:
-               hdev->discovery.type = 0;
-
                if (hdev->discovery.state != DISCOVERY_STARTING)
                        mgmt_discovering(hdev, 0);
+               hdev->discovery.type = 0;
                break;
        case DISCOVERY_STARTING:
                break;
@@ -410,7 +412,6 @@ static void inquiry_cache_flush(struct hci_dev *hdev)
 
        INIT_LIST_HEAD(&cache->unknown);
        INIT_LIST_HEAD(&cache->resolve);
-       cache->state = DISCOVERY_STOPPED;
 }
 
 struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
@@ -429,7 +430,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *b
 }
 
 struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
-                                                       bdaddr_t *bdaddr)
+                                                      bdaddr_t *bdaddr)
 {
        struct discovery_state *cache = &hdev->discovery;
        struct inquiry_entry *e;
@@ -445,8 +446,8 @@ struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
 }
 
 struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
-                                                       bdaddr_t *bdaddr,
-                                                       int state)
+                                                      bdaddr_t *bdaddr,
+                                                      int state)
 {
        struct discovery_state *cache = &hdev->discovery;
        struct inquiry_entry *e;
@@ -464,7 +465,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
 }
 
 void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
-                                               struct inquiry_entry *ie)
+                                     struct inquiry_entry *ie)
 {
        struct discovery_state *cache = &hdev->discovery;
        struct list_head *pos = &cache->resolve;
@@ -483,15 +484,21 @@ void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
 }
 
 bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
-                                                       bool name_known)
+                             bool name_known, bool *ssp)
 {
        struct discovery_state *cache = &hdev->discovery;
        struct inquiry_entry *ie;
 
        BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr));
 
+       if (ssp)
+               *ssp = data->ssp_mode;
+
        ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr);
        if (ie) {
+               if (ie->data.ssp_mode && ssp)
+                       *ssp = true;
+
                if (ie->name_state == NAME_NEEDED &&
                                                data->rssi != ie->data.rssi) {
                        ie->data.rssi = data->rssi;
@@ -658,6 +665,11 @@ int hci_dev_open(__u16 dev)
 
        hci_req_lock(hdev);
 
+       if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) {
+               ret = -ENODEV;
+               goto done;
+       }
+
        if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
                ret = -ERFKILL;
                goto done;
@@ -754,11 +766,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
        if (hdev->discov_timeout > 0) {
                cancel_delayed_work(&hdev->discov_off);
                hdev->discov_timeout = 0;
+               clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
        }
 
-       if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
-               cancel_delayed_work(&hdev->power_off);
-
        if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
                cancel_delayed_work(&hdev->service_cache);
 
@@ -804,13 +814,18 @@ static int hci_dev_do_close(struct hci_dev *hdev)
         * and no tasks are scheduled. */
        hdev->close(hdev);
 
-       hci_dev_lock(hdev);
-       mgmt_powered(hdev, 0);
-       hci_dev_unlock(hdev);
+       if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
+               hci_dev_lock(hdev);
+               mgmt_powered(hdev, 0);
+               hci_dev_unlock(hdev);
+       }
 
        /* Clear flags */
        hdev->flags = 0;
 
+       memset(hdev->eir, 0, sizeof(hdev->eir));
+       memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
+
        hci_req_unlock(hdev);
 
        hci_dev_put(hdev);
@@ -825,7 +840,12 @@ int hci_dev_close(__u16 dev)
        hdev = hci_dev_get(dev);
        if (!hdev)
                return -ENODEV;
+
+       if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+               cancel_delayed_work(&hdev->power_off);
+
        err = hci_dev_do_close(hdev);
+
        hci_dev_put(hdev);
        return err;
 }
@@ -1119,9 +1139,7 @@ static void hci_power_off(struct work_struct *work)
 
        BT_DBG("%s", hdev->name);
 
-       clear_bit(HCI_AUTO_OFF, &hdev->dev_flags);
-
-       hci_dev_close(hdev->id);
+       hci_dev_do_close(hdev);
 }
 
 static void hci_discov_off(struct work_struct *work)
@@ -1197,40 +1215,40 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
        return NULL;
 }
 
-static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
+static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
                                                u8 key_type, u8 old_key_type)
 {
        /* Legacy key */
        if (key_type < 0x03)
-               return 1;
+               return true;
 
        /* Debug keys are insecure so don't store them persistently */
        if (key_type == HCI_LK_DEBUG_COMBINATION)
-               return 0;
+               return false;
 
        /* Changed combination key and there's no previous one */
        if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
-               return 0;
+               return false;
 
        /* Security mode 3 case */
        if (!conn)
-               return 1;
+               return true;
 
        /* Neither local nor remote side had no-bonding as requirement */
        if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
-               return 1;
+               return true;
 
        /* Local side had dedicated bonding as requirement */
        if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
-               return 1;
+               return true;
 
        /* Remote side had dedicated bonding as requirement */
        if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
-               return 1;
+               return true;
 
        /* If none of the above criteria match, then don't store the key
         * persistently */
-       return 0;
+       return false;
 }
 
 struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
@@ -1250,7 +1268,7 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
 EXPORT_SYMBOL(hci_find_ltk);
 
 struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
-                                                               u8 addr_type)
+                                    u8 addr_type)
 {
        struct smp_ltk *k;
 
@@ -1264,10 +1282,11 @@ struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
 EXPORT_SYMBOL(hci_find_ltk_by_addr);
 
 int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
-                               bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
+                    bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
 {
        struct link_key *key, *old_key;
-       u8 old_key_type, persistent;
+       u8 old_key_type;
+       bool persistent;
 
        old_key = hci_find_link_key(hdev, bdaddr);
        if (old_key) {
@@ -1310,17 +1329,15 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
 
        mgmt_new_link_key(hdev, key, persistent);
 
-       if (!persistent) {
-               list_del(&key->list);
-               kfree(key);
-       }
+       if (conn)
+               conn->flush_key = !persistent;
 
        return 0;
 }
 
 int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
-                               int new_key, u8 authenticated, u8 tk[16],
-                               u8 enc_size, u16 ediv, u8 rand[8])
+               int new_key, u8 authenticated, u8 tk[16], u8 enc_size, u16
+               ediv, u8 rand[8])
 {
        struct smp_ltk *key, *old_key;
 
@@ -1399,7 +1416,7 @@ static void hci_cmd_timer(unsigned long arg)
 }
 
 struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
-                                                       bdaddr_t *bdaddr)
+                                         bdaddr_t *bdaddr)
 {
        struct oob_data *data;
 
@@ -1439,7 +1456,7 @@ int hci_remote_oob_data_clear(struct hci_dev *hdev)
 }
 
 int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
-                                                               u8 *randomizer)
+                           u8 *randomizer)
 {
        struct oob_data *data;
 
@@ -1462,8 +1479,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
        return 0;
 }
 
-struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
-                                               bdaddr_t *bdaddr)
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
        struct bdaddr_list *b;
 
@@ -1531,7 +1547,7 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 static void hci_clear_adv_cache(struct work_struct *work)
 {
        struct hci_dev *hdev = container_of(work, struct hci_dev,
-                                                       adv_work.work);
+                                           adv_work.work);
 
        hci_dev_lock(hdev);
 
@@ -1574,11 +1590,7 @@ static inline int is_connectable_adv(u8 evt_type)
 }
 
 int hci_add_adv_entry(struct hci_dev *hdev,
-                                       struct hci_ev_le_advertising_info *ev)
-{
-       struct adv_entry *entry;
-
-       if (!is_connectable_adv(ev->evt_type))
+                                       struct hci_ev_le_advertising_info *ev) { struct adv_entry *entry; if (!is_connectable_adv(ev->evt_type))
                return -EINVAL;
 
        /* Only new entries should be added to adv_entries. So, if
@@ -1625,7 +1637,7 @@ static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt)
 }
 
 static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
-                                               u16 window, int timeout)
+                         u16 window, int timeout)
 {
        long timeo = msecs_to_jiffies(3000);
        struct le_scan_params param;
@@ -1643,7 +1655,7 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
        hci_req_lock(hdev);
 
        err = __hci_request(hdev, le_scan_param_req, (unsigned long) &param,
-                                                                       timeo);
+                           timeo);
        if (!err)
                err = __hci_request(hdev, le_scan_enable_req, 0, timeo);
 
@@ -1653,7 +1665,7 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
                return err;
 
        schedule_delayed_work(&hdev->le_scan_disable,
-                                               msecs_to_jiffies(timeout));
+                             msecs_to_jiffies(timeout));
 
        return 0;
 }
@@ -1661,7 +1673,7 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
 static void le_scan_disable_work(struct work_struct *work)
 {
        struct hci_dev *hdev = container_of(work, struct hci_dev,
-                                               le_scan_disable.work);
+                                           le_scan_disable.work);
        struct hci_cp_le_set_scan_enable cp;
 
        BT_DBG("%s", hdev->name);
@@ -1678,12 +1690,12 @@ static void le_scan_work(struct work_struct *work)
 
        BT_DBG("%s", hdev->name);
 
-       hci_do_le_scan(hdev, param->type, param->interval,
-                                       param->window, param->timeout);
+       hci_do_le_scan(hdev, param->type, param->interval, param->window,
+                      param->timeout);
 }
 
 int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window,
-                                                               int timeout)
+               int timeout)
 {
        struct le_scan_params *param = &hdev->le_scan_params;
 
@@ -1841,6 +1853,8 @@ void hci_unregister_dev(struct hci_dev *hdev)
 
        BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
 
+       set_bit(HCI_UNREGISTER, &hdev->dev_flags);
+
        write_lock(&hci_dev_list_lock);
        list_del(&hdev->list);
        write_unlock(&hci_dev_list_lock);
@@ -1971,7 +1985,7 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
 
        while (count) {
                scb = (void *) skb->cb;
-               len = min(scb->expect, (__u16)count);
+               len = min_t(uint, scb->expect, count);
 
                memcpy(skb_put(skb, len), data, len);
 
@@ -2127,11 +2141,15 @@ static int hci_send_frame(struct sk_buff *skb)
 
        BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
 
-       if (atomic_read(&hdev->promisc)) {
-               /* Time stamp */
-               __net_timestamp(skb);
+       /* Time stamp */
+       __net_timestamp(skb);
 
-               hci_send_to_sock(hdev, skb, NULL);
+       /* Send copy to monitor */
+       hci_send_to_monitor(hdev, skb);
+
+       if (atomic_read(&hdev->promisc)) {
+               /* Send copy to the sockets */
+               hci_send_to_sock(hdev, skb);
        }
 
        /* Get rid of skb owner, prior to sending to the driver. */
@@ -2540,7 +2558,7 @@ static inline void hci_sched_acl_pkt(struct hci_dev *hdev)
                        skb = skb_dequeue(&chan->data_q);
 
                        hci_conn_enter_active_mode(chan->conn,
-                                               bt_cb(skb)->force_active);
+                                                  bt_cb(skb)->force_active);
 
                        hci_send_frame(skb);
                        hdev->acl_last_tx = jiffies;
@@ -2766,6 +2784,14 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
        if (conn) {
                hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
 
+               hci_dev_lock(hdev);
+               if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
+                   !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+                       mgmt_device_connected(hdev, &conn->dst, conn->type,
+                                             conn->dst_type, 0, NULL, 0,
+                                             conn->dev_class);
+               hci_dev_unlock(hdev);
+
                /* Send to upper protocol */
                l2cap_recv_acldata(conn, skb, flags);
                return;
@@ -2816,9 +2842,12 @@ static void hci_rx_work(struct work_struct *work)
        BT_DBG("%s", hdev->name);
 
        while ((skb = skb_dequeue(&hdev->rx_q))) {
+               /* Send copy to monitor */
+               hci_send_to_monitor(hdev, skb);
+
                if (atomic_read(&hdev->promisc)) {
                        /* Send copy to the sockets */
-                       hci_send_to_sock(hdev, skb, NULL);
+                       hci_send_to_sock(hdev, skb);
                }
 
                if (test_bit(HCI_RAW, &hdev->flags)) {
@@ -2920,6 +2949,3 @@ int hci_cancel_inquiry(struct hci_dev *hdev)
 
        return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
 }
-
-module_param(enable_hs, bool, 0644);
-MODULE_PARM_DESC(enable_hs, "Enable High Speed");