Skip to content

Commit 05c200c

Browse files
kirankrishnappa-intelVudentz
authored andcommittedNov 14, 2024
Bluetooth: btintel_pcie: Add handshake between driver and firmware
The following handshake mechanism needs be followed after firmware download is completed to bring the firmware to running state. After firmware fragments of Operational image are downloaded and secure sends result of the image succeeds, 1. Driver sends HCI Intel reset with boot option #1 to switch FW image. 2. FW sends Alive GP[0] MSIx 3. Driver enables data path (doorbell 0x460 for RBDs, etc...) 4. Driver gets Bootup event from firmware 5. Driver performs D0 entry to device (WRITE to IPC_Sleep_Control =0x0) 6. FW sends Alive GP[0] MSIx 7. Device host interface is fully set for BT protocol stack operation. 8. Driver may optionally get debug event with ID 0x97 which can be dropped For Intermediate loadger image, all the above steps are applicable expcept Rust-for-Linux#5 and Rust-for-Linux#6. On HCI_OP_RESET, firmware raises alive interrupt. Driver needs to wait for it before passing control over to bluetooth stack. Co-developed-by: Devegowda Chandrashekar <chandrashekar.devegowda@intel.com> Signed-off-by: Devegowda Chandrashekar <chandrashekar.devegowda@intel.com> Signed-off-by: Kiran K <kiran.k@intel.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

File tree

4 files changed

+329
-12
lines changed

4 files changed

+329
-12
lines changed
 

‎drivers/bluetooth/btintel.c

+52-4
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,37 @@ static int btintel_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec)
18411841
return 0;
18421842
}
18431843

1844+
static int btintel_boot_wait_d0(struct hci_dev *hdev, ktime_t calltime,
1845+
int msec)
1846+
{
1847+
ktime_t delta, rettime;
1848+
unsigned long long duration;
1849+
int err;
1850+
1851+
bt_dev_info(hdev, "Waiting for device transition to d0");
1852+
1853+
err = btintel_wait_on_flag_timeout(hdev, INTEL_WAIT_FOR_D0,
1854+
TASK_INTERRUPTIBLE,
1855+
msecs_to_jiffies(msec));
1856+
if (err == -EINTR) {
1857+
bt_dev_err(hdev, "Device d0 move interrupted");
1858+
return -EINTR;
1859+
}
1860+
1861+
if (err) {
1862+
bt_dev_err(hdev, "Device d0 move timeout");
1863+
return -ETIMEDOUT;
1864+
}
1865+
1866+
rettime = ktime_get();
1867+
delta = ktime_sub(rettime, calltime);
1868+
duration = (unsigned long long)ktime_to_ns(delta) >> 10;
1869+
1870+
bt_dev_info(hdev, "Device moved to D0 in %llu usecs", duration);
1871+
1872+
return 0;
1873+
}
1874+
18441875
static int btintel_boot(struct hci_dev *hdev, u32 boot_addr)
18451876
{
18461877
ktime_t calltime;
@@ -1849,6 +1880,7 @@ static int btintel_boot(struct hci_dev *hdev, u32 boot_addr)
18491880
calltime = ktime_get();
18501881

18511882
btintel_set_flag(hdev, INTEL_BOOTING);
1883+
btintel_set_flag(hdev, INTEL_WAIT_FOR_D0);
18521884

18531885
err = btintel_send_intel_reset(hdev, boot_addr);
18541886
if (err) {
@@ -1861,13 +1893,28 @@ static int btintel_boot(struct hci_dev *hdev, u32 boot_addr)
18611893
* is done by the operational firmware sending bootup notification.
18621894
*
18631895
* Booting into operational firmware should not take longer than
1864-
* 1 second. However if that happens, then just fail the setup
1896+
* 5 second. However if that happens, then just fail the setup
18651897
* since something went wrong.
18661898
*/
1867-
err = btintel_boot_wait(hdev, calltime, 1000);
1868-
if (err == -ETIMEDOUT)
1899+
err = btintel_boot_wait(hdev, calltime, 5000);
1900+
if (err == -ETIMEDOUT) {
18691901
btintel_reset_to_bootloader(hdev);
1902+
goto exit_error;
1903+
}
18701904

1905+
if (hdev->bus == HCI_PCI) {
1906+
/* In case of PCIe, after receiving bootup event, driver performs
1907+
* D0 entry by writing 0 to sleep control register (check
1908+
* btintel_pcie_recv_event())
1909+
* Firmware acks with alive interrupt indicating host is full ready to
1910+
* perform BT operation. Lets wait here till INTEL_WAIT_FOR_D0
1911+
* bit is cleared.
1912+
*/
1913+
calltime = ktime_get();
1914+
err = btintel_boot_wait_d0(hdev, calltime, 2000);
1915+
}
1916+
1917+
exit_error:
18711918
return err;
18721919
}
18731920

@@ -3273,7 +3320,7 @@ int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name)
32733320
}
32743321
EXPORT_SYMBOL_GPL(btintel_configure_setup);
32753322

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

@@ -3302,6 +3349,7 @@ static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
33023349
recv_frame:
33033350
return hci_recv_frame(hdev, skb);
33043351
}
3352+
EXPORT_SYMBOL_GPL(btintel_diagnostics);
33053353

33063354
int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
33073355
{

‎drivers/bluetooth/btintel.h

+7
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ enum {
178178
INTEL_ROM_LEGACY,
179179
INTEL_ROM_LEGACY_NO_WBS_SUPPORT,
180180
INTEL_ACPI_RESET_ACTIVE,
181+
INTEL_WAIT_FOR_D0,
181182

182183
__INTEL_NUM_FLAGS,
183184
};
@@ -249,6 +250,7 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
249250
int btintel_shutdown_combined(struct hci_dev *hdev);
250251
void btintel_hw_error(struct hci_dev *hdev, u8 code);
251252
void btintel_print_fseq_info(struct hci_dev *hdev);
253+
int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb);
252254
#else
253255

254256
static inline int btintel_check_bdaddr(struct hci_dev *hdev)
@@ -382,4 +384,9 @@ static inline void btintel_hw_error(struct hci_dev *hdev, u8 code)
382384
static inline void btintel_print_fseq_info(struct hci_dev *hdev)
383385
{
384386
}
387+
388+
static inline int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
389+
{
390+
return -EOPNOTSUPP;
391+
}
385392
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.