Skip to content

Commit

Permalink
Merge tag 'for-net-next-2023-08-11' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/bluetooth/bluetooth-next

bluetooth-next pull request for net-next:

 - Add new VID/PID for Mediatek MT7922
 - Add support multiple BIS/BIG
 - Add support for Intel Gale Peak
 - Add support for Qualcomm WCN3988
 - Add support for BT_PKT_STATUS for ISO sockets
 - Various fixes for experimental ISO support
 - Load FW v2 for RTL8852C
 - Add support for NXP AW693 chipset
 - Add support for Mediatek MT2925
  • Loading branch information
davem330 committed Aug 13, 2023
2 parents 2f4503f + b5793de commit 3d38293
Show file tree
Hide file tree
Showing 41 changed files with 2,370 additions and 1,002 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ properties:
- qcom,qca2066-bt
- qcom,qca6174-bt
- qcom,qca9377-bt
- qcom,wcn3988-bt
- qcom,wcn3990-bt
- qcom,wcn3991-bt
- qcom,wcn3998-bt
Expand Down Expand Up @@ -111,6 +112,7 @@ allOf:
compatible:
contains:
enum:
- qcom,wcn3988-bt
- qcom,wcn3990-bt
- qcom,wcn3991-bt
- qcom,wcn3998-bt
Expand Down
5 changes: 5 additions & 0 deletions drivers/bluetooth/btbcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define BDADDR_BCM20702A1 (&(bdaddr_t) {{0x00, 0x00, 0xa0, 0x02, 0x70, 0x20}})
#define BDADDR_BCM2076B1 (&(bdaddr_t) {{0x79, 0x56, 0x00, 0xa0, 0x76, 0x20}})
#define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}})
#define BDADDR_BCM43430A1 (&(bdaddr_t) {{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}})
#define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}})
#define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}})
#define BDADDR_BCM4334B0 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb0, 0x34, 0x43}})
Expand Down Expand Up @@ -115,6 +116,9 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
*
* The address 43:43:A0:12:1F:AC indicates a BCM43430A0 controller
* with no configured address.
*
* The address AA:AA:AA:AA:AA:AA indicates a BCM43430A1 controller
* with no configured address.
*/
if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) ||
!bacmp(&bda->bdaddr, BDADDR_BCM20702A1) ||
Expand All @@ -124,6 +128,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
!bacmp(&bda->bdaddr, BDADDR_BCM4334B0) ||
!bacmp(&bda->bdaddr, BDADDR_BCM4345C5) ||
!bacmp(&bda->bdaddr, BDADDR_BCM43430A0) ||
!bacmp(&bda->bdaddr, BDADDR_BCM43430A1) ||
!bacmp(&bda->bdaddr, BDADDR_BCM43341B)) {
/* Try falling back to BDADDR EFI variable */
if (btbcm_set_bdaddr_from_efi(hdev) != 0) {
Expand Down
198 changes: 198 additions & 0 deletions drivers/bluetooth/btintel.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/firmware.h>
#include <linux/regmap.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <asm/unaligned.h>

#include <net/bluetooth/bluetooth.h>
Expand All @@ -27,6 +28,11 @@

#define BTINTEL_PPAG_NAME "PPAG"

enum {
DSM_SET_WDISABLE2_DELAY = 1,
DSM_SET_RESET_METHOD = 3,
};

/* structure to store the PPAG data read from ACPI table */
struct btintel_ppag {
u32 domain;
Expand All @@ -49,6 +55,10 @@ static struct {
u32 fw_build_num;
} coredump_info;

static const guid_t btintel_guid_dsm =
GUID_INIT(0xaa10f4e0, 0x81ac, 0x4233,
0xab, 0xf6, 0x3b, 0x2a, 0xc5, 0x0e, 0x28, 0xd9);

int btintel_check_bdaddr(struct hci_dev *hdev)
{
struct hci_rp_read_bd_addr *bda;
Expand Down Expand Up @@ -470,6 +480,7 @@ static int btintel_version_info_tlv(struct hci_dev *hdev,
case 0x18: /* Slr */
case 0x19: /* Slr-F */
case 0x1b: /* Mgr */
case 0x1c: /* Gale Peak (GaP) */
break;
default:
bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
Expand Down Expand Up @@ -2444,6 +2455,116 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver
kfree_skb(skb);
}

static int btintel_acpi_reset_method(struct hci_dev *hdev)
{
int ret = 0;
acpi_status status;
union acpi_object *p, *ref;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };

status = acpi_evaluate_object(ACPI_HANDLE(GET_HCIDEV_DEV(hdev)), "_PRR", NULL, &buffer);
if (ACPI_FAILURE(status)) {
bt_dev_err(hdev, "Failed to run _PRR method");
ret = -ENODEV;
return ret;
}
p = buffer.pointer;

if (p->package.count != 1 || p->type != ACPI_TYPE_PACKAGE) {
bt_dev_err(hdev, "Invalid arguments");
ret = -EINVAL;
goto exit_on_error;
}

ref = &p->package.elements[0];
if (ref->type != ACPI_TYPE_LOCAL_REFERENCE) {
bt_dev_err(hdev, "Invalid object type: 0x%x", ref->type);
ret = -EINVAL;
goto exit_on_error;
}

status = acpi_evaluate_object(ref->reference.handle, "_RST", NULL, NULL);
if (ACPI_FAILURE(status)) {
bt_dev_err(hdev, "Failed to run_RST method");
ret = -ENODEV;
goto exit_on_error;
}

exit_on_error:
kfree(buffer.pointer);
return ret;
}

static void btintel_set_dsm_reset_method(struct hci_dev *hdev,
struct intel_version_tlv *ver_tlv)
{
struct btintel_data *data = hci_get_priv(hdev);
acpi_handle handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev));
u8 reset_payload[4] = {0x01, 0x00, 0x01, 0x00};
union acpi_object *obj, argv4;
enum {
RESET_TYPE_WDISABLE2,
RESET_TYPE_VSEC
};

handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev));

if (!handle) {
bt_dev_dbg(hdev, "No support for bluetooth device in ACPI firmware");
return;
}

if (!acpi_has_method(handle, "_PRR")) {
bt_dev_err(hdev, "No support for _PRR ACPI method");
return;
}

switch (ver_tlv->cnvi_top & 0xfff) {
case 0x910: /* GalePeak2 */
reset_payload[2] = RESET_TYPE_VSEC;
break;
default:
/* WDISABLE2 is the default reset method */
reset_payload[2] = RESET_TYPE_WDISABLE2;

if (!acpi_check_dsm(handle, &btintel_guid_dsm, 0,
BIT(DSM_SET_WDISABLE2_DELAY))) {
bt_dev_err(hdev, "No dsm support to set reset delay");
return;
}
argv4.integer.type = ACPI_TYPE_INTEGER;
/* delay required to toggle BT power */
argv4.integer.value = 160;
obj = acpi_evaluate_dsm(handle, &btintel_guid_dsm, 0,
DSM_SET_WDISABLE2_DELAY, &argv4);
if (!obj) {
bt_dev_err(hdev, "Failed to call dsm to set reset delay");
return;
}
ACPI_FREE(obj);
}

bt_dev_info(hdev, "DSM reset method type: 0x%02x", reset_payload[2]);

if (!acpi_check_dsm(handle, &btintel_guid_dsm, 0,
DSM_SET_RESET_METHOD)) {
bt_dev_warn(hdev, "No support for dsm to set reset method");
return;
}
argv4.buffer.type = ACPI_TYPE_BUFFER;
argv4.buffer.length = sizeof(reset_payload);
argv4.buffer.pointer = reset_payload;

obj = acpi_evaluate_dsm(handle, &btintel_guid_dsm, 0,
DSM_SET_RESET_METHOD, &argv4);
if (!obj) {
bt_dev_err(hdev, "Failed to call dsm to set reset method");
return;
}
ACPI_FREE(obj);
data->acpi_reset_method = btintel_acpi_reset_method;
}

static int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
struct intel_version_tlv *ver)
{
Expand Down Expand Up @@ -2528,6 +2649,7 @@ static void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant)
case 0x18:
case 0x19:
case 0x1b:
case 0x1c:
hci_set_msft_opcode(hdev, 0xFC1E);
break;
default:
Expand Down Expand Up @@ -2742,6 +2864,7 @@ static int btintel_setup_combined(struct hci_dev *hdev)
case 0x18:
case 0x19:
case 0x1b:
case 0x1c:
/* Display version information of TLV type */
btintel_version_info_tlv(hdev, &ver_tlv);

Expand All @@ -2757,6 +2880,7 @@ static int btintel_setup_combined(struct hci_dev *hdev)
/* Setup MSFT Extension support */
btintel_set_msft_opcode(hdev,
INTEL_HW_VARIANT(ver_tlv.cnvi_bt));
btintel_set_dsm_reset_method(hdev, &ver_tlv);

err = btintel_bootloader_setup_tlv(hdev, &ver_tlv);
btintel_register_devcoredump_support(hdev);
Expand Down Expand Up @@ -2824,6 +2948,80 @@ int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name)
}
EXPORT_SYMBOL_GPL(btintel_configure_setup);

static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
{
struct intel_tlv *tlv = (void *)&skb->data[5];

/* The first event is always an event type TLV */
if (tlv->type != INTEL_TLV_TYPE_ID)
goto recv_frame;

switch (tlv->val[0]) {
case INTEL_TLV_SYSTEM_EXCEPTION:
case INTEL_TLV_FATAL_EXCEPTION:
case INTEL_TLV_DEBUG_EXCEPTION:
case INTEL_TLV_TEST_EXCEPTION:
/* Generate devcoredump from exception */
if (!hci_devcd_init(hdev, skb->len)) {
hci_devcd_append(hdev, skb);
hci_devcd_complete(hdev);
} else {
bt_dev_err(hdev, "Failed to generate devcoredump");
kfree_skb(skb);
}
return 0;
default:
bt_dev_err(hdev, "Invalid exception type %02X", tlv->val[0]);
}

recv_frame:
return hci_recv_frame(hdev, skb);
}

int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (void *)skb->data;
const char diagnostics_hdr[] = { 0x87, 0x80, 0x03 };

if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff &&
hdr->plen > 0) {
const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1;
unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1;

if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
switch (skb->data[2]) {
case 0x02:
/* When switching to the operational firmware
* the device sends a vendor specific event
* indicating that the bootup completed.
*/
btintel_bootup(hdev, ptr, len);
break;
case 0x06:
/* When the firmware loading completes the
* device sends out a vendor specific event
* indicating the result of the firmware
* loading.
*/
btintel_secure_send_result(hdev, ptr, len);
break;
}
}

/* Handle all diagnostics events separately. May still call
* hci_recv_frame.
*/
if (len >= sizeof(diagnostics_hdr) &&
memcmp(&skb->data[2], diagnostics_hdr,
sizeof(diagnostics_hdr)) == 0) {
return btintel_diagnostics(hdev, skb);
}
}

return hci_recv_frame(hdev, skb);
}
EXPORT_SYMBOL_GPL(btintel_recv_event);

void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len)
{
const struct intel_bootup *evt = ptr;
Expand Down
3 changes: 3 additions & 0 deletions drivers/bluetooth/btintel.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,14 @@ enum {
INTEL_BROKEN_SHUTDOWN_LED,
INTEL_ROM_LEGACY,
INTEL_ROM_LEGACY_NO_WBS_SUPPORT,
INTEL_ACPI_RESET_ACTIVE,

__INTEL_NUM_FLAGS,
};

struct btintel_data {
DECLARE_BITMAP(flags, __INTEL_NUM_FLAGS);
int (*acpi_reset_method)(struct hci_dev *hdev);
};

#define btintel_set_flag(hdev, nr) \
Expand Down Expand Up @@ -220,6 +222,7 @@ int btintel_read_boot_params(struct hci_dev *hdev,
int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver,
const struct firmware *fw, u32 *boot_param);
int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name);
int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb);
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);
Expand Down
Loading

0 comments on commit 3d38293

Please sign in to comment.