Skip to content

Commit 31a9729

Browse files
committed
Merge tag 'for-net-2024-08-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: - btintel: Allow configuring drive strength of BRI - hci_core: Fix not handling hibernation actions - btnxpuart: Fix random crash seen while removing driver * tag 'for-net-2024-08-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Bluetooth: hci_core: Fix not handling hibernation actions Bluetooth: btnxpuart: Fix random crash seen while removing driver Bluetooth: btintel: Allow configuring drive strength of BRI ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 4186c8d + 18b3256 commit 31a9729

File tree

3 files changed

+150
-4
lines changed

3 files changed

+150
-4
lines changed

drivers/bluetooth/btintel.c

+124
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/acpi.h>
1313
#include <acpi/acpi_bus.h>
1414
#include <asm/unaligned.h>
15+
#include <linux/efi.h>
1516

1617
#include <net/bluetooth/bluetooth.h>
1718
#include <net/bluetooth/hci_core.h>
@@ -26,6 +27,8 @@
2627
#define ECDSA_OFFSET 644
2728
#define ECDSA_HEADER_LEN 320
2829

30+
#define BTINTEL_EFI_DSBR L"UefiCnvCommonDSBR"
31+
2932
enum {
3033
DSM_SET_WDISABLE2_DELAY = 1,
3134
DSM_SET_RESET_METHOD = 3,
@@ -2616,6 +2619,120 @@ static u8 btintel_classify_pkt_type(struct hci_dev *hdev, struct sk_buff *skb)
26162619
return hci_skb_pkt_type(skb);
26172620
}
26182621

2622+
/*
2623+
* UefiCnvCommonDSBR UEFI variable provides information from the OEM platforms
2624+
* if they have replaced the BRI (Bluetooth Radio Interface) resistor to
2625+
* overcome the potential STEP errors on their designs. Based on the
2626+
* configauration, bluetooth firmware shall adjust the BRI response line drive
2627+
* strength. The below structure represents DSBR data.
2628+
* struct {
2629+
* u8 header;
2630+
* u32 dsbr;
2631+
* } __packed;
2632+
*
2633+
* header - defines revision number of the structure
2634+
* dsbr - defines drive strength BRI response
2635+
* bit0
2636+
* 0 - instructs bluetooth firmware to use default values
2637+
* 1 - instructs bluetooth firmware to override default values
2638+
* bit3:1
2639+
* Reserved
2640+
* bit7:4
2641+
* DSBR override values (only if bit0 is set. Default value is 0xF
2642+
* bit31:7
2643+
* Reserved
2644+
* Expected values for dsbr field:
2645+
* 1. 0xF1 - indicates that the resistor on board is 33 Ohm
2646+
* 2. 0x00 or 0xB1 - indicates that the resistor on board is 10 Ohm
2647+
* 3. Non existing UEFI variable or invalid (none of the above) - indicates
2648+
* that the resistor on board is 10 Ohm
2649+
* Even if uefi variable is not present, driver shall send 0xfc0a command to
2650+
* firmware to use default values.
2651+
*
2652+
*/
2653+
static int btintel_uefi_get_dsbr(u32 *dsbr_var)
2654+
{
2655+
struct btintel_dsbr {
2656+
u8 header;
2657+
u32 dsbr;
2658+
} __packed data;
2659+
2660+
efi_status_t status;
2661+
unsigned long data_size = 0;
2662+
efi_guid_t guid = EFI_GUID(0xe65d8884, 0xd4af, 0x4b20, 0x8d, 0x03,
2663+
0x77, 0x2e, 0xcc, 0x3d, 0xa5, 0x31);
2664+
2665+
if (!IS_ENABLED(CONFIG_EFI))
2666+
return -EOPNOTSUPP;
2667+
2668+
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
2669+
return -EOPNOTSUPP;
2670+
2671+
status = efi.get_variable(BTINTEL_EFI_DSBR, &guid, NULL, &data_size,
2672+
NULL);
2673+
2674+
if (status != EFI_BUFFER_TOO_SMALL || !data_size)
2675+
return -EIO;
2676+
2677+
status = efi.get_variable(BTINTEL_EFI_DSBR, &guid, NULL, &data_size,
2678+
&data);
2679+
2680+
if (status != EFI_SUCCESS)
2681+
return -ENXIO;
2682+
2683+
*dsbr_var = data.dsbr;
2684+
return 0;
2685+
}
2686+
2687+
static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver)
2688+
{
2689+
struct btintel_dsbr_cmd {
2690+
u8 enable;
2691+
u8 dsbr;
2692+
} __packed;
2693+
2694+
struct btintel_dsbr_cmd cmd;
2695+
struct sk_buff *skb;
2696+
u8 status;
2697+
u32 dsbr;
2698+
bool apply_dsbr;
2699+
int err;
2700+
2701+
/* DSBR command needs to be sent for BlazarI + B0 step product after
2702+
* downloading IML image.
2703+
*/
2704+
apply_dsbr = (ver->img_type == BTINTEL_IMG_IML &&
2705+
((ver->cnvi_top & 0xfff) == BTINTEL_CNVI_BLAZARI) &&
2706+
INTEL_CNVX_TOP_STEP(ver->cnvi_top) == 0x01);
2707+
2708+
if (!apply_dsbr)
2709+
return 0;
2710+
2711+
dsbr = 0;
2712+
err = btintel_uefi_get_dsbr(&dsbr);
2713+
if (err < 0)
2714+
bt_dev_dbg(hdev, "Error reading efi: %ls (%d)",
2715+
BTINTEL_EFI_DSBR, err);
2716+
2717+
cmd.enable = dsbr & BIT(0);
2718+
cmd.dsbr = dsbr >> 4 & 0xF;
2719+
2720+
bt_dev_info(hdev, "dsbr: enable: 0x%2.2x value: 0x%2.2x", cmd.enable,
2721+
cmd.dsbr);
2722+
2723+
skb = __hci_cmd_sync(hdev, 0xfc0a, sizeof(cmd), &cmd, HCI_CMD_TIMEOUT);
2724+
if (IS_ERR(skb))
2725+
return -bt_to_errno(PTR_ERR(skb));
2726+
2727+
status = skb->data[0];
2728+
kfree_skb(skb);
2729+
2730+
if (status)
2731+
return -bt_to_errno(status);
2732+
2733+
return 0;
2734+
}
2735+
26192736
int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
26202737
struct intel_version_tlv *ver)
26212738
{
@@ -2650,6 +2767,13 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
26502767
if (err)
26512768
return err;
26522769

2770+
/* set drive strength of BRI response */
2771+
err = btintel_set_dsbr(hdev, ver);
2772+
if (err) {
2773+
bt_dev_err(hdev, "Failed to send dsbr command (%d)", err);
2774+
return err;
2775+
}
2776+
26532777
/* If image type returned is BTINTEL_IMG_IML, then controller supports
26542778
* intermediate loader image
26552779
*/

drivers/bluetooth/btnxpuart.c

+18-2
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,23 @@ static bool ps_wakeup(struct btnxpuart_dev *nxpdev)
449449
return false;
450450
}
451451

452+
static void ps_cleanup(struct btnxpuart_dev *nxpdev)
453+
{
454+
struct ps_data *psdata = &nxpdev->psdata;
455+
u8 ps_state;
456+
457+
mutex_lock(&psdata->ps_lock);
458+
ps_state = psdata->ps_state;
459+
mutex_unlock(&psdata->ps_lock);
460+
461+
if (ps_state != PS_STATE_AWAKE)
462+
ps_control(psdata->hdev, PS_STATE_AWAKE);
463+
464+
ps_cancel_timer(nxpdev);
465+
cancel_work_sync(&psdata->work);
466+
mutex_destroy(&psdata->ps_lock);
467+
}
468+
452469
static int send_ps_cmd(struct hci_dev *hdev, void *data)
453470
{
454471
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
@@ -1363,7 +1380,6 @@ static int btnxpuart_close(struct hci_dev *hdev)
13631380
{
13641381
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
13651382

1366-
ps_wakeup(nxpdev);
13671383
serdev_device_close(nxpdev->serdev);
13681384
skb_queue_purge(&nxpdev->txq);
13691385
if (!IS_ERR_OR_NULL(nxpdev->rx_skb)) {
@@ -1516,8 +1532,8 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
15161532
nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
15171533
nxp_set_baudrate_cmd(hdev, NULL);
15181534
}
1519-
ps_cancel_timer(nxpdev);
15201535
}
1536+
ps_cleanup(nxpdev);
15211537
hci_unregister_dev(hdev);
15221538
hci_free_dev(hdev);
15231539
}

net/bluetooth/hci_core.c

+8-2
Original file line numberDiff line numberDiff line change
@@ -2406,10 +2406,16 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
24062406
/* To avoid a potential race with hci_unregister_dev. */
24072407
hci_dev_hold(hdev);
24082408

2409-
if (action == PM_SUSPEND_PREPARE)
2409+
switch (action) {
2410+
case PM_HIBERNATION_PREPARE:
2411+
case PM_SUSPEND_PREPARE:
24102412
ret = hci_suspend_dev(hdev);
2411-
else if (action == PM_POST_SUSPEND)
2413+
break;
2414+
case PM_POST_HIBERNATION:
2415+
case PM_POST_SUSPEND:
24122416
ret = hci_resume_dev(hdev);
2417+
break;
2418+
}
24132419

24142420
if (ret)
24152421
bt_dev_err(hdev, "Suspend notifier action (%lu) failed: %d",

0 commit comments

Comments
 (0)