Message ID | 20230313151549.15791-1-kiran.k@intel.com |
---|---|
State | Superseded |
Headers | show |
Series | [v1] Bluetooth: btintel: Add support to reset bluetooth via ACPI DSM | expand |
This is automated email and please do not reply to this email! Dear submitter, Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series: PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=729488 ---Test result--- Test Summary: CheckPatch PASS 1.10 seconds GitLint PASS 0.31 seconds SubjectPrefix PASS 0.10 seconds BuildKernel PASS 31.68 seconds CheckAllWarning PASS 35.22 seconds CheckSparse PASS 38.86 seconds CheckSmatch PASS 108.73 seconds BuildKernel32 PASS 30.72 seconds TestRunnerSetup PASS 440.17 seconds TestRunner_l2cap-tester PASS 17.12 seconds TestRunner_iso-tester PASS 16.62 seconds TestRunner_bnep-tester PASS 5.35 seconds TestRunner_mgmt-tester PASS 107.79 seconds TestRunner_rfcomm-tester PASS 8.54 seconds TestRunner_sco-tester PASS 7.85 seconds TestRunner_ioctl-tester PASS 9.34 seconds TestRunner_mesh-tester PASS 6.87 seconds TestRunner_smp-tester PASS 7.85 seconds TestRunner_userchan-tester PASS 5.59 seconds IncrementalBuild PASS 28.02 seconds --- Regards, Linux Bluetooth
Hi Kiran, Thank you for the patch! Yet something to improve: [auto build test ERROR on bluetooth-next/master] [also build test ERROR on linus/master v6.3-rc2 next-20230310] [cannot apply to bluetooth/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Kiran-K/Bluetooth-btintel-Add-support-to-reset-bluetooth-via-ACPI-DSM/20230313-230800 base: https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master patch link: https://lore.kernel.org/r/20230313151549.15791-1-kiran.k%40intel.com patch subject: [PATCH v1] Bluetooth: btintel: Add support to reset bluetooth via ACPI DSM config: hexagon-randconfig-r045-20230313 (https://download.01.org/0day-ci/archive/20230314/202303140618.ncRRCBV2-lkp@intel.com/config) compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project 67409911353323ca5edf2049ef0df54132fa1ca7) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/6a89221ddaa7b13fa1da2d345e61b2bf8efd5a87 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Kiran-K/Bluetooth-btintel-Add-support-to-reset-bluetooth-via-ACPI-DSM/20230313-230800 git checkout 6a89221ddaa7b13fa1da2d345e61b2bf8efd5a87 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/bluetooth/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202303140618.ncRRCBV2-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from drivers/bluetooth/btintel.c:11: In file included from include/linux/regmap.h:20: In file included from include/linux/iopoll.h:14: In file included from include/linux/io.h:13: In file included from arch/hexagon/include/asm/io.h:334: include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] val = __raw_readb(PCI_IOBASE + addr); ~~~~~~~~~~ ^ include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr)); ~~~~~~~~~~ ^ include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu' #define __le16_to_cpu(x) ((__force __u16)(__le16)(x)) ^ In file included from drivers/bluetooth/btintel.c:11: In file included from include/linux/regmap.h:20: In file included from include/linux/iopoll.h:14: In file included from include/linux/io.h:13: In file included from arch/hexagon/include/asm/io.h:334: include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr)); ~~~~~~~~~~ ^ include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu' #define __le32_to_cpu(x) ((__force __u32)(__le32)(x)) ^ In file included from drivers/bluetooth/btintel.c:11: In file included from include/linux/regmap.h:20: In file included from include/linux/iopoll.h:14: In file included from include/linux/io.h:13: In file included from arch/hexagon/include/asm/io.h:334: include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] __raw_writeb(value, PCI_IOBASE + addr); ~~~~~~~~~~ ^ include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr); ~~~~~~~~~~ ^ include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr); ~~~~~~~~~~ ^ >> drivers/bluetooth/btintel.c:2450:7: error: call to undeclared function 'acpi_has_method'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] if (!acpi_has_method(handle, "_PRR")) { ^ drivers/bluetooth/btintel.c:2450:7: note: did you mean 'acpi_has_watchdog'? include/linux/acpi.h:1442:20: note: 'acpi_has_watchdog' declared here static inline bool acpi_has_watchdog(void) { return false; } ^ 6 warnings and 1 error generated. vim +/acpi_has_method +2450 drivers/bluetooth/btintel.c 2430 2431 static void btintel_set_dsm_reset_method(struct hci_dev *hdev, 2432 struct intel_version_tlv *ver_tlv) 2433 { 2434 struct btintel_data *data = hci_get_priv(hdev); 2435 acpi_handle handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev)); 2436 u8 reset_payload[4] = {0x01, 0x00, 0x01, 0x00}; 2437 union acpi_object *obj, argv4; 2438 enum { 2439 RESET_TYPE_WDISABLE2, 2440 RESET_TYPE_VSEC 2441 }; 2442 2443 handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev)); 2444 2445 if (!handle) { 2446 bt_dev_dbg(hdev, "No support for bluetooth device in ACPI firmware"); 2447 return; 2448 } 2449 > 2450 if (!acpi_has_method(handle, "_PRR")) { 2451 bt_dev_err(hdev, "No support for _PRR ACPI method"); 2452 return; 2453 } 2454 2455 switch (ver_tlv->cnvi_top & 0xfff) { 2456 case 0x910: /* GalePeak2 */ 2457 reset_payload[2] = RESET_TYPE_VSEC; 2458 break; 2459 default: 2460 /* WDISABLE2 is the default reset method */ 2461 reset_payload[2] = RESET_TYPE_WDISABLE2; 2462 2463 if (!acpi_check_dsm(handle, &btintel_guid_dsm, 0, 2464 BIT(DSM_SET_WDISABLE2_DELAY))) { 2465 bt_dev_err(hdev, "No dsm support to set reset delay"); 2466 return; 2467 } 2468 argv4.integer.type = ACPI_TYPE_INTEGER; 2469 /* delay required to toggle BT power */ 2470 argv4.integer.value = 160; 2471 obj = acpi_evaluate_dsm(handle, &btintel_guid_dsm, 0, 2472 DSM_SET_WDISABLE2_DELAY, &argv4); 2473 if (!obj) { 2474 bt_dev_err(hdev, "Failed to call dsm to set reset delay"); 2475 return; 2476 } 2477 ACPI_FREE(obj); 2478 } 2479 2480 bt_dev_info(hdev, "DSM reset method type: 0x%02x", reset_payload[2]); 2481 2482 if (!acpi_check_dsm(handle, &btintel_guid_dsm, 0, 2483 DSM_SET_RESET_METHOD)) { 2484 bt_dev_warn(hdev, "No support for dsm to set reset method"); 2485 return; 2486 } 2487 argv4.buffer.type = ACPI_TYPE_BUFFER; 2488 argv4.buffer.length = sizeof(reset_payload); 2489 argv4.buffer.pointer = reset_payload; 2490 2491 obj = acpi_evaluate_dsm(handle, &btintel_guid_dsm, 0, 2492 DSM_SET_RESET_METHOD, &argv4); 2493 if (!obj) { 2494 bt_dev_err(hdev, "Failed to call dsm to set reset method"); 2495 return; 2496 } 2497 ACPI_FREE(obj); 2498 data->acpi_reset_method = btintel_acpi_reset_method; 2499 } 2500
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index af774688f1c0..a07b19cff9af 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -43,6 +43,15 @@ struct cmd_write_boot_params { u8 fw_build_yy; } __packed; +enum { + DSM_SET_WDISABLE2_DELAY = 1, + DSM_SET_RESET_METHOD = 3, +}; + +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; @@ -2379,6 +2388,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) { @@ -2691,6 +2810,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); break; diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 8fdb65b66315..8e7c51a78327 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -159,12 +159,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) \ diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 0c94cd7f4af3..be0b27dab033 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -838,10 +838,26 @@ static void btusb_intel_cmd_timeout(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); struct gpio_desc *reset_gpio = data->reset_gpio; + struct btintel_data *intel_data = hci_get_priv(hdev); if (++data->cmd_timeout_cnt < 5) return; + if (intel_data->acpi_reset_method) { + if (test_and_set_bit(INTEL_ACPI_RESET_ACTIVE, intel_data->flags)) { + bt_dev_err(hdev, "acpi: last reset failed ? Not resetting again"); + return; + } + + bt_dev_err(hdev, "Initiating acpi reset method"); + /* If ACPI reset method fails, lets try with legacy GPIO + * toggling + */ + if (!intel_data->acpi_reset_method(hdev)) { + return; + } + } + if (!reset_gpio) { btusb_reset(hdev); return;
New Intel platforms supports reset of Bluetooth device via ACPI DSM methods. The legacy reset mechanism via GPIO will be deprecated in future. This patch checks the platform support for reset methods and if supported uses the same instead of legacy GPIO toggling method. ACPI firmware supports two types of reset method based on NIC card. (Discrete or Integrated). 1. VSEC Type - Vendor Specific Extended Capability. Here BT_EN and BT_IF_SELECT lines are driven by a register in PCH cluster. This interface is supported on discrete BT solution. 2. WDISABLE2 - In this soluton, W_DISABLE2 pin in M.2 is connected to physical GPIO from PCH. The DSM interface shall toggle this to recover from error. Signed-off-by: Kiran K <kiran.k@intel.com> --- drivers/bluetooth/btintel.c | 120 ++++++++++++++++++++++++++++++++++++ drivers/bluetooth/btintel.h | 2 + drivers/bluetooth/btusb.c | 16 +++++ 3 files changed, 138 insertions(+)