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 -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmbI6ekZHGx1aXoudm9u LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKd2WD/9D9rjtwrPKMHRoxuGpyrWJ t7Z3rr/TBUfjHT+GcmKvA8q9ZOmb9OXpFRfXwN/xUb34B8hs4hn9TsEy3RztJhlu M6o14Te/hrpv6FK698O9doIIrzccGueN99MCXgs809RQLFHsu8cLy/xl+KrKdtyK w6S0ceeNFAnGd0LjaDSsPPoqxLYRYWNitj4gxEHMY1NnXW98dhzQ10deJjDgba86 4BxcOIoOGsN36eFsv424U8xqPj9He+zKsQPSmYCPY/AFW3ojbqTs1VVZE8yxI1q2 qCf+whYXaOq8MYNFSO0Lc8PrPX744gtTTkudzlZJLt0niMq1M1fI6ovS5VtHDG2f rpPfvejOz15Ii7eYQAo0bdXn6zr7AgKburv6BYyMKq4LTM49OXuweHEU23Z4xbpZ OhqTMf0Qmvw2k33e7PdplC2EzE/WKkqux9C50n5lJZ1WMFxga7SyRhUtw4o8A4ev pNd9BbqZWTRtNWOYuRmyqN99/Kj8tfUi0E3MtHLcdZqTR1a/sCuaCpc9UB8lVay2 Z3kh8T8hmeE3vLY+d/OSJDWb03Tqdy171jpvO6908tUtHyvHbYFvkPc9vS8dr8ae tHM36Bs0imjsy66aKOGigjb+wtVwP6QEcJbM5FobUJMVjAfya657H7r8NAPpzxhV OAnIIsU9eX9oqOdzyS4QeQ== =m4CK -----END PGP SIGNATURE----- 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/20240823200008.65241-1-luiz.dentz@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
31a972959a
3 changed files with 150 additions and 4 deletions
|
@ -12,6 +12,7 @@
|
|||
#include <linux/acpi.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/efi.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
@ -26,6 +27,8 @@
|
|||
#define ECDSA_OFFSET 644
|
||||
#define ECDSA_HEADER_LEN 320
|
||||
|
||||
#define BTINTEL_EFI_DSBR L"UefiCnvCommonDSBR"
|
||||
|
||||
enum {
|
||||
DSM_SET_WDISABLE2_DELAY = 1,
|
||||
DSM_SET_RESET_METHOD = 3,
|
||||
|
@ -2616,6 +2619,120 @@ static u8 btintel_classify_pkt_type(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
return hci_skb_pkt_type(skb);
|
||||
}
|
||||
|
||||
/*
|
||||
* UefiCnvCommonDSBR UEFI variable provides information from the OEM platforms
|
||||
* if they have replaced the BRI (Bluetooth Radio Interface) resistor to
|
||||
* overcome the potential STEP errors on their designs. Based on the
|
||||
* configauration, bluetooth firmware shall adjust the BRI response line drive
|
||||
* strength. The below structure represents DSBR data.
|
||||
* struct {
|
||||
* u8 header;
|
||||
* u32 dsbr;
|
||||
* } __packed;
|
||||
*
|
||||
* header - defines revision number of the structure
|
||||
* dsbr - defines drive strength BRI response
|
||||
* bit0
|
||||
* 0 - instructs bluetooth firmware to use default values
|
||||
* 1 - instructs bluetooth firmware to override default values
|
||||
* bit3:1
|
||||
* Reserved
|
||||
* bit7:4
|
||||
* DSBR override values (only if bit0 is set. Default value is 0xF
|
||||
* bit31:7
|
||||
* Reserved
|
||||
* Expected values for dsbr field:
|
||||
* 1. 0xF1 - indicates that the resistor on board is 33 Ohm
|
||||
* 2. 0x00 or 0xB1 - indicates that the resistor on board is 10 Ohm
|
||||
* 3. Non existing UEFI variable or invalid (none of the above) - indicates
|
||||
* that the resistor on board is 10 Ohm
|
||||
* Even if uefi variable is not present, driver shall send 0xfc0a command to
|
||||
* firmware to use default values.
|
||||
*
|
||||
*/
|
||||
static int btintel_uefi_get_dsbr(u32 *dsbr_var)
|
||||
{
|
||||
struct btintel_dsbr {
|
||||
u8 header;
|
||||
u32 dsbr;
|
||||
} __packed data;
|
||||
|
||||
efi_status_t status;
|
||||
unsigned long data_size = 0;
|
||||
efi_guid_t guid = EFI_GUID(0xe65d8884, 0xd4af, 0x4b20, 0x8d, 0x03,
|
||||
0x77, 0x2e, 0xcc, 0x3d, 0xa5, 0x31);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_EFI))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
status = efi.get_variable(BTINTEL_EFI_DSBR, &guid, NULL, &data_size,
|
||||
NULL);
|
||||
|
||||
if (status != EFI_BUFFER_TOO_SMALL || !data_size)
|
||||
return -EIO;
|
||||
|
||||
status = efi.get_variable(BTINTEL_EFI_DSBR, &guid, NULL, &data_size,
|
||||
&data);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
return -ENXIO;
|
||||
|
||||
*dsbr_var = data.dsbr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver)
|
||||
{
|
||||
struct btintel_dsbr_cmd {
|
||||
u8 enable;
|
||||
u8 dsbr;
|
||||
} __packed;
|
||||
|
||||
struct btintel_dsbr_cmd cmd;
|
||||
struct sk_buff *skb;
|
||||
u8 status;
|
||||
u32 dsbr;
|
||||
bool apply_dsbr;
|
||||
int err;
|
||||
|
||||
/* DSBR command needs to be sent for BlazarI + B0 step product after
|
||||
* downloading IML image.
|
||||
*/
|
||||
apply_dsbr = (ver->img_type == BTINTEL_IMG_IML &&
|
||||
((ver->cnvi_top & 0xfff) == BTINTEL_CNVI_BLAZARI) &&
|
||||
INTEL_CNVX_TOP_STEP(ver->cnvi_top) == 0x01);
|
||||
|
||||
if (!apply_dsbr)
|
||||
return 0;
|
||||
|
||||
dsbr = 0;
|
||||
err = btintel_uefi_get_dsbr(&dsbr);
|
||||
if (err < 0)
|
||||
bt_dev_dbg(hdev, "Error reading efi: %ls (%d)",
|
||||
BTINTEL_EFI_DSBR, err);
|
||||
|
||||
cmd.enable = dsbr & BIT(0);
|
||||
cmd.dsbr = dsbr >> 4 & 0xF;
|
||||
|
||||
bt_dev_info(hdev, "dsbr: enable: 0x%2.2x value: 0x%2.2x", cmd.enable,
|
||||
cmd.dsbr);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc0a, sizeof(cmd), &cmd, HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
return -bt_to_errno(PTR_ERR(skb));
|
||||
|
||||
status = skb->data[0];
|
||||
kfree_skb(skb);
|
||||
|
||||
if (status)
|
||||
return -bt_to_errno(status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
|
||||
struct intel_version_tlv *ver)
|
||||
{
|
||||
|
@ -2650,6 +2767,13 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* set drive strength of BRI response */
|
||||
err = btintel_set_dsbr(hdev, ver);
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "Failed to send dsbr command (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* If image type returned is BTINTEL_IMG_IML, then controller supports
|
||||
* intermediate loader image
|
||||
*/
|
||||
|
|
|
@ -449,6 +449,23 @@ static bool ps_wakeup(struct btnxpuart_dev *nxpdev)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void ps_cleanup(struct btnxpuart_dev *nxpdev)
|
||||
{
|
||||
struct ps_data *psdata = &nxpdev->psdata;
|
||||
u8 ps_state;
|
||||
|
||||
mutex_lock(&psdata->ps_lock);
|
||||
ps_state = psdata->ps_state;
|
||||
mutex_unlock(&psdata->ps_lock);
|
||||
|
||||
if (ps_state != PS_STATE_AWAKE)
|
||||
ps_control(psdata->hdev, PS_STATE_AWAKE);
|
||||
|
||||
ps_cancel_timer(nxpdev);
|
||||
cancel_work_sync(&psdata->work);
|
||||
mutex_destroy(&psdata->ps_lock);
|
||||
}
|
||||
|
||||
static int send_ps_cmd(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
|
||||
|
@ -1363,7 +1380,6 @@ static int btnxpuart_close(struct hci_dev *hdev)
|
|||
{
|
||||
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
|
||||
|
||||
ps_wakeup(nxpdev);
|
||||
serdev_device_close(nxpdev->serdev);
|
||||
skb_queue_purge(&nxpdev->txq);
|
||||
if (!IS_ERR_OR_NULL(nxpdev->rx_skb)) {
|
||||
|
@ -1516,8 +1532,8 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
|
|||
nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
|
||||
nxp_set_baudrate_cmd(hdev, NULL);
|
||||
}
|
||||
ps_cancel_timer(nxpdev);
|
||||
}
|
||||
ps_cleanup(nxpdev);
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
}
|
||||
|
|
|
@ -2406,10 +2406,16 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
|
|||
/* To avoid a potential race with hci_unregister_dev. */
|
||||
hci_dev_hold(hdev);
|
||||
|
||||
if (action == PM_SUSPEND_PREPARE)
|
||||
switch (action) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
case PM_SUSPEND_PREPARE:
|
||||
ret = hci_suspend_dev(hdev);
|
||||
else if (action == PM_POST_SUSPEND)
|
||||
break;
|
||||
case PM_POST_HIBERNATION:
|
||||
case PM_POST_SUSPEND:
|
||||
ret = hci_resume_dev(hdev);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
bt_dev_err(hdev, "Suspend notifier action (%lu) failed: %d",
|
||||
|
|
Loading…
Reference in a new issue