Commit ed2a2ef1 authored by Sven Peter's avatar Sven Peter Committed by Luiz Augusto von Dentz

Bluetooth: Add quirk to ignore reserved PHY bits in LE Extended Adv Report

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: 2e7ed5f5 ("Bluetooth: hci_sync: Use advertised PHYs on hci_le_ext_create_conn_sync")
Reported-by: default avatarJanne Grunau <j@jannau.net>
Closes: https://lore.kernel.org/all/Zjz0atzRhFykROM9@robinTested-by: default avatarJanne Grunau <j@jannau.net>
Signed-off-by: default avatarSven Peter <sven@svenpeter.dev>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent dc6be0b7
...@@ -495,6 +495,10 @@ struct bcm4377_data; ...@@ -495,6 +495,10 @@ struct bcm4377_data;
* extended scanning * extended scanning
* broken_mws_transport_config: Set to true if the chip erroneously claims to * broken_mws_transport_config: Set to true if the chip erroneously claims to
* support MWS Transport Configuration * 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_calibration: Optional callback to send calibration data
* send_ptb: Callback to send "PTB" regulatory/calibration data * send_ptb: Callback to send "PTB" regulatory/calibration data
*/ */
...@@ -513,6 +517,7 @@ struct bcm4377_hw { ...@@ -513,6 +517,7 @@ struct bcm4377_hw {
unsigned long broken_ext_scan : 1; unsigned long broken_ext_scan : 1;
unsigned long broken_mws_transport_config : 1; unsigned long broken_mws_transport_config : 1;
unsigned long broken_le_coded : 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_calibration)(struct bcm4377_data *bcm4377);
int (*send_ptb)(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) ...@@ -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); set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
if (bcm4377->hw->broken_le_coded) if (bcm4377->hw->broken_le_coded)
set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); 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); pci_set_drvdata(pdev, bcm4377);
hci_set_drvdata(hdev, bcm4377); hci_set_drvdata(hdev, bcm4377);
...@@ -2477,6 +2484,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = { ...@@ -2477,6 +2484,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
.clear_pciecfg_subsystem_ctrl_bit19 = true, .clear_pciecfg_subsystem_ctrl_bit19 = true,
.broken_mws_transport_config = true, .broken_mws_transport_config = true,
.broken_le_coded = true, .broken_le_coded = true,
.broken_le_ext_adv_report_phy = true,
.send_calibration = bcm4387_send_calibration, .send_calibration = bcm4387_send_calibration,
.send_ptb = bcm4378_send_ptb, .send_ptb = bcm4378_send_ptb,
}, },
......
...@@ -324,6 +324,17 @@ enum { ...@@ -324,6 +324,17 @@ enum {
* claim to support it. * claim to support it.
*/ */
HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, 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 */ /* HCI device flags */
......
...@@ -6311,6 +6311,13 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data, ...@@ -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; evt_type = __le16_to_cpu(info->type) & LE_EXT_ADV_EVT_TYPE_MASK;
legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type); 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) { if (legacy_evt_type != LE_ADV_INVALID) {
process_adv_report(hdev, legacy_evt_type, &info->bdaddr, process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
info->bdaddr_type, NULL, 0, info->bdaddr_type, NULL, 0,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment