Bluetooth: set quality report callback for Intel
authorJoseph Hwang <josephsih@chromium.org>
Sun, 15 Aug 2021 12:17:17 +0000 (20:17 +0800)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 30 Aug 2021 14:44:49 +0000 (16:44 +0200)
This patch sets up set_quality_report callback for Intel to
set and reset the debug features.

Reviewed-by: Miao-chen Chou <mcchou@chromium.org>
Signed-off-by: Joseph Hwang <josephsih@chromium.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
drivers/bluetooth/btintel.c
drivers/bluetooth/btintel.h

index 643e2194ca016aabb5a4f80506a4ff9b1db00514..778d803159f3164112e8ee5069ab1148d2e6fff7 100644 (file)
@@ -1291,8 +1291,10 @@ static int btintel_set_debug_features(struct hci_dev *hdev,
        u8 trace_enable = 0x02;
        struct sk_buff *skb;
 
-       if (!features)
+       if (!features) {
+               bt_dev_warn(hdev, "Debug features not read");
                return -EINVAL;
+       }
 
        if (!(features->page1[0] & 0x3f)) {
                bt_dev_info(hdev, "Telemetry exception format not supported");
@@ -1323,9 +1325,77 @@ static int btintel_set_debug_features(struct hci_dev *hdev,
        }
        kfree_skb(skb);
 
+       bt_dev_info(hdev, "set debug features: trace_enable 0x%02x mask 0x%02x",
+                   trace_enable, mask[3]);
+
        return 0;
 }
 
+static int btintel_reset_debug_features(struct hci_dev *hdev,
+                                const struct intel_debug_features *features)
+{
+       u8 mask[11] = { 0x0a, 0x92, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00 };
+       u8 trace_enable = 0x00;
+       struct sk_buff *skb;
+
+       if (!features) {
+               bt_dev_warn(hdev, "Debug features not read");
+               return -EINVAL;
+       }
+
+       if (!(features->page1[0] & 0x3f)) {
+               bt_dev_info(hdev, "Telemetry exception format not supported");
+               return 0;
+       }
+
+       /* Should stop the trace before writing ddc event mask. */
+       skb = __hci_cmd_sync(hdev, 0xfca1, 1, &trace_enable, HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb)) {
+               bt_dev_err(hdev, "Stop tracing of link statistics events failed (%ld)",
+                          PTR_ERR(skb));
+               return PTR_ERR(skb);
+       }
+       kfree_skb(skb);
+
+       skb = __hci_cmd_sync(hdev, 0xfc8b, 11, mask, HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb)) {
+               bt_dev_err(hdev, "Setting Intel telemetry ddc write event mask failed (%ld)",
+                          PTR_ERR(skb));
+               return PTR_ERR(skb);
+       }
+       kfree_skb(skb);
+
+       bt_dev_info(hdev, "reset debug features: trace_enable 0x%02x mask 0x%02x",
+                   trace_enable, mask[3]);
+
+       return 0;
+}
+
+int btintel_set_quality_report(struct hci_dev *hdev, bool enable)
+{
+       struct intel_debug_features features;
+       int err;
+
+       bt_dev_dbg(hdev, "enable %d", enable);
+
+       /* Read the Intel supported features and if new exception formats
+        * supported, need to load the additional DDC config to enable.
+        */
+       err = btintel_read_debug_features(hdev, &features);
+       if (err)
+               return err;
+
+       /* Set or reset the debug features. */
+       if (enable)
+               err = btintel_set_debug_features(hdev, &features);
+       else
+               err = btintel_reset_debug_features(hdev, &features);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(btintel_set_quality_report);
+
 static const struct firmware *btintel_legacy_rom_get_fw(struct hci_dev *hdev,
                                               struct intel_version *ver)
 {
@@ -1951,6 +2021,8 @@ static int btintel_bootloader_setup(struct hci_dev *hdev,
                btintel_load_ddc_config(hdev, ddcname);
        }
 
+       hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
+
        /* Read the Intel version information after loading the FW  */
        err = btintel_read_version(hdev, &new_ver);
        if (err)
@@ -2132,6 +2204,8 @@ static int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
         */
        btintel_load_ddc_config(hdev, ddcname);
 
+       hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
+
        /* Read the Intel version information after loading the FW  */
        err = btintel_read_version_tlv(hdev, &new_ver);
        if (err)
@@ -2230,6 +2304,9 @@ static int btintel_setup_combined(struct hci_dev *hdev)
        set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
        set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
 
+       /* Set up the quality report callback for Intel devices */
+       hdev->set_quality_report = btintel_set_quality_report;
+
        /* For Legacy device, check the HW platform value and size */
        if (skb->len == sizeof(ver) && skb->data[1] == 0x37) {
                bt_dev_dbg(hdev, "Read the legacy Intel version information");
index aa64072bbe68d77b5c0dce0e99b8e147d50f587b..fe02cb9ac96c0d542a3f25027a8945b1e022038e 100644 (file)
@@ -204,6 +204,7 @@ int btintel_configure_setup(struct hci_dev *hdev);
 void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len);
 void btintel_secure_send_result(struct hci_dev *hdev,
                                const void *ptr, unsigned int len);
+int btintel_set_quality_report(struct hci_dev *hdev, bool enable);
 #else
 
 static inline int btintel_check_bdaddr(struct hci_dev *hdev)
@@ -294,4 +295,9 @@ static inline void btintel_secure_send_result(struct hci_dev *hdev,
                                const void *ptr, unsigned int len)
 {
 }
+
+static inline int btintel_set_quality_report(struct hci_dev *hdev, bool enable)
+{
+       return -ENODEV;
+}
 #endif