Message ID | 20230203093332.4736-1-kiran.k@intel.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [v1] Bluetooth: btintel: Set Per Platform Antenna Gain(PPAG) | expand |
Context | Check | Description |
---|---|---|
tedd_an/pre-ci_am | success | Success |
tedd_an/CheckPatch | success | CheckPatch PASS |
tedd_an/GitLint | success | Gitlint PASS |
tedd_an/SubjectPrefix | success | Gitlint PASS |
tedd_an/BuildKernel | success | BuildKernel PASS |
tedd_an/CheckAllWarning | success | CheckAllWarning PASS |
tedd_an/CheckSparse | success | CheckSparse PASS |
tedd_an/CheckSmatch | success | CheckSparse PASS |
tedd_an/BuildKernel32 | success | BuildKernel32 PASS |
tedd_an/TestRunnerSetup | success | TestRunnerSetup PASS |
tedd_an/TestRunner_l2cap-tester | success | TestRunner PASS |
tedd_an/TestRunner_iso-tester | success | TestRunner PASS |
tedd_an/TestRunner_bnep-tester | success | TestRunner PASS |
tedd_an/TestRunner_mgmt-tester | success | TestRunner PASS |
tedd_an/TestRunner_rfcomm-tester | success | TestRunner PASS |
tedd_an/TestRunner_sco-tester | success | TestRunner PASS |
tedd_an/TestRunner_ioctl-tester | success | TestRunner PASS |
tedd_an/TestRunner_mesh-tester | success | TestRunner PASS |
tedd_an/TestRunner_smp-tester | success | TestRunner PASS |
tedd_an/TestRunner_userchan-tester | success | TestRunner PASS |
tedd_an/IncrementalBuild | success | Incremental Build PASS |
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=718490 ---Test result--- Test Summary: CheckPatch PASS 1.11 seconds GitLint PASS 0.29 seconds SubjectPrefix PASS 0.09 seconds BuildKernel PASS 29.78 seconds CheckAllWarning PASS 31.18 seconds CheckSparse PASS 36.11 seconds CheckSmatch PASS 95.28 seconds BuildKernel32 PASS 27.59 seconds TestRunnerSetup PASS 390.39 seconds TestRunner_l2cap-tester PASS 15.62 seconds TestRunner_iso-tester PASS 15.92 seconds TestRunner_bnep-tester PASS 5.16 seconds TestRunner_mgmt-tester PASS 104.89 seconds TestRunner_rfcomm-tester PASS 8.49 seconds TestRunner_sco-tester PASS 7.94 seconds TestRunner_ioctl-tester PASS 8.92 seconds TestRunner_mesh-tester PASS 6.60 seconds TestRunner_smp-tester PASS 7.67 seconds TestRunner_userchan-tester PASS 5.43 seconds IncrementalBuild PASS 25.51 seconds --- Regards, Linux Bluetooth
Hi Kiran, Seema, On Fri, Feb 3, 2023 at 1:28 AM Kiran K <kiran.k@intel.com> wrote: > > From: Seema Sreemantha <seema.sreemantha@intel.com> > > Antenna gain is defined as the antenna’s ability to > increase the Tx power in a given direction. Intel > is certifying its products with fixed reference > antenna peak gain values (3/5dBi). The feature takes > into account the actual antenna gain, and increases > output power values, which results in a performance > improvement. > > After firmware download is completed, driver reads from > ACPI table and configures PPAG as required. ACPI table > entry for PPAG is defined as below. > > Name (PPAG, Package (0x02) > { > 0x00000001, > Package (0x02) > { > 0x00000012, /* Bluetooth Domain */ > 0x00000001 /* 1 - Enable PPAG, 0 - Disable PPAG */ > } > }) > > btmon log: > > < HCI Command: Vendor (0x3f|0x0219) plen 12 > 00 00 00 00 00 00 00 00 00 00 00 00 > > HCI Event: Command Complete (0x0e) plen 4 > Vendor (0x3f|0x0219) ncmd 1 > Status: Success (0x00) It would have been better if you guys had added a decoder for it. > Signed-off-by: Kiran K <kiran.k@intel.com> > Signed-off-by: Seema Sreemantha <seema.sreemantha@intel.com> > --- > drivers/bluetooth/btintel.c | 114 ++++++++++++++++++++++++++++++++++++ > drivers/bluetooth/btintel.h | 13 ++++ > 2 files changed, 127 insertions(+) > > diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c > index d4e2cb9a4eb4..4d6d0dc10caa 100644 > --- a/drivers/bluetooth/btintel.c > +++ b/drivers/bluetooth/btintel.c > @@ -9,6 +9,7 @@ > #include <linux/module.h> > #include <linux/firmware.h> > #include <linux/regmap.h> > +#include <linux/acpi.h> > #include <asm/unaligned.h> > > #include <net/bluetooth/bluetooth.h> > @@ -24,6 +25,9 @@ > #define ECDSA_OFFSET 644 > #define ECDSA_HEADER_LEN 320 > > +#define BTINTEL_PPAG_NAME "PPAG" > +#define BTINTEL_PPAG_PREFIX "\\_SB_.PCI0.XHCI.RHUB" > + > #define CMD_WRITE_BOOT_PARAMS 0xfc0e > struct cmd_write_boot_params { > __le32 boot_addr; > @@ -1278,6 +1282,63 @@ static int btintel_read_debug_features(struct hci_dev *hdev, > return 0; > } > > +static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data, > + void **ret) > +{ > + acpi_status status; > + size_t len; > + struct btintel_ppag *ppag; You can probably just assign ppag = data above; > + union acpi_object *p, *elements; > + struct acpi_buffer string = {ACPI_ALLOCATE_BUFFER, NULL}; > + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; > + struct hci_dev *hdev = ((struct btintel_ppag *)data)->hdev; Then use hdev = ppga->hdev > + > + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); > + if (ACPI_FAILURE(status)) { > + bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status)); > + return status; > + } > + > + if (strncmp(BTINTEL_PPAG_PREFIX, string.pointer, > + strlen(BTINTEL_PPAG_PREFIX))) { > + kfree(string.pointer); > + return AE_OK; > + } > + > + len = strlen(string.pointer); > + if (strncmp((char *)string.pointer + len - 4, BTINTEL_PPAG_NAME, 4)) { > + kfree(string.pointer); > + return AE_OK; > + } > + kfree(string.pointer); > + > + status = acpi_evaluate_object(handle, NULL, NULL, &buffer); > + if (ACPI_FAILURE(status)) { > + bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status)); > + return status; > + } > + > + p = buffer.pointer; > + ppag = (struct btintel_ppag *)data; > + > + if (p->type != ACPI_TYPE_PACKAGE || p->package.count != 2) { > + kfree(buffer.pointer); > + bt_dev_warn(hdev, "Invalid object type: %d or package count: %d", > + p->type, p->package.count); > + return AE_ERROR; > + } > + > + elements = p->package.elements; > + > + /* PPAG table is located at element[1] */ > + p = &elements[1]; > + > + ppag->domain = (u32)p->package.elements[0].integer.value; > + ppag->mode = (u32)p->package.elements[1].integer.value; > + kfree(buffer.pointer); > + return AE_CTRL_TERMINATE; > +} > + > static int btintel_set_debug_features(struct hci_dev *hdev, > const struct intel_debug_features *features) > { > @@ -2251,6 +2312,56 @@ static int btintel_configure_offload(struct hci_dev *hdev) > return err; > } > > +static int btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver) > +{ > + acpi_status status; > + struct btintel_ppag ppag; > + struct sk_buff *skb; > + struct btintel_loc_aware_reg ppag_cmd; > + > + /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */ > + switch (ver->cnvr_top & 0xFFF) { > + case 0x504: /* Hrp2 */ > + case 0x202: /* Jfp2 */ > + case 0x201: /* Jfp1 */ > + return 0; > + } > + > + memset(&ppag, 0, sizeof(ppag)); > + > + ppag.hdev = hdev; > + status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, > + ACPI_UINT32_MAX, NULL, > + btintel_ppag_callback, &ppag, NULL); > + > + if (ACPI_FAILURE(status)) { > + bt_dev_warn(hdev, "PPAG: ACPI Failure: %s", acpi_format_exception(status)); Shouldn't we consider it ok if the ACPI doesn't have an entry? I mean it should be possible to plug a new controller in an old laptop that possibly doesn't have this entry, right? > + return -1; > + } > + > + if (ppag.domain != 0x12) { > + bt_dev_warn(hdev, "PPAG-BT Domain disabled"); > + return -1; > + } > + > + /* PPAG mode, BIT0 = 0 Disabled, BIT0 = 1 Enabled */ > + if (!(ppag.mode & BIT(0))) { > + bt_dev_dbg(hdev, "PPAG disabled"); > + return 0; > + } > + > + ppag_cmd.mcc = 0; > + ppag_cmd.sel = 0; /* 0 - Operational, 1 - Disable, 2 - Testing mode */ > + ppag_cmd.delta = 0; > + skb = __hci_cmd_sync(hdev, 0xfe19, sizeof(ppag_cmd), &ppag_cmd, HCI_CMD_TIMEOUT); > + if (IS_ERR(skb)) { > + bt_dev_warn(hdev, "Failed to send PPAG Enable (%ld)", PTR_ERR(skb)); > + return PTR_ERR(skb); > + } > + kfree_skb(skb); > + return 0; > +} > + > static int btintel_bootloader_setup_tlv(struct hci_dev *hdev, > struct intel_version_tlv *ver) > { > @@ -2297,6 +2408,9 @@ static int btintel_bootloader_setup_tlv(struct hci_dev *hdev, > > hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); > > + /* Set PPAG feature */ > + btintel_set_ppag(hdev, ver); Looks like you are not using the return above which I guess is fine since this step can be considered optional but I'd document it as such and probably make btintel_set_ppag return void as it shouldn't be considered as an error if it fails. > + > /* Read the Intel version information after loading the FW */ > err = btintel_read_version_tlv(hdev, &new_ver); > if (err) > diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h > index e0060e58573c..af508a0e0c42 100644 > --- a/drivers/bluetooth/btintel.h > +++ b/drivers/bluetooth/btintel.h > @@ -137,6 +137,19 @@ struct intel_offload_use_cases { > __u8 preset[8]; > } __packed; > > +/* structure to store the PPAG data read from ACPI table */ > +struct btintel_ppag { > + u32 domain; > + u32 mode; > + struct hci_dev *hdev; > +}; > + > +struct btintel_loc_aware_reg { > + u32 mcc; > + u32 sel; > + s32 delta; > +}; The above struct seems to be used as command data, in which case it should be __packed, also they shall probably use le32 since there is no guarantee we would be running in a system with the same byte order as the controller. > + > #define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8)) > #define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16)) > #define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff) > -- > 2.17.1 >
Hi Luiz, > -----Original Message----- > From: Luiz Augusto von Dentz <luiz.dentz@gmail.com> > Sent: Saturday, February 4, 2023 2:38 AM > To: K, Kiran <kiran.k@intel.com> > Cc: linux-bluetooth@vger.kernel.org; Srivatsa, Ravishankar > <ravishankar.srivatsa@intel.com>; Singh, Lokendra > <lokendra.singh@intel.com>; Tumkur Narayan, Chethan > <chethan.tumkur.narayan@intel.com>; Sreemantha, Seema > <seema.sreemantha@intel.com> > Subject: Re: [PATCH v1] Bluetooth: btintel: Set Per Platform Antenna > Gain(PPAG) > > Hi Kiran, Seema, > > On Fri, Feb 3, 2023 at 1:28 AM Kiran K <kiran.k@intel.com> wrote: > > > > From: Seema Sreemantha <seema.sreemantha@intel.com> > > > > Antenna gain is defined as the antenna’s ability to increase the Tx > > power in a given direction. Intel is certifying its products with > > fixed reference antenna peak gain values (3/5dBi). The feature takes > > into account the actual antenna gain, and increases output power > > values, which results in a performance improvement. > > > > After firmware download is completed, driver reads from ACPI table and > > configures PPAG as required. ACPI table entry for PPAG is defined as > > below. > > > > Name (PPAG, Package (0x02) > > { > > 0x00000001, > > Package (0x02) > > { > > 0x00000012, /* Bluetooth Domain */ > > 0x00000001 /* 1 - Enable PPAG, 0 - Disable PPAG */ > > } > > }) > > > > btmon log: > > > > < HCI Command: Vendor (0x3f|0x0219) plen 12 > > 00 00 00 00 00 00 00 00 00 00 00 00 > > > HCI Event: Command Complete (0x0e) plen 4 > > Vendor (0x3f|0x0219) ncmd 1 > > Status: Success (0x00) > > It would have been better if you guys had added a decoder for it. Ack. I will publish the patch for the same. > > > Signed-off-by: Kiran K <kiran.k@intel.com> > > Signed-off-by: Seema Sreemantha <seema.sreemantha@intel.com> > > --- > > drivers/bluetooth/btintel.c | 114 > > ++++++++++++++++++++++++++++++++++++ > > drivers/bluetooth/btintel.h | 13 ++++ > > 2 files changed, 127 insertions(+) > > > > diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c > > index d4e2cb9a4eb4..4d6d0dc10caa 100644 > > --- a/drivers/bluetooth/btintel.c > > +++ b/drivers/bluetooth/btintel.c > > @@ -9,6 +9,7 @@ > > #include <linux/module.h> > > #include <linux/firmware.h> > > #include <linux/regmap.h> > > +#include <linux/acpi.h> > > #include <asm/unaligned.h> > > > > #include <net/bluetooth/bluetooth.h> > > @@ -24,6 +25,9 @@ > > #define ECDSA_OFFSET 644 > > #define ECDSA_HEADER_LEN 320 > > > > +#define BTINTEL_PPAG_NAME "PPAG" > > +#define BTINTEL_PPAG_PREFIX "\\_SB_.PCI0.XHCI.RHUB" > > + > > #define CMD_WRITE_BOOT_PARAMS 0xfc0e struct > cmd_write_boot_params { > > __le32 boot_addr; > > @@ -1278,6 +1282,63 @@ static int btintel_read_debug_features(struct > hci_dev *hdev, > > return 0; > > } > > > > +static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void > *data, > > + void **ret) { > > + acpi_status status; > > + size_t len; > > + struct btintel_ppag *ppag; > > You can probably just assign ppag = data above; > > > + union acpi_object *p, *elements; > > + struct acpi_buffer string = {ACPI_ALLOCATE_BUFFER, NULL}; > > + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; > > + struct hci_dev *hdev = ((struct btintel_ppag *)data)->hdev; > > Then use hdev = ppga->hdev > Ack. > > + > > + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); > > + if (ACPI_FAILURE(status)) { > > + bt_dev_warn(hdev, "ACPI Failure: %s", > acpi_format_exception(status)); > > + return status; > > + } > > + > > + if (strncmp(BTINTEL_PPAG_PREFIX, string.pointer, > > + strlen(BTINTEL_PPAG_PREFIX))) { > > + kfree(string.pointer); > > + return AE_OK; > > + } > > + > > + len = strlen(string.pointer); > > + if (strncmp((char *)string.pointer + len - 4, BTINTEL_PPAG_NAME, 4)) { > > + kfree(string.pointer); > > + return AE_OK; > > + } > > + kfree(string.pointer); > > + > > + status = acpi_evaluate_object(handle, NULL, NULL, &buffer); > > + if (ACPI_FAILURE(status)) { > > + bt_dev_warn(hdev, "ACPI Failure: %s", > acpi_format_exception(status)); > > + return status; > > + } > > + > > + p = buffer.pointer; > > + ppag = (struct btintel_ppag *)data; > > + > > + if (p->type != ACPI_TYPE_PACKAGE || p->package.count != 2) { > > + kfree(buffer.pointer); > > + bt_dev_warn(hdev, "Invalid object type: %d or package count: > %d", > > + p->type, p->package.count); > > + return AE_ERROR; > > + } > > + > > + elements = p->package.elements; > > + > > + /* PPAG table is located at element[1] */ > > + p = &elements[1]; > > + > > + ppag->domain = (u32)p->package.elements[0].integer.value; > > + ppag->mode = (u32)p->package.elements[1].integer.value; > > + kfree(buffer.pointer); > > + return AE_CTRL_TERMINATE; > > +} > > + > > static int btintel_set_debug_features(struct hci_dev *hdev, > > const struct intel_debug_features > > *features) { @@ -2251,6 +2312,56 @@ static int > > btintel_configure_offload(struct hci_dev *hdev) > > return err; > > } > > > > +static int btintel_set_ppag(struct hci_dev *hdev, struct > > +intel_version_tlv *ver) { > > + acpi_status status; > > + struct btintel_ppag ppag; > > + struct sk_buff *skb; > > + struct btintel_loc_aware_reg ppag_cmd; > > + > > + /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */ > > + switch (ver->cnvr_top & 0xFFF) { > > + case 0x504: /* Hrp2 */ > > + case 0x202: /* Jfp2 */ > > + case 0x201: /* Jfp1 */ > > + return 0; > > + } > > + > > + memset(&ppag, 0, sizeof(ppag)); > > + > > + ppag.hdev = hdev; > > + status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, > > + ACPI_UINT32_MAX, NULL, > > + btintel_ppag_callback, &ppag, > > + NULL); > > + > > + if (ACPI_FAILURE(status)) { > > + bt_dev_warn(hdev, "PPAG: ACPI Failure: %s", > > + acpi_format_exception(status)); > > Shouldn't we consider it ok if the ACPI doesn't have an entry? I mean it > should be possible to plug a new controller in an old laptop that possibly > doesn't have this entry, right? > Ack. Older platform won't support this feature. > > + return -1; > > + } > > + > > + if (ppag.domain != 0x12) { > > + bt_dev_warn(hdev, "PPAG-BT Domain disabled"); > > + return -1; > > + } > > + > > + /* PPAG mode, BIT0 = 0 Disabled, BIT0 = 1 Enabled */ > > + if (!(ppag.mode & BIT(0))) { > > + bt_dev_dbg(hdev, "PPAG disabled"); > > + return 0; > > + } > > + > > + ppag_cmd.mcc = 0; > > + ppag_cmd.sel = 0; /* 0 - Operational, 1 - Disable, 2 - Testing mode */ > > + ppag_cmd.delta = 0; > > + skb = __hci_cmd_sync(hdev, 0xfe19, sizeof(ppag_cmd), &ppag_cmd, > HCI_CMD_TIMEOUT); > > + if (IS_ERR(skb)) { > > + bt_dev_warn(hdev, "Failed to send PPAG Enable (%ld)", > PTR_ERR(skb)); > > + return PTR_ERR(skb); > > + } > > + kfree_skb(skb); > > + return 0; > > +} > > + > > static int btintel_bootloader_setup_tlv(struct hci_dev *hdev, > > struct intel_version_tlv *ver) > > { @@ -2297,6 +2408,9 @@ static int btintel_bootloader_setup_tlv(struct > > hci_dev *hdev, > > > > hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); > > > > + /* Set PPAG feature */ > > + btintel_set_ppag(hdev, ver); > > Looks like you are not using the return above which I guess is fine since this > step can be considered optional but I'd document it as such and probably > make btintel_set_ppag return void as it shouldn't be considered as an error if > it fails. Ack. > > > + .... Thanks, Kiran
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index d4e2cb9a4eb4..4d6d0dc10caa 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/firmware.h> #include <linux/regmap.h> +#include <linux/acpi.h> #include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> @@ -24,6 +25,9 @@ #define ECDSA_OFFSET 644 #define ECDSA_HEADER_LEN 320 +#define BTINTEL_PPAG_NAME "PPAG" +#define BTINTEL_PPAG_PREFIX "\\_SB_.PCI0.XHCI.RHUB" + #define CMD_WRITE_BOOT_PARAMS 0xfc0e struct cmd_write_boot_params { __le32 boot_addr; @@ -1278,6 +1282,63 @@ static int btintel_read_debug_features(struct hci_dev *hdev, return 0; } +static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data, + void **ret) +{ + acpi_status status; + size_t len; + struct btintel_ppag *ppag; + union acpi_object *p, *elements; + struct acpi_buffer string = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct hci_dev *hdev = ((struct btintel_ppag *)data)->hdev; + + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + if (ACPI_FAILURE(status)) { + bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status)); + return status; + } + + if (strncmp(BTINTEL_PPAG_PREFIX, string.pointer, + strlen(BTINTEL_PPAG_PREFIX))) { + kfree(string.pointer); + return AE_OK; + } + + len = strlen(string.pointer); + if (strncmp((char *)string.pointer + len - 4, BTINTEL_PPAG_NAME, 4)) { + kfree(string.pointer); + return AE_OK; + } + kfree(string.pointer); + + status = acpi_evaluate_object(handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) { + bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status)); + return status; + } + + p = buffer.pointer; + ppag = (struct btintel_ppag *)data; + + if (p->type != ACPI_TYPE_PACKAGE || p->package.count != 2) { + kfree(buffer.pointer); + bt_dev_warn(hdev, "Invalid object type: %d or package count: %d", + p->type, p->package.count); + return AE_ERROR; + } + + elements = p->package.elements; + + /* PPAG table is located at element[1] */ + p = &elements[1]; + + ppag->domain = (u32)p->package.elements[0].integer.value; + ppag->mode = (u32)p->package.elements[1].integer.value; + kfree(buffer.pointer); + return AE_CTRL_TERMINATE; +} + static int btintel_set_debug_features(struct hci_dev *hdev, const struct intel_debug_features *features) { @@ -2251,6 +2312,56 @@ static int btintel_configure_offload(struct hci_dev *hdev) return err; } +static int btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver) +{ + acpi_status status; + struct btintel_ppag ppag; + struct sk_buff *skb; + struct btintel_loc_aware_reg ppag_cmd; + + /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */ + switch (ver->cnvr_top & 0xFFF) { + case 0x504: /* Hrp2 */ + case 0x202: /* Jfp2 */ + case 0x201: /* Jfp1 */ + return 0; + } + + memset(&ppag, 0, sizeof(ppag)); + + ppag.hdev = hdev; + status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, NULL, + btintel_ppag_callback, &ppag, NULL); + + if (ACPI_FAILURE(status)) { + bt_dev_warn(hdev, "PPAG: ACPI Failure: %s", acpi_format_exception(status)); + return -1; + } + + if (ppag.domain != 0x12) { + bt_dev_warn(hdev, "PPAG-BT Domain disabled"); + return -1; + } + + /* PPAG mode, BIT0 = 0 Disabled, BIT0 = 1 Enabled */ + if (!(ppag.mode & BIT(0))) { + bt_dev_dbg(hdev, "PPAG disabled"); + return 0; + } + + ppag_cmd.mcc = 0; + ppag_cmd.sel = 0; /* 0 - Operational, 1 - Disable, 2 - Testing mode */ + ppag_cmd.delta = 0; + skb = __hci_cmd_sync(hdev, 0xfe19, sizeof(ppag_cmd), &ppag_cmd, HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_warn(hdev, "Failed to send PPAG Enable (%ld)", PTR_ERR(skb)); + return PTR_ERR(skb); + } + kfree_skb(skb); + return 0; +} + static int btintel_bootloader_setup_tlv(struct hci_dev *hdev, struct intel_version_tlv *ver) { @@ -2297,6 +2408,9 @@ static int btintel_bootloader_setup_tlv(struct hci_dev *hdev, hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); + /* Set PPAG feature */ + btintel_set_ppag(hdev, ver); + /* Read the Intel version information after loading the FW */ err = btintel_read_version_tlv(hdev, &new_ver); if (err) diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index e0060e58573c..af508a0e0c42 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -137,6 +137,19 @@ struct intel_offload_use_cases { __u8 preset[8]; } __packed; +/* structure to store the PPAG data read from ACPI table */ +struct btintel_ppag { + u32 domain; + u32 mode; + struct hci_dev *hdev; +}; + +struct btintel_loc_aware_reg { + u32 mcc; + u32 sel; + s32 delta; +}; + #define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8)) #define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16)) #define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff)