Bluetooth: Split HCI init sequence into three stages
authorJohan Hedberg <johan.hedberg@intel.com>
Tue, 5 Mar 2013 18:37:43 +0000 (20:37 +0200)
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>
Fri, 8 Mar 2013 13:40:25 +0000 (10:40 -0300)
Having conditional command sending during a request has always been
problematic and caused hacks like the hdev->init_last_cmd variable. This
patch removes these conditionals and instead splits the init sequence
into three stages, each with its own __hci_req_sync() call.

This also paves the way to the upcoming asynchronous request support
swhich will also benefit by having a simpler implementation if it
doesn't need to cater for requests that change on the fly.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c

index 9369e01..6ab38fe 100644 (file)
@@ -193,6 +193,9 @@ static void bredr_init(struct hci_dev *hdev)
 
        /* Read Local Version */
        hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
+
+       /* Read BD Address */
+       hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
 }
 
 static void amp_init(struct hci_dev *hdev)
@@ -209,7 +212,7 @@ static void amp_init(struct hci_dev *hdev)
        hci_send_cmd(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL);
 }
 
-static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
+static void hci_init1_req(struct hci_dev *hdev, unsigned long opt)
 {
        struct sk_buff *skb;
 
@@ -246,6 +249,273 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
        }
 }
 
+static void bredr_setup(struct hci_dev *hdev)
+{
+       struct hci_cp_delete_stored_link_key cp;
+       __le16 param;
+       __u8 flt_type;
+
+       /* Read Buffer Size (ACL mtu, max pkt, etc.) */
+       hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
+
+       /* Read Class of Device */
+       hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
+
+       /* Read Local Name */
+       hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
+
+       /* Read Voice Setting */
+       hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
+
+       /* Clear Event Filters */
+       flt_type = HCI_FLT_CLEAR_ALL;
+       hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
+
+       /* Connection accept timeout ~20 secs */
+       param = __constant_cpu_to_le16(0x7d00);
+       hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
+
+       bacpy(&cp.bdaddr, BDADDR_ANY);
+       cp.delete_all = 0x01;
+       hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
+}
+
+static void le_setup(struct hci_dev *hdev)
+{
+       /* Read LE Buffer Size */
+       hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
+
+       /* Read LE Local Supported Features */
+       hci_send_cmd(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL);
+
+       /* Read LE Advertising Channel TX Power */
+       hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
+
+       /* Read LE White List Size */
+       hci_send_cmd(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
+
+       /* Read LE Supported States */
+       hci_send_cmd(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
+}
+
+static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
+{
+       if (lmp_ext_inq_capable(hdev))
+               return 0x02;
+
+       if (lmp_inq_rssi_capable(hdev))
+               return 0x01;
+
+       if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
+           hdev->lmp_subver == 0x0757)
+               return 0x01;
+
+       if (hdev->manufacturer == 15) {
+               if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
+                       return 0x01;
+               if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
+                       return 0x01;
+               if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
+                       return 0x01;
+       }
+
+       if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
+           hdev->lmp_subver == 0x1805)
+               return 0x01;
+
+       return 0x00;
+}
+
+static void hci_setup_inquiry_mode(struct hci_dev *hdev)
+{
+       u8 mode;
+
+       mode = hci_get_inquiry_mode(hdev);
+
+       hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
+}
+
+static void hci_setup_event_mask(struct hci_dev *hdev)
+{
+       /* The second byte is 0xff instead of 0x9f (two reserved bits
+        * disabled) since a Broadcom 1.2 dongle doesn't respond to the
+        * command otherwise.
+        */
+       u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
+
+       /* CSR 1.1 dongles does not accept any bitfield so don't try to set
+        * any event mask for pre 1.2 devices.
+        */
+       if (hdev->hci_ver < BLUETOOTH_VER_1_2)
+               return;
+
+       if (lmp_bredr_capable(hdev)) {
+               events[4] |= 0x01; /* Flow Specification Complete */
+               events[4] |= 0x02; /* Inquiry Result with RSSI */
+               events[4] |= 0x04; /* Read Remote Extended Features Complete */
+               events[5] |= 0x08; /* Synchronous Connection Complete */
+               events[5] |= 0x10; /* Synchronous Connection Changed */
+       }
+
+       if (lmp_inq_rssi_capable(hdev))
+               events[4] |= 0x02; /* Inquiry Result with RSSI */
+
+       if (lmp_sniffsubr_capable(hdev))
+               events[5] |= 0x20; /* Sniff Subrating */
+
+       if (lmp_pause_enc_capable(hdev))
+               events[5] |= 0x80; /* Encryption Key Refresh Complete */
+
+       if (lmp_ext_inq_capable(hdev))
+               events[5] |= 0x40; /* Extended Inquiry Result */
+
+       if (lmp_no_flush_capable(hdev))
+               events[7] |= 0x01; /* Enhanced Flush Complete */
+
+       if (lmp_lsto_capable(hdev))
+               events[6] |= 0x80; /* Link Supervision Timeout Changed */
+
+       if (lmp_ssp_capable(hdev)) {
+               events[6] |= 0x01;      /* IO Capability Request */
+               events[6] |= 0x02;      /* IO Capability Response */
+               events[6] |= 0x04;      /* User Confirmation Request */
+               events[6] |= 0x08;      /* User Passkey Request */
+               events[6] |= 0x10;      /* Remote OOB Data Request */
+               events[6] |= 0x20;      /* Simple Pairing Complete */
+               events[7] |= 0x04;      /* User Passkey Notification */
+               events[7] |= 0x08;      /* Keypress Notification */
+               events[7] |= 0x10;      /* Remote Host Supported
+                                        * Features Notification
+                                        */
+       }
+
+       if (lmp_le_capable(hdev))
+               events[7] |= 0x20;      /* LE Meta-Event */
+
+       hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
+
+       if (lmp_le_capable(hdev)) {
+               memset(events, 0, sizeof(events));
+               events[0] = 0x1f;
+               hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
+                            sizeof(events), events);
+       }
+}
+
+static void hci_init2_req(struct hci_dev *hdev, unsigned long opt)
+{
+       if (lmp_bredr_capable(hdev))
+               bredr_setup(hdev);
+
+       if (lmp_le_capable(hdev))
+               le_setup(hdev);
+
+       hci_setup_event_mask(hdev);
+
+       if (hdev->hci_ver > BLUETOOTH_VER_1_1)
+               hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
+
+       if (lmp_ssp_capable(hdev)) {
+               if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+                       u8 mode = 0x01;
+                       hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
+                                    sizeof(mode), &mode);
+               } else {
+                       struct hci_cp_write_eir cp;
+
+                       memset(hdev->eir, 0, sizeof(hdev->eir));
+                       memset(&cp, 0, sizeof(cp));
+
+                       hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
+               }
+       }
+
+       if (lmp_inq_rssi_capable(hdev))
+               hci_setup_inquiry_mode(hdev);
+
+       if (lmp_inq_tx_pwr_capable(hdev))
+               hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
+
+       if (lmp_ext_feat_capable(hdev)) {
+               struct hci_cp_read_local_ext_features cp;
+
+               cp.page = 0x01;
+               hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
+                            &cp);
+       }
+
+       if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
+               u8 enable = 1;
+               hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
+                            &enable);
+       }
+}
+
+static void hci_setup_link_policy(struct hci_dev *hdev)
+{
+       struct hci_cp_write_def_link_policy cp;
+       u16 link_policy = 0;
+
+       if (lmp_rswitch_capable(hdev))
+               link_policy |= HCI_LP_RSWITCH;
+       if (lmp_hold_capable(hdev))
+               link_policy |= HCI_LP_HOLD;
+       if (lmp_sniff_capable(hdev))
+               link_policy |= HCI_LP_SNIFF;
+       if (lmp_park_capable(hdev))
+               link_policy |= HCI_LP_PARK;
+
+       cp.policy = cpu_to_le16(link_policy);
+       hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
+}
+
+static void hci_set_le_support(struct hci_dev *hdev)
+{
+       struct hci_cp_write_le_host_supported cp;
+
+       memset(&cp, 0, sizeof(cp));
+
+       if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
+               cp.le = 0x01;
+               cp.simul = lmp_le_br_capable(hdev);
+       }
+
+       if (cp.le != lmp_host_le_capable(hdev))
+               hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
+                            &cp);
+}
+
+static void hci_init3_req(struct hci_dev *hdev, unsigned long opt)
+{
+       if (hdev->commands[5] & 0x10)
+               hci_setup_link_policy(hdev);
+
+       if (lmp_le_capable(hdev))
+               hci_set_le_support(hdev);
+}
+
+static int __hci_init(struct hci_dev *hdev)
+{
+       int err;
+
+       err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT);
+       if (err < 0)
+               return err;
+
+       /* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode
+        * BR/EDR/LE type controllers. AMP controllers only need the
+        * first stage init.
+        */
+       if (hdev->dev_type != HCI_BREDR)
+               return 0;
+
+       err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT);
+       if (err < 0)
+               return err;
+
+       return __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT);
+}
+
 static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
 {
        __u8 scan = opt;
@@ -746,7 +1016,7 @@ int hci_dev_open(__u16 dev)
                set_bit(HCI_INIT, &hdev->flags);
                hdev->init_last_cmd = 0;
 
-               ret = __hci_req_sync(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
+               ret = __hci_init(hdev);
 
                clear_bit(HCI_INIT, &hdev->flags);
        }
index 5892e54..14e872a 100644 (file)
@@ -472,211 +472,6 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
        }
 }
 
-static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
-{
-       if (lmp_ext_inq_capable(hdev))
-               return 2;
-
-       if (lmp_inq_rssi_capable(hdev))
-               return 1;
-
-       if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
-           hdev->lmp_subver == 0x0757)
-               return 1;
-
-       if (hdev->manufacturer == 15) {
-               if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
-                       return 1;
-               if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
-                       return 1;
-               if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
-                       return 1;
-       }
-
-       if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
-           hdev->lmp_subver == 0x1805)
-               return 1;
-
-       return 0;
-}
-
-static void hci_setup_inquiry_mode(struct hci_dev *hdev)
-{
-       u8 mode;
-
-       mode = hci_get_inquiry_mode(hdev);
-
-       hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
-}
-
-static void hci_setup_event_mask(struct hci_dev *hdev)
-{
-       /* The second byte is 0xff instead of 0x9f (two reserved bits
-        * disabled) since a Broadcom 1.2 dongle doesn't respond to the
-        * command otherwise */
-       u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
-
-       /* CSR 1.1 dongles does not accept any bitfield so don't try to set
-        * any event mask for pre 1.2 devices */
-       if (hdev->hci_ver < BLUETOOTH_VER_1_2)
-               return;
-
-       if (lmp_bredr_capable(hdev)) {
-               events[4] |= 0x01; /* Flow Specification Complete */
-               events[4] |= 0x02; /* Inquiry Result with RSSI */
-               events[4] |= 0x04; /* Read Remote Extended Features Complete */
-               events[5] |= 0x08; /* Synchronous Connection Complete */
-               events[5] |= 0x10; /* Synchronous Connection Changed */
-       }
-
-       if (lmp_inq_rssi_capable(hdev))
-               events[4] |= 0x02; /* Inquiry Result with RSSI */
-
-       if (lmp_sniffsubr_capable(hdev))
-               events[5] |= 0x20; /* Sniff Subrating */
-
-       if (lmp_pause_enc_capable(hdev))
-               events[5] |= 0x80; /* Encryption Key Refresh Complete */
-
-       if (lmp_ext_inq_capable(hdev))
-               events[5] |= 0x40; /* Extended Inquiry Result */
-
-       if (lmp_no_flush_capable(hdev))
-               events[7] |= 0x01; /* Enhanced Flush Complete */
-
-       if (lmp_lsto_capable(hdev))
-               events[6] |= 0x80; /* Link Supervision Timeout Changed */
-
-       if (lmp_ssp_capable(hdev)) {
-               events[6] |= 0x01;      /* IO Capability Request */
-               events[6] |= 0x02;      /* IO Capability Response */
-               events[6] |= 0x04;      /* User Confirmation Request */
-               events[6] |= 0x08;      /* User Passkey Request */
-               events[6] |= 0x10;      /* Remote OOB Data Request */
-               events[6] |= 0x20;      /* Simple Pairing Complete */
-               events[7] |= 0x04;      /* User Passkey Notification */
-               events[7] |= 0x08;      /* Keypress Notification */
-               events[7] |= 0x10;      /* Remote Host Supported
-                                        * Features Notification */
-       }
-
-       if (lmp_le_capable(hdev))
-               events[7] |= 0x20;      /* LE Meta-Event */
-
-       hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
-
-       if (lmp_le_capable(hdev)) {
-               memset(events, 0, sizeof(events));
-               events[0] = 0x1f;
-               hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
-                            sizeof(events), events);
-       }
-}
-
-static void bredr_setup(struct hci_dev *hdev)
-{
-       struct hci_cp_delete_stored_link_key cp;
-       __le16 param;
-       __u8 flt_type;
-
-       /* Read Buffer Size (ACL mtu, max pkt, etc.) */
-       hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
-
-       /* Read Class of Device */
-       hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
-
-       /* Read Local Name */
-       hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
-
-       /* Read Voice Setting */
-       hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
-
-       /* Clear Event Filters */
-       flt_type = HCI_FLT_CLEAR_ALL;
-       hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
-
-       /* Connection accept timeout ~20 secs */
-       param = __constant_cpu_to_le16(0x7d00);
-       hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
-
-       bacpy(&cp.bdaddr, BDADDR_ANY);
-       cp.delete_all = 1;
-       hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
-}
-
-static void le_setup(struct hci_dev *hdev)
-{
-       /* Read LE Buffer Size */
-       hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
-
-       /* Read LE Local Supported Features */
-       hci_send_cmd(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL);
-
-       /* Read LE Advertising Channel TX Power */
-       hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
-
-       /* Read LE White List Size */
-       hci_send_cmd(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
-
-       /* Read LE Supported States */
-       hci_send_cmd(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
-}
-
-static void hci_setup(struct hci_dev *hdev)
-{
-       if (hdev->dev_type != HCI_BREDR)
-               return;
-
-       /* Read BD Address */
-       hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
-
-       if (lmp_bredr_capable(hdev))
-               bredr_setup(hdev);
-
-       if (lmp_le_capable(hdev))
-               le_setup(hdev);
-
-       hci_setup_event_mask(hdev);
-
-       if (hdev->hci_ver > BLUETOOTH_VER_1_1)
-               hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
-
-       if (lmp_ssp_capable(hdev)) {
-               if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
-                       u8 mode = 0x01;
-                       hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
-                                    sizeof(mode), &mode);
-               } else {
-                       struct hci_cp_write_eir cp;
-
-                       memset(hdev->eir, 0, sizeof(hdev->eir));
-                       memset(&cp, 0, sizeof(cp));
-
-                       hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
-               }
-       }
-
-       if (lmp_inq_rssi_capable(hdev))
-               hci_setup_inquiry_mode(hdev);
-
-       if (lmp_inq_tx_pwr_capable(hdev))
-               hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
-
-       if (lmp_ext_feat_capable(hdev)) {
-               struct hci_cp_read_local_ext_features cp;
-
-               cp.page = 0x01;
-               hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
-                            &cp);
-       }
-
-       if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
-               u8 enable = 1;
-               hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
-                            &enable);
-       }
-}
-
 static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_rp_read_local_version *rp = (void *) skb->data;
@@ -695,31 +490,10 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
        BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
               hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
 
-       if (test_bit(HCI_INIT, &hdev->flags))
-               hci_setup(hdev);
-
 done:
        hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
 }
 
-static void hci_setup_link_policy(struct hci_dev *hdev)
-{
-       struct hci_cp_write_def_link_policy cp;
-       u16 link_policy = 0;
-
-       if (lmp_rswitch_capable(hdev))
-               link_policy |= HCI_LP_RSWITCH;
-       if (lmp_hold_capable(hdev))
-               link_policy |= HCI_LP_HOLD;
-       if (lmp_sniff_capable(hdev))
-               link_policy |= HCI_LP_SNIFF;
-       if (lmp_park_capable(hdev))
-               link_policy |= HCI_LP_PARK;
-
-       cp.policy = cpu_to_le16(link_policy);
-       hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
-}
-
 static void hci_cc_read_local_commands(struct hci_dev *hdev,
                                       struct sk_buff *skb)
 {
@@ -727,15 +501,9 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev,
 
        BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
-       if (rp->status)
-               goto done;
-
-       memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
-
-       if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
-               hci_setup_link_policy(hdev);
+       if (!rp->status)
+               memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
 
-done:
        hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
 }
 
@@ -795,22 +563,6 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
               hdev->features[6], hdev->features[7]);
 }
 
-static void hci_set_le_support(struct hci_dev *hdev)
-{
-       struct hci_cp_write_le_host_supported cp;
-
-       memset(&cp, 0, sizeof(cp));
-
-       if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
-               cp.le = 1;
-               cp.simul = lmp_le_br_capable(hdev);
-       }
-
-       if (cp.le != lmp_host_le_capable(hdev))
-               hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
-                            &cp);
-}
-
 static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
                                           struct sk_buff *skb)
 {
@@ -830,9 +582,6 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
                break;
        }
 
-       if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
-               hci_set_le_support(hdev);
-
 done:
        hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
 }