]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
Bluetooth: Add quirk to ignore reserved PHY bits in LE Extended Adv Report
authorSven Peter <sven@svenpeter.dev>
Wed, 15 May 2024 18:02:58 +0000 (18:02 +0000)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 28 Jun 2024 18:30:20 +0000 (14:30 -0400)
Some Broadcom controllers found on Apple Silicon machines abuse the
reserved bits inside the PHY fields of LE Extended Advertising Report
events for additional flags. Add a quirk to drop these and correctly
extract the Primary/Secondary_PHY field.

The following excerpt from a btmon trace shows a report received with
"Reserved" for "Primary PHY" on a 4388 controller:

> HCI Event: LE Meta Event (0x3e) plen 26
      LE Extended Advertising Report (0x0d)
        Num reports: 1
        Entry 0
          Event type: 0x2515
            Props: 0x0015
              Connectable
              Directed
              Use legacy advertising PDUs
            Data status: Complete
            Reserved (0x2500)
         Legacy PDU Type: Reserved (0x2515)
          Address type: Random (0x01)
          Address: 00:00:00:00:00:00 (Static)
          Primary PHY: Reserved
          Secondary PHY: No packets
          SID: no ADI field (0xff)
          TX power: 127 dBm
          RSSI: -60 dBm (0xc4)
          Periodic advertising interval: 0.00 msec (0x0000)
          Direct address type: Public (0x00)
          Direct address: 00:00:00:00:00:00 (Apple, Inc.)
          Data length: 0x00

Cc: stable@vger.kernel.org
Fixes: 2e7ed5f5e69b ("Bluetooth: hci_sync: Use advertised PHYs on hci_le_ext_create_conn_sync")
Reported-by: Janne Grunau <j@jannau.net>
Closes: https://lore.kernel.org/all/Zjz0atzRhFykROM9@robin
Tested-by: Janne Grunau <j@jannau.net>
Signed-off-by: Sven Peter <sven@svenpeter.dev>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
drivers/bluetooth/hci_bcm4377.c
include/net/bluetooth/hci.h
net/bluetooth/hci_event.c

index 0c2f15235b4cdaa42930dd3bf7eba4ffc2fa3c63..94e7365954435c877bb651f6938c9dd0e703fd01 100644 (file)
@@ -495,6 +495,10 @@ struct bcm4377_data;
  *                  extended scanning
  * broken_mws_transport_config: Set to true if the chip erroneously claims to
  *                              support MWS Transport Configuration
+ * broken_le_ext_adv_report_phy: Set to true if this chip stuffs flags inside
+ *                               reserved bits of Primary/Secondary_PHY inside
+ *                               LE Extended Advertising Report events which
+ *                               have to be ignored
  * send_calibration: Optional callback to send calibration data
  * send_ptb: Callback to send "PTB" regulatory/calibration data
  */
@@ -513,6 +517,7 @@ struct bcm4377_hw {
        unsigned long broken_ext_scan : 1;
        unsigned long broken_mws_transport_config : 1;
        unsigned long broken_le_coded : 1;
+       unsigned long broken_le_ext_adv_report_phy : 1;
 
        int (*send_calibration)(struct bcm4377_data *bcm4377);
        int (*send_ptb)(struct bcm4377_data *bcm4377,
@@ -2373,6 +2378,8 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
        if (bcm4377->hw->broken_le_coded)
                set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks);
+       if (bcm4377->hw->broken_le_ext_adv_report_phy)
+               set_bit(HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY, &hdev->quirks);
 
        pci_set_drvdata(pdev, bcm4377);
        hci_set_drvdata(hdev, bcm4377);
@@ -2477,6 +2484,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
                .clear_pciecfg_subsystem_ctrl_bit19 = true,
                .broken_mws_transport_config = true,
                .broken_le_coded = true,
+               .broken_le_ext_adv_report_phy = true,
                .send_calibration = bcm4387_send_calibration,
                .send_ptb = bcm4378_send_ptb,
        },
index fe932ca3bc8ca973a7c220a6cb729673657856e9..e372a88e8c3f6a9a640f791ad4ddcf9be25a7947 100644 (file)
@@ -324,6 +324,17 @@ enum {
         * claim to support it.
         */
        HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE,
+
+       /*
+        * When this quirk is set, the reserved bits of Primary/Secondary_PHY
+        * inside the LE Extended Advertising Report events are discarded.
+        * This is required for some Apple/Broadcom controllers which
+        * abuse these reserved bits for unrelated flags.
+        *
+        * This quirk can be set before hci_register_dev is called or
+        * during the hdev->setup vendor callback.
+        */
+       HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY,
 };
 
 /* HCI device flags */
index a487f9df81450fe92b58b67503e9c9fddc888c14..da10738a052d787d020b891a3de02728681e3668 100644 (file)
@@ -6311,6 +6311,13 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data,
 
                evt_type = __le16_to_cpu(info->type) & LE_EXT_ADV_EVT_TYPE_MASK;
                legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type);
+
+               if (test_bit(HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY,
+                            &hdev->quirks)) {
+                       info->primary_phy &= 0x1f;
+                       info->secondary_phy &= 0x1f;
+               }
+
                if (legacy_evt_type != LE_ADV_INVALID) {
                        process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
                                           info->bdaddr_type, NULL, 0,