Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v3 1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download
@ 2025-06-10 14:00 Kiran K
  2025-06-10 14:00 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Support Function level reset Kiran K
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Kiran K @ 2025-06-10 14:00 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: ravishankar.srivatsa, chethan.tumkur.narayan,
	chandrashekar.devegowda, aluvala.sai.teja, Kiran K

During firmware download, if an error occurs, interrupts must be
disabled, synchronized, and re-enabled before retrying the download.
This change ensures proper interrupt handling to prevent race
conditions.

Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
Signed-off-by: Kiran K <kiran.k@intel.com>
---
 drivers/bluetooth/btintel_pcie.c | 33 ++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index 563165c5efae..e1c688dd2d45 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -2033,6 +2033,28 @@ static void btintel_pcie_release_hdev(struct btintel_pcie_data *data)
 	data->hdev = NULL;
 }
 
+static void btintel_pcie_disable_interrupts(struct btintel_pcie_data *data)
+{
+	spin_lock(&data->irq_lock);
+	btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, data->fh_init_mask);
+	btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, data->hw_init_mask);
+	spin_unlock(&data->irq_lock);
+}
+
+static void btintel_pcie_enable_interrupts(struct btintel_pcie_data *data)
+{
+	spin_lock(&data->irq_lock);
+	btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, ~data->fh_init_mask);
+	btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, ~data->hw_init_mask);
+	spin_unlock(&data->irq_lock);
+}
+
+static void btintel_pcie_synchronize_irqs(struct btintel_pcie_data *data)
+{
+	for (int i = 0; i < data->alloc_vecs; i++)
+		synchronize_irq(data->msix_entries[i].vector);
+}
+
 static int btintel_pcie_setup_internal(struct hci_dev *hdev)
 {
 	struct btintel_pcie_data *data = hci_get_drvdata(hdev);
@@ -2152,6 +2174,8 @@ static int btintel_pcie_setup(struct hci_dev *hdev)
 		bt_dev_err(hdev, "Firmware download retry count: %d",
 			   fw_dl_retry);
 		btintel_pcie_dump_debug_registers(hdev);
+		btintel_pcie_disable_interrupts(data);
+		btintel_pcie_synchronize_irqs(data);
 		err = btintel_pcie_reset_bt(data);
 		if (err) {
 			bt_dev_err(hdev, "Failed to do shr reset: %d", err);
@@ -2159,6 +2183,7 @@ static int btintel_pcie_setup(struct hci_dev *hdev)
 		}
 		usleep_range(10000, 12000);
 		btintel_pcie_reset_ia(data);
+		btintel_pcie_enable_interrupts(data);
 		btintel_pcie_config_msix(data);
 		err = btintel_pcie_enable_bt(data);
 		if (err) {
@@ -2291,6 +2316,12 @@ static void btintel_pcie_remove(struct pci_dev *pdev)
 
 	data = pci_get_drvdata(pdev);
 
+	btintel_pcie_disable_interrupts(data);
+
+	btintel_pcie_synchronize_irqs(data);
+
+	flush_work(&data->rx_work);
+
 	btintel_pcie_reset_bt(data);
 	for (int i = 0; i < data->alloc_vecs; i++) {
 		struct msix_entry *msix_entry;
@@ -2303,8 +2334,6 @@ static void btintel_pcie_remove(struct pci_dev *pdev)
 
 	btintel_pcie_release_hdev(data);
 
-	flush_work(&data->rx_work);
-
 	destroy_workqueue(data->workqueue);
 
 	btintel_pcie_free(data);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 2/2] Bluetooth: btintel_pcie: Support Function level reset
  2025-06-10 14:00 [PATCH v3 1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download Kiran K
@ 2025-06-10 14:00 ` Kiran K
  2025-06-10 15:01   ` Paul Menzel
  2025-06-10 14:10 ` [v3,1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download bluez.test.bot
  2025-06-11 14:40 ` [PATCH v3 1/2] " patchwork-bot+bluetooth
  2 siblings, 1 reply; 7+ messages in thread
From: Kiran K @ 2025-06-10 14:00 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: ravishankar.srivatsa, chethan.tumkur.narayan,
	chandrashekar.devegowda, aluvala.sai.teja, Kiran K

From: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>

The driver supports Function Level Reset (FLR) to recover the controller
upon hardware exceptions or hci command timeouts. FLR is triggered only
when no prior reset has occurred within the retry window, with a maximum
of one FLR allowed within this window.

This patch is tested by,
echo 1 >  /sys/class/bluetooth/hciX/reset

Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
Signed-off-by: Kiran K <kiran.k@intel.com>
---
changes in v3:
- Fix typos, indentation issues
- Update commit message to include test command
- Keep the flr max retry to 1

 drivers/bluetooth/btintel_pcie.c | 226 ++++++++++++++++++++++++++++++-
 drivers/bluetooth/btintel_pcie.h |   4 +-
 2 files changed, 227 insertions(+), 3 deletions(-)

diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index e1c688dd2d45..87e4b3546c7a 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -41,6 +41,13 @@ static const struct pci_device_id btintel_pcie_table[] = {
 };
 MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
 
+struct btintel_pcie_dev_restart_data {
+	struct list_head list;
+	u8 restart_count;
+	time64_t last_error;
+	char name[];
+};
+
 /* Intel PCIe uses 4 bytes of HCI type instead of 1 byte BT SIG HCI type */
 #define BTINTEL_PCIE_HCI_TYPE_LEN	4
 #define BTINTEL_PCIE_HCI_CMD_PKT	0x00000001
@@ -62,6 +69,9 @@ MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
 #define BTINTEL_PCIE_TRIGGER_REASON_USER_TRIGGER	0x17A2
 #define BTINTEL_PCIE_TRIGGER_REASON_FW_ASSERT		0x1E61
 
+#define BTINTEL_PCIE_RESET_WINDOW_SECS		5
+#define BTINTEL_PCIE_FLR_MAX_RETRY	1
+
 /* Alive interrupt context */
 enum {
 	BTINTEL_PCIE_ROM,
@@ -99,6 +109,14 @@ struct btintel_pcie_dbgc_ctxt {
 	struct btintel_pcie_dbgc_ctxt_buf bufs[BTINTEL_PCIE_DBGC_BUFFER_COUNT];
 };
 
+struct btintel_pcie_removal {
+	struct pci_dev *pdev;
+	struct work_struct work;
+};
+
+static LIST_HEAD(btintel_pcie_restart_data_list);
+static DEFINE_SPINLOCK(btintel_pcie_restart_data_lock);
+
 /* This function initializes the memory for DBGC buffers and formats the
  * DBGC fragment which consists header info and DBGC buffer's LSB, MSB and
  * size as the payload
@@ -1932,6 +1950,9 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
 	u32 type;
 	u32 old_ctxt;
 
+	if (test_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags))
+		return -ENODEV;
+
 	/* Due to the fw limitation, the type header of the packet should be
 	 * 4 bytes unlike 1 byte for UART. In UART, the firmware can read
 	 * the first byte to get the packet type and redirect the rest of data
@@ -2192,9 +2213,196 @@ static int btintel_pcie_setup(struct hci_dev *hdev)
 		}
 		btintel_pcie_start_rx(data);
 	}
+
+	if (!err)
+		set_bit(BTINTEL_PCIE_SETUP_DONE, &data->flags);
 	return err;
 }
 
+static struct btintel_pcie_dev_restart_data *btintel_pcie_get_restart_data(struct pci_dev *pdev,
+									   struct device *dev)
+{
+	struct btintel_pcie_dev_restart_data *tmp, *data = NULL;
+	const char *name = pci_name(pdev);
+	struct hci_dev *hdev = to_hci_dev(dev);
+
+	spin_lock(&btintel_pcie_restart_data_lock);
+	list_for_each_entry(tmp, &btintel_pcie_restart_data_list, list) {
+		if (strcmp(tmp->name, name))
+			continue;
+		data = tmp;
+		break;
+	}
+	spin_unlock(&btintel_pcie_restart_data_lock);
+
+	if (data) {
+		bt_dev_dbg(hdev, "Found restart data for BDF: %s", data->name);
+		return data;
+	}
+
+	data = kzalloc(struct_size(data, name, strlen(name) + 1), GFP_ATOMIC);
+	if (!data)
+		return NULL;
+
+	strscpy_pad(data->name, name, strlen(name) + 1);
+	spin_lock(&btintel_pcie_restart_data_lock);
+	list_add_tail(&data->list, &btintel_pcie_restart_data_list);
+	spin_unlock(&btintel_pcie_restart_data_lock);
+
+	return data;
+}
+
+static void btintel_pcie_free_restart_list(void)
+{
+	struct btintel_pcie_dev_restart_data *tmp;
+
+	while ((tmp = list_first_entry_or_null(&btintel_pcie_restart_data_list,
+					       typeof(*tmp), list))) {
+		list_del(&tmp->list);
+		kfree(tmp);
+	}
+}
+
+static void btintel_pcie_inc_restart_count(struct pci_dev *pdev,
+					   struct device *dev)
+{
+	struct btintel_pcie_dev_restart_data *data;
+	struct hci_dev *hdev = to_hci_dev(dev);
+	time64_t retry_window;
+
+	data = btintel_pcie_get_restart_data(pdev, dev);
+	if (!data)
+		return;
+
+	retry_window = ktime_get_boottime_seconds() - data->last_error;
+	if (data->restart_count == 0) {
+		data->last_error = ktime_get_boottime_seconds();
+		data->restart_count++;
+		bt_dev_dbg(hdev, "First iteration initialise. last_error: %lld seconds restart_count: %d",
+			   data->last_error, data->restart_count);
+	} else if (retry_window < BTINTEL_PCIE_RESET_WINDOW_SECS &&
+		   data->restart_count <= BTINTEL_PCIE_FLR_MAX_RETRY) {
+		data->restart_count++;
+		bt_dev_dbg(hdev, "Flr triggered within the max retry time so increment the restart_count: %d",
+			   data->restart_count);
+	} else if (retry_window > BTINTEL_PCIE_RESET_WINDOW_SECS) {
+		data->last_error = 0;
+		data->restart_count = 0;
+		bt_dev_dbg(hdev, "Flr triggered out of the retry window, so reset counters");
+	}
+}
+
+static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data);
+
+static void btintel_pcie_removal_work(struct work_struct *wk)
+{
+	struct btintel_pcie_removal *removal =
+		container_of(wk, struct btintel_pcie_removal, work);
+	struct pci_dev *pdev = removal->pdev;
+	struct btintel_pcie_data *data;
+	int err;
+
+	pci_lock_rescan_remove();
+
+	if (!pdev->bus)
+		goto error;
+
+	data = pci_get_drvdata(pdev);
+
+	btintel_pcie_disable_interrupts(data);
+	btintel_pcie_synchronize_irqs(data);
+
+	flush_work(&data->rx_work);
+	flush_work(&data->hdev->dump.dump_rx);
+
+	bt_dev_dbg(data->hdev, "Release bluetooth interface");
+	btintel_pcie_release_hdev(data);
+
+	err = pci_reset_function(pdev);
+	if (err) {
+		BT_ERR("Failed resetting the pcie device (%d)", err);
+		goto error;
+	}
+
+	btintel_pcie_enable_interrupts(data);
+	btintel_pcie_config_msix(data);
+
+	err = btintel_pcie_enable_bt(data);
+	if (err) {
+		BT_ERR("Failed to enable bluetooth hardware after reset (%d)",
+		       err);
+		goto error;
+	}
+
+	btintel_pcie_reset_ia(data);
+	btintel_pcie_start_rx(data);
+	data->flags = 0;
+
+	err = btintel_pcie_setup_hdev(data);
+	if (err) {
+		BT_ERR("Failed registering hdev (%d)", err);
+		goto error;
+	}
+error:
+	pci_dev_put(pdev);
+	pci_unlock_rescan_remove();
+	kfree(removal);
+}
+
+static void btintel_pcie_reset(struct hci_dev *hdev)
+{
+	struct btintel_pcie_removal *removal;
+	struct btintel_pcie_data *data;
+
+	data = hci_get_drvdata(hdev);
+
+	if (!test_bit(BTINTEL_PCIE_SETUP_DONE, &data->flags))
+		return;
+
+	if (test_and_set_bit(BTINTEL_PCIE_RECOVERY_IN_PROGRESS, &data->flags))
+		return;
+
+	removal = kzalloc(sizeof(*removal), GFP_ATOMIC);
+	if (!removal)
+		return;
+
+	removal->pdev = data->pdev;
+	INIT_WORK(&removal->work, btintel_pcie_removal_work);
+	pci_dev_get(removal->pdev);
+	schedule_work(&removal->work);
+}
+
+static void btintel_pcie_hw_error(struct hci_dev *hdev, u8 code)
+{
+	struct  btintel_pcie_dev_restart_data *data;
+	struct btintel_pcie_data *dev_data = hci_get_drvdata(hdev);
+	struct pci_dev *pdev = dev_data->pdev;
+	time64_t retry_window;
+
+	if (code == 0x13) {
+		bt_dev_err(hdev, "Encountered top exception");
+		return;
+	}
+
+	data = btintel_pcie_get_restart_data(pdev, &hdev->dev);
+	if (!data)
+		return;
+
+	retry_window = ktime_get_boottime_seconds() - data->last_error;
+
+	if (retry_window < BTINTEL_PCIE_RESET_WINDOW_SECS &&
+	    data->restart_count >= BTINTEL_PCIE_FLR_MAX_RETRY) {
+		bt_dev_err(hdev, "Exhausted maximum: %d recovery attempts: %d",
+			   BTINTEL_PCIE_FLR_MAX_RETRY, data->restart_count);
+		bt_dev_dbg(hdev, "Boot time: %lld seconds first_flr at: %lld seconds restart_count: %d",
+			   ktime_get_boottime_seconds(), data->last_error,
+			   data->restart_count);
+		return;
+	}
+	btintel_pcie_inc_restart_count(pdev, &hdev->dev);
+	btintel_pcie_reset(hdev);
+}
+
 static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
 {
 	int err;
@@ -2216,9 +2424,10 @@ static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
 	hdev->send = btintel_pcie_send_frame;
 	hdev->setup = btintel_pcie_setup;
 	hdev->shutdown = btintel_shutdown_combined;
-	hdev->hw_error = btintel_hw_error;
+	hdev->hw_error = btintel_pcie_hw_error;
 	hdev->set_diag = btintel_set_diag;
 	hdev->set_bdaddr = btintel_set_bdaddr;
+	hdev->reset = btintel_pcie_reset;
 
 	err = hci_register_dev(hdev);
 	if (err < 0) {
@@ -2366,7 +2575,20 @@ static struct pci_driver btintel_pcie_driver = {
 	.driver.coredump = btintel_pcie_coredump
 #endif
 };
-module_pci_driver(btintel_pcie_driver);
+
+static int __init btintel_pcie_init(void)
+{
+	return pci_register_driver(&btintel_pcie_driver);
+}
+
+static void __exit btintel_pcie_exit(void)
+{
+	pci_unregister_driver(&btintel_pcie_driver);
+	btintel_pcie_free_restart_list();
+}
+
+module_init(btintel_pcie_init);
+module_exit(btintel_pcie_exit);
 
 MODULE_AUTHOR("Tedd Ho-Jeong An <tedd.an@intel.com>");
 MODULE_DESCRIPTION("Intel Bluetooth PCIe transport driver ver " VERSION);
diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h
index 7dad4523236c..0fa876c5b954 100644
--- a/drivers/bluetooth/btintel_pcie.h
+++ b/drivers/bluetooth/btintel_pcie.h
@@ -117,7 +117,9 @@ enum {
 enum {
 	BTINTEL_PCIE_CORE_HALTED,
 	BTINTEL_PCIE_HWEXP_INPROGRESS,
-	BTINTEL_PCIE_COREDUMP_INPROGRESS
+	BTINTEL_PCIE_COREDUMP_INPROGRESS,
+	BTINTEL_PCIE_RECOVERY_IN_PROGRESS,
+	BTINTEL_PCIE_SETUP_DONE
 };
 
 enum btintel_pcie_tlv_type {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* RE: [v3,1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download
  2025-06-10 14:00 [PATCH v3 1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download Kiran K
  2025-06-10 14:00 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Support Function level reset Kiran K
@ 2025-06-10 14:10 ` bluez.test.bot
  2025-06-11 14:40 ` [PATCH v3 1/2] " patchwork-bot+bluetooth
  2 siblings, 0 replies; 7+ messages in thread
From: bluez.test.bot @ 2025-06-10 14:10 UTC (permalink / raw)
  To: linux-bluetooth, kiran.k

[-- Attachment #1: Type: text/plain, Size: 1950 bytes --]

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=970379

---Test result---

Test Summary:
CheckPatch                    PENDING   0.30 seconds
GitLint                       PENDING   0.24 seconds
SubjectPrefix                 PASS      0.20 seconds
BuildKernel                   PASS      24.97 seconds
CheckAllWarning               PASS      27.17 seconds
CheckSparse                   PASS      30.71 seconds
BuildKernel32                 PASS      24.63 seconds
TestRunnerSetup               PASS      466.61 seconds
TestRunner_l2cap-tester       PASS      25.77 seconds
TestRunner_iso-tester         PASS      38.91 seconds
TestRunner_bnep-tester        PASS      5.96 seconds
TestRunner_mgmt-tester        FAIL      137.16 seconds
TestRunner_rfcomm-tester      PASS      9.41 seconds
TestRunner_sco-tester         PASS      14.87 seconds
TestRunner_ioctl-tester       PASS      10.02 seconds
TestRunner_mesh-tester        PASS      7.38 seconds
TestRunner_smp-tester         PASS      8.62 seconds
TestRunner_userchan-tester    PASS      6.19 seconds
IncrementalBuild              PENDING   0.98 seconds

Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:

##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:

##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 490, Passed: 485 (99.0%), Failed: 1, Not Run: 4

Failed Test Cases
LL Privacy - Set Flags 4 (RL is full)                Failed       0.302 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:



---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/2] Bluetooth: btintel_pcie: Support Function level reset
  2025-06-10 14:00 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Support Function level reset Kiran K
@ 2025-06-10 15:01   ` Paul Menzel
  2025-06-10 15:19     ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 7+ messages in thread
From: Paul Menzel @ 2025-06-10 15:01 UTC (permalink / raw)
  To: Kiran K
  Cc: ravishankar.srivatsa, chethan.tumkur.narayan,
	chandrashekar.devegowda, aluvala.sai.teja, linux-bluetooth

Dear Chandrashekar, dear Kiran,


Thank you for the improved version. Sorry, but I still have a few minor 
comments.

Am 10.06.25 um 16:00 schrieb Kiran K:
> From: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
> 
> The driver supports Function Level Reset (FLR) to recover the controller
> upon hardware exceptions or hci command timeouts. FLR is triggered only
> when no prior reset has occurred within the retry window, with a maximum
> of one FLR allowed within this window.

Why only one FLR?

> This patch is tested by,
> echo 1 >  /sys/class/bluetooth/hciX/reset
> 
> Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
> Signed-off-by: Kiran K <kiran.k@intel.com>
> ---
> changes in v3:
> - Fix typos, indentation issues
> - Update commit message to include test command
> - Keep the flr max retry to 1
> 
>   drivers/bluetooth/btintel_pcie.c | 226 ++++++++++++++++++++++++++++++-
>   drivers/bluetooth/btintel_pcie.h |   4 +-
>   2 files changed, 227 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
> index e1c688dd2d45..87e4b3546c7a 100644
> --- a/drivers/bluetooth/btintel_pcie.c
> +++ b/drivers/bluetooth/btintel_pcie.c
> @@ -41,6 +41,13 @@ static const struct pci_device_id btintel_pcie_table[] = {
>   };
>   MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
>   
> +struct btintel_pcie_dev_restart_data {
> +	struct list_head list;
> +	u8 restart_count;
> +	time64_t last_error;
> +	char name[];
> +};
> +
>   /* Intel PCIe uses 4 bytes of HCI type instead of 1 byte BT SIG HCI type */
>   #define BTINTEL_PCIE_HCI_TYPE_LEN	4
>   #define BTINTEL_PCIE_HCI_CMD_PKT	0x00000001
> @@ -62,6 +69,9 @@ MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
>   #define BTINTEL_PCIE_TRIGGER_REASON_USER_TRIGGER	0x17A2
>   #define BTINTEL_PCIE_TRIGGER_REASON_FW_ASSERT		0x1E61
>   
> +#define BTINTEL_PCIE_RESET_WINDOW_SECS		5
> +#define BTINTEL_PCIE_FLR_MAX_RETRY	1
> +
>   /* Alive interrupt context */
>   enum {
>   	BTINTEL_PCIE_ROM,
> @@ -99,6 +109,14 @@ struct btintel_pcie_dbgc_ctxt {
>   	struct btintel_pcie_dbgc_ctxt_buf bufs[BTINTEL_PCIE_DBGC_BUFFER_COUNT];
>   };
>   
> +struct btintel_pcie_removal {
> +	struct pci_dev *pdev;
> +	struct work_struct work;
> +};
> +
> +static LIST_HEAD(btintel_pcie_restart_data_list);
> +static DEFINE_SPINLOCK(btintel_pcie_restart_data_lock);
> +
>   /* This function initializes the memory for DBGC buffers and formats the
>    * DBGC fragment which consists header info and DBGC buffer's LSB, MSB and
>    * size as the payload
> @@ -1932,6 +1950,9 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
>   	u32 type;
>   	u32 old_ctxt;
>   
> +	if (test_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags))
> +		return -ENODEV;
> +
>   	/* Due to the fw limitation, the type header of the packet should be
>   	 * 4 bytes unlike 1 byte for UART. In UART, the firmware can read
>   	 * the first byte to get the packet type and redirect the rest of data
> @@ -2192,9 +2213,196 @@ static int btintel_pcie_setup(struct hci_dev *hdev)
>   		}
>   		btintel_pcie_start_rx(data);
>   	}
> +
> +	if (!err)
> +		set_bit(BTINTEL_PCIE_SETUP_DONE, &data->flags);
>   	return err;
>   }
>   
> +static struct btintel_pcie_dev_restart_data *btintel_pcie_get_restart_data(struct pci_dev *pdev,
> +									   struct device *dev)
> +{
> +	struct btintel_pcie_dev_restart_data *tmp, *data = NULL;
> +	const char *name = pci_name(pdev);
> +	struct hci_dev *hdev = to_hci_dev(dev);
> +
> +	spin_lock(&btintel_pcie_restart_data_lock);
> +	list_for_each_entry(tmp, &btintel_pcie_restart_data_list, list) {
> +		if (strcmp(tmp->name, name))
> +			continue;
> +		data = tmp;
> +		break;
> +	}
> +	spin_unlock(&btintel_pcie_restart_data_lock);
> +
> +	if (data) {
> +		bt_dev_dbg(hdev, "Found restart data for BDF: %s", data->name);
> +		return data;
> +	}
> +
> +	data = kzalloc(struct_size(data, name, strlen(name) + 1), GFP_ATOMIC);
> +	if (!data)
> +		return NULL;
> +
> +	strscpy_pad(data->name, name, strlen(name) + 1);
> +	spin_lock(&btintel_pcie_restart_data_lock);
> +	list_add_tail(&data->list, &btintel_pcie_restart_data_list);
> +	spin_unlock(&btintel_pcie_restart_data_lock);
> +
> +	return data;
> +}
> +
> +static void btintel_pcie_free_restart_list(void)
> +{
> +	struct btintel_pcie_dev_restart_data *tmp;
> +
> +	while ((tmp = list_first_entry_or_null(&btintel_pcie_restart_data_list,
> +					       typeof(*tmp), list))) {
> +		list_del(&tmp->list);
> +		kfree(tmp);
> +	}
> +}
> +
> +static void btintel_pcie_inc_restart_count(struct pci_dev *pdev,
> +					   struct device *dev)
> +{
> +	struct btintel_pcie_dev_restart_data *data;
> +	struct hci_dev *hdev = to_hci_dev(dev);
> +	time64_t retry_window;
> +
> +	data = btintel_pcie_get_restart_data(pdev, dev);
> +	if (!data)
> +		return;
> +
> +	retry_window = ktime_get_boottime_seconds() - data->last_error;
> +	if (data->restart_count == 0) {
> +		data->last_error = ktime_get_boottime_seconds();
> +		data->restart_count++;
> +		bt_dev_dbg(hdev, "First iteration initialise. last_error: %lld seconds restart_count: %d",
> +			   data->last_error, data->restart_count);
> +	} else if (retry_window < BTINTEL_PCIE_RESET_WINDOW_SECS &&
> +		   data->restart_count <= BTINTEL_PCIE_FLR_MAX_RETRY) {
> +		data->restart_count++;
> +		bt_dev_dbg(hdev, "Flr triggered within the max retry time so increment the restart_count: %d",

Spell it FLR?

> +			   data->restart_count);
> +	} else if (retry_window > BTINTEL_PCIE_RESET_WINDOW_SECS) {
> +		data->last_error = 0;
> +		data->restart_count = 0;
> +		bt_dev_dbg(hdev, "Flr triggered out of the retry window, so reset counters");

Ditto.

> +	}
> +}
> +
> +static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data);
> +
> +static void btintel_pcie_removal_work(struct work_struct *wk)
> +{
> +	struct btintel_pcie_removal *removal =
> +		container_of(wk, struct btintel_pcie_removal, work);
> +	struct pci_dev *pdev = removal->pdev;
> +	struct btintel_pcie_data *data;
> +	int err;
> +
> +	pci_lock_rescan_remove();
> +
> +	if (!pdev->bus)
> +		goto error;
> +
> +	data = pci_get_drvdata(pdev);
> +
> +	btintel_pcie_disable_interrupts(data);
> +	btintel_pcie_synchronize_irqs(data);
> +
> +	flush_work(&data->rx_work);
> +	flush_work(&data->hdev->dump.dump_rx);
> +
> +	bt_dev_dbg(data->hdev, "Release bluetooth interface");
> +	btintel_pcie_release_hdev(data);
> +
> +	err = pci_reset_function(pdev);
> +	if (err) {
> +		BT_ERR("Failed resetting the pcie device (%d)", err);
> +		goto error;
> +	}
> +
> +	btintel_pcie_enable_interrupts(data);
> +	btintel_pcie_config_msix(data);
> +
> +	err = btintel_pcie_enable_bt(data);
> +	if (err) {
> +		BT_ERR("Failed to enable bluetooth hardware after reset (%d)",
> +		       err);
> +		goto error;
> +	}
> +
> +	btintel_pcie_reset_ia(data);
> +	btintel_pcie_start_rx(data);
> +	data->flags = 0;
> +
> +	err = btintel_pcie_setup_hdev(data);
> +	if (err) {
> +		BT_ERR("Failed registering hdev (%d)", err);
> +		goto error;
> +	}
> +error:
> +	pci_dev_put(pdev);
> +	pci_unlock_rescan_remove();
> +	kfree(removal);
> +}
> +
> +static void btintel_pcie_reset(struct hci_dev *hdev)
> +{
> +	struct btintel_pcie_removal *removal;
> +	struct btintel_pcie_data *data;
> +
> +	data = hci_get_drvdata(hdev);
> +
> +	if (!test_bit(BTINTEL_PCIE_SETUP_DONE, &data->flags))
> +		return;
> +
> +	if (test_and_set_bit(BTINTEL_PCIE_RECOVERY_IN_PROGRESS, &data->flags))
> +		return;
> +
> +	removal = kzalloc(sizeof(*removal), GFP_ATOMIC);
> +	if (!removal)
> +		return;
> +
> +	removal->pdev = data->pdev;
> +	INIT_WORK(&removal->work, btintel_pcie_removal_work);
> +	pci_dev_get(removal->pdev);
> +	schedule_work(&removal->work);
> +}
> +
> +static void btintel_pcie_hw_error(struct hci_dev *hdev, u8 code)
> +{
> +	struct  btintel_pcie_dev_restart_data *data;

Exactly one space after struct?

> +	struct btintel_pcie_data *dev_data = hci_get_drvdata(hdev);
> +	struct pci_dev *pdev = dev_data->pdev;
> +	time64_t retry_window;
> +
> +	if (code == 0x13) {
> +		bt_dev_err(hdev, "Encountered top exception");
> +		return;
> +	}
> +
> +	data = btintel_pcie_get_restart_data(pdev, &hdev->dev);
> +	if (!data)
> +		return;
> +
> +	retry_window = ktime_get_boottime_seconds() - data->last_error;
> +
> +	if (retry_window < BTINTEL_PCIE_RESET_WINDOW_SECS &&
> +	    data->restart_count >= BTINTEL_PCIE_FLR_MAX_RETRY) {
> +		bt_dev_err(hdev, "Exhausted maximum: %d recovery attempts: %d",
> +			   BTINTEL_PCIE_FLR_MAX_RETRY, data->restart_count);
> +		bt_dev_dbg(hdev, "Boot time: %lld seconds first_flr at: %lld seconds restart_count: %d",
> +			   ktime_get_boottime_seconds(), data->last_error,
> +			   data->restart_count);
> +		return;
> +	}
> +	btintel_pcie_inc_restart_count(pdev, &hdev->dev);
> +	btintel_pcie_reset(hdev);
> +}
> +
>   static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
>   {
>   	int err;
> @@ -2216,9 +2424,10 @@ static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
>   	hdev->send = btintel_pcie_send_frame;
>   	hdev->setup = btintel_pcie_setup;
>   	hdev->shutdown = btintel_shutdown_combined;
> -	hdev->hw_error = btintel_hw_error;
> +	hdev->hw_error = btintel_pcie_hw_error;
>   	hdev->set_diag = btintel_set_diag;
>   	hdev->set_bdaddr = btintel_set_bdaddr;
> +	hdev->reset = btintel_pcie_reset;
>   
>   	err = hci_register_dev(hdev);
>   	if (err < 0) {
> @@ -2366,7 +2575,20 @@ static struct pci_driver btintel_pcie_driver = {
>   	.driver.coredump = btintel_pcie_coredump
>   #endif
>   };
> -module_pci_driver(btintel_pcie_driver);
> +
> +static int __init btintel_pcie_init(void)
> +{
> +	return pci_register_driver(&btintel_pcie_driver);
> +}
> +
> +static void __exit btintel_pcie_exit(void)
> +{
> +	pci_unregister_driver(&btintel_pcie_driver);
> +	btintel_pcie_free_restart_list();
> +}
> +
> +module_init(btintel_pcie_init);
> +module_exit(btintel_pcie_exit);
>   
>   MODULE_AUTHOR("Tedd Ho-Jeong An <tedd.an@intel.com>");
>   MODULE_DESCRIPTION("Intel Bluetooth PCIe transport driver ver " VERSION);
> diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h
> index 7dad4523236c..0fa876c5b954 100644
> --- a/drivers/bluetooth/btintel_pcie.h
> +++ b/drivers/bluetooth/btintel_pcie.h
> @@ -117,7 +117,9 @@ enum {
>   enum {
>   	BTINTEL_PCIE_CORE_HALTED,
>   	BTINTEL_PCIE_HWEXP_INPROGRESS,
> -	BTINTEL_PCIE_COREDUMP_INPROGRESS
> +	BTINTEL_PCIE_COREDUMP_INPROGRESS,
> +	BTINTEL_PCIE_RECOVERY_IN_PROGRESS,
> +	BTINTEL_PCIE_SETUP_DONE
>   };
>   
>   enum btintel_pcie_tlv_type {


Kind regards,

Paul

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/2] Bluetooth: btintel_pcie: Support Function level reset
  2025-06-10 15:01   ` Paul Menzel
@ 2025-06-10 15:19     ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2025-06-10 15:19 UTC (permalink / raw)
  To: Paul Menzel
  Cc: Kiran K, ravishankar.srivatsa, chethan.tumkur.narayan,
	chandrashekar.devegowda, aluvala.sai.teja, linux-bluetooth

Hi Paul,

On Tue, Jun 10, 2025 at 11:08 AM Paul Menzel <pmenzel@molgen.mpg.de> wrote:
>
> Dear Chandrashekar, dear Kiran,
>
>
> Thank you for the improved version. Sorry, but I still have a few minor
> comments.
>
> Am 10.06.25 um 16:00 schrieb Kiran K:
> > From: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
> >
> > The driver supports Function Level Reset (FLR) to recover the controller
> > upon hardware exceptions or hci command timeouts. FLR is triggered only
> > when no prior reset has occurred within the retry window, with a maximum
> > of one FLR allowed within this window.
>
> Why only one FLR?

FLR is used for recovery, if it can't recover on the first try then it
probably can't be recovered with FLR alone.

> > This patch is tested by,
> > echo 1 >  /sys/class/bluetooth/hciX/reset
> >
> > Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
> > Signed-off-by: Kiran K <kiran.k@intel.com>
> > ---
> > changes in v3:
> > - Fix typos, indentation issues
> > - Update commit message to include test command
> > - Keep the flr max retry to 1
> >
> >   drivers/bluetooth/btintel_pcie.c | 226 ++++++++++++++++++++++++++++++-
> >   drivers/bluetooth/btintel_pcie.h |   4 +-
> >   2 files changed, 227 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
> > index e1c688dd2d45..87e4b3546c7a 100644
> > --- a/drivers/bluetooth/btintel_pcie.c
> > +++ b/drivers/bluetooth/btintel_pcie.c
> > @@ -41,6 +41,13 @@ static const struct pci_device_id btintel_pcie_table[] = {
> >   };
> >   MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
> >
> > +struct btintel_pcie_dev_restart_data {
> > +     struct list_head list;
> > +     u8 restart_count;
> > +     time64_t last_error;
> > +     char name[];
> > +};
> > +
> >   /* Intel PCIe uses 4 bytes of HCI type instead of 1 byte BT SIG HCI type */
> >   #define BTINTEL_PCIE_HCI_TYPE_LEN   4
> >   #define BTINTEL_PCIE_HCI_CMD_PKT    0x00000001
> > @@ -62,6 +69,9 @@ MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
> >   #define BTINTEL_PCIE_TRIGGER_REASON_USER_TRIGGER    0x17A2
> >   #define BTINTEL_PCIE_TRIGGER_REASON_FW_ASSERT               0x1E61
> >
> > +#define BTINTEL_PCIE_RESET_WINDOW_SECS               5
> > +#define BTINTEL_PCIE_FLR_MAX_RETRY   1
> > +
> >   /* Alive interrupt context */
> >   enum {
> >       BTINTEL_PCIE_ROM,
> > @@ -99,6 +109,14 @@ struct btintel_pcie_dbgc_ctxt {
> >       struct btintel_pcie_dbgc_ctxt_buf bufs[BTINTEL_PCIE_DBGC_BUFFER_COUNT];
> >   };
> >
> > +struct btintel_pcie_removal {
> > +     struct pci_dev *pdev;
> > +     struct work_struct work;
> > +};
> > +
> > +static LIST_HEAD(btintel_pcie_restart_data_list);
> > +static DEFINE_SPINLOCK(btintel_pcie_restart_data_lock);
> > +
> >   /* This function initializes the memory for DBGC buffers and formats the
> >    * DBGC fragment which consists header info and DBGC buffer's LSB, MSB and
> >    * size as the payload
> > @@ -1932,6 +1950,9 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
> >       u32 type;
> >       u32 old_ctxt;
> >
> > +     if (test_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags))
> > +             return -ENODEV;
> > +
> >       /* Due to the fw limitation, the type header of the packet should be
> >        * 4 bytes unlike 1 byte for UART. In UART, the firmware can read
> >        * the first byte to get the packet type and redirect the rest of data
> > @@ -2192,9 +2213,196 @@ static int btintel_pcie_setup(struct hci_dev *hdev)
> >               }
> >               btintel_pcie_start_rx(data);
> >       }
> > +
> > +     if (!err)
> > +             set_bit(BTINTEL_PCIE_SETUP_DONE, &data->flags);
> >       return err;
> >   }
> >
> > +static struct btintel_pcie_dev_restart_data *btintel_pcie_get_restart_data(struct pci_dev *pdev,
> > +                                                                        struct device *dev)
> > +{
> > +     struct btintel_pcie_dev_restart_data *tmp, *data = NULL;
> > +     const char *name = pci_name(pdev);
> > +     struct hci_dev *hdev = to_hci_dev(dev);
> > +
> > +     spin_lock(&btintel_pcie_restart_data_lock);
> > +     list_for_each_entry(tmp, &btintel_pcie_restart_data_list, list) {
> > +             if (strcmp(tmp->name, name))
> > +                     continue;
> > +             data = tmp;
> > +             break;
> > +     }
> > +     spin_unlock(&btintel_pcie_restart_data_lock);
> > +
> > +     if (data) {
> > +             bt_dev_dbg(hdev, "Found restart data for BDF: %s", data->name);
> > +             return data;
> > +     }
> > +
> > +     data = kzalloc(struct_size(data, name, strlen(name) + 1), GFP_ATOMIC);
> > +     if (!data)
> > +             return NULL;
> > +
> > +     strscpy_pad(data->name, name, strlen(name) + 1);
> > +     spin_lock(&btintel_pcie_restart_data_lock);
> > +     list_add_tail(&data->list, &btintel_pcie_restart_data_list);
> > +     spin_unlock(&btintel_pcie_restart_data_lock);
> > +
> > +     return data;
> > +}
> > +
> > +static void btintel_pcie_free_restart_list(void)
> > +{
> > +     struct btintel_pcie_dev_restart_data *tmp;
> > +
> > +     while ((tmp = list_first_entry_or_null(&btintel_pcie_restart_data_list,
> > +                                            typeof(*tmp), list))) {
> > +             list_del(&tmp->list);
> > +             kfree(tmp);
> > +     }
> > +}
> > +
> > +static void btintel_pcie_inc_restart_count(struct pci_dev *pdev,
> > +                                        struct device *dev)
> > +{
> > +     struct btintel_pcie_dev_restart_data *data;
> > +     struct hci_dev *hdev = to_hci_dev(dev);
> > +     time64_t retry_window;
> > +
> > +     data = btintel_pcie_get_restart_data(pdev, dev);
> > +     if (!data)
> > +             return;
> > +
> > +     retry_window = ktime_get_boottime_seconds() - data->last_error;
> > +     if (data->restart_count == 0) {
> > +             data->last_error = ktime_get_boottime_seconds();
> > +             data->restart_count++;
> > +             bt_dev_dbg(hdev, "First iteration initialise. last_error: %lld seconds restart_count: %d",
> > +                        data->last_error, data->restart_count);
> > +     } else if (retry_window < BTINTEL_PCIE_RESET_WINDOW_SECS &&
> > +                data->restart_count <= BTINTEL_PCIE_FLR_MAX_RETRY) {
> > +             data->restart_count++;
> > +             bt_dev_dbg(hdev, "Flr triggered within the max retry time so increment the restart_count: %d",
>
> Spell it FLR?

This is maybe misleading since the idea now is that the FLR is only
triggered once, we could probably remove restart_count altogether and
just a flag to indicate FLR has been triggered.

> > +                        data->restart_count);
> > +     } else if (retry_window > BTINTEL_PCIE_RESET_WINDOW_SECS) {
> > +             data->last_error = 0;
> > +             data->restart_count = 0;
> > +             bt_dev_dbg(hdev, "Flr triggered out of the retry window, so reset counters");
>
> Ditto.
>
> > +     }
> > +}
> > +
> > +static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data);
> > +
> > +static void btintel_pcie_removal_work(struct work_struct *wk)
> > +{
> > +     struct btintel_pcie_removal *removal =
> > +             container_of(wk, struct btintel_pcie_removal, work);
> > +     struct pci_dev *pdev = removal->pdev;
> > +     struct btintel_pcie_data *data;
> > +     int err;
> > +
> > +     pci_lock_rescan_remove();
> > +
> > +     if (!pdev->bus)
> > +             goto error;
> > +
> > +     data = pci_get_drvdata(pdev);
> > +
> > +     btintel_pcie_disable_interrupts(data);
> > +     btintel_pcie_synchronize_irqs(data);
> > +
> > +     flush_work(&data->rx_work);
> > +     flush_work(&data->hdev->dump.dump_rx);
> > +
> > +     bt_dev_dbg(data->hdev, "Release bluetooth interface");
> > +     btintel_pcie_release_hdev(data);
> > +
> > +     err = pci_reset_function(pdev);
> > +     if (err) {
> > +             BT_ERR("Failed resetting the pcie device (%d)", err);
> > +             goto error;
> > +     }
> > +
> > +     btintel_pcie_enable_interrupts(data);
> > +     btintel_pcie_config_msix(data);
> > +
> > +     err = btintel_pcie_enable_bt(data);
> > +     if (err) {
> > +             BT_ERR("Failed to enable bluetooth hardware after reset (%d)",
> > +                    err);
> > +             goto error;
> > +     }
> > +
> > +     btintel_pcie_reset_ia(data);
> > +     btintel_pcie_start_rx(data);
> > +     data->flags = 0;
> > +
> > +     err = btintel_pcie_setup_hdev(data);
> > +     if (err) {
> > +             BT_ERR("Failed registering hdev (%d)", err);
> > +             goto error;
> > +     }
> > +error:
> > +     pci_dev_put(pdev);
> > +     pci_unlock_rescan_remove();
> > +     kfree(removal);
> > +}
> > +
> > +static void btintel_pcie_reset(struct hci_dev *hdev)
> > +{
> > +     struct btintel_pcie_removal *removal;
> > +     struct btintel_pcie_data *data;
> > +
> > +     data = hci_get_drvdata(hdev);
> > +
> > +     if (!test_bit(BTINTEL_PCIE_SETUP_DONE, &data->flags))
> > +             return;
> > +
> > +     if (test_and_set_bit(BTINTEL_PCIE_RECOVERY_IN_PROGRESS, &data->flags))
> > +             return;
> > +
> > +     removal = kzalloc(sizeof(*removal), GFP_ATOMIC);
> > +     if (!removal)
> > +             return;
> > +
> > +     removal->pdev = data->pdev;
> > +     INIT_WORK(&removal->work, btintel_pcie_removal_work);
> > +     pci_dev_get(removal->pdev);
> > +     schedule_work(&removal->work);
> > +}
> > +
> > +static void btintel_pcie_hw_error(struct hci_dev *hdev, u8 code)
> > +{
> > +     struct  btintel_pcie_dev_restart_data *data;
>
> Exactly one space after struct?
>
> > +     struct btintel_pcie_data *dev_data = hci_get_drvdata(hdev);
> > +     struct pci_dev *pdev = dev_data->pdev;
> > +     time64_t retry_window;
> > +
> > +     if (code == 0x13) {
> > +             bt_dev_err(hdev, "Encountered top exception");
> > +             return;
> > +     }
> > +
> > +     data = btintel_pcie_get_restart_data(pdev, &hdev->dev);
> > +     if (!data)
> > +             return;
> > +
> > +     retry_window = ktime_get_boottime_seconds() - data->last_error;
> > +
> > +     if (retry_window < BTINTEL_PCIE_RESET_WINDOW_SECS &&
> > +         data->restart_count >= BTINTEL_PCIE_FLR_MAX_RETRY) {
> > +             bt_dev_err(hdev, "Exhausted maximum: %d recovery attempts: %d",
> > +                        BTINTEL_PCIE_FLR_MAX_RETRY, data->restart_count);
> > +             bt_dev_dbg(hdev, "Boot time: %lld seconds first_flr at: %lld seconds restart_count: %d",
> > +                        ktime_get_boottime_seconds(), data->last_error,
> > +                        data->restart_count);
> > +             return;
> > +     }
> > +     btintel_pcie_inc_restart_count(pdev, &hdev->dev);
> > +     btintel_pcie_reset(hdev);
> > +}
> > +
> >   static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
> >   {
> >       int err;
> > @@ -2216,9 +2424,10 @@ static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
> >       hdev->send = btintel_pcie_send_frame;
> >       hdev->setup = btintel_pcie_setup;
> >       hdev->shutdown = btintel_shutdown_combined;
> > -     hdev->hw_error = btintel_hw_error;
> > +     hdev->hw_error = btintel_pcie_hw_error;
> >       hdev->set_diag = btintel_set_diag;
> >       hdev->set_bdaddr = btintel_set_bdaddr;
> > +     hdev->reset = btintel_pcie_reset;
> >
> >       err = hci_register_dev(hdev);
> >       if (err < 0) {
> > @@ -2366,7 +2575,20 @@ static struct pci_driver btintel_pcie_driver = {
> >       .driver.coredump = btintel_pcie_coredump
> >   #endif
> >   };
> > -module_pci_driver(btintel_pcie_driver);
> > +
> > +static int __init btintel_pcie_init(void)
> > +{
> > +     return pci_register_driver(&btintel_pcie_driver);
> > +}
> > +
> > +static void __exit btintel_pcie_exit(void)
> > +{
> > +     pci_unregister_driver(&btintel_pcie_driver);
> > +     btintel_pcie_free_restart_list();
> > +}
> > +
> > +module_init(btintel_pcie_init);
> > +module_exit(btintel_pcie_exit);
> >
> >   MODULE_AUTHOR("Tedd Ho-Jeong An <tedd.an@intel.com>");
> >   MODULE_DESCRIPTION("Intel Bluetooth PCIe transport driver ver " VERSION);
> > diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h
> > index 7dad4523236c..0fa876c5b954 100644
> > --- a/drivers/bluetooth/btintel_pcie.h
> > +++ b/drivers/bluetooth/btintel_pcie.h
> > @@ -117,7 +117,9 @@ enum {
> >   enum {
> >       BTINTEL_PCIE_CORE_HALTED,
> >       BTINTEL_PCIE_HWEXP_INPROGRESS,
> > -     BTINTEL_PCIE_COREDUMP_INPROGRESS
> > +     BTINTEL_PCIE_COREDUMP_INPROGRESS,
> > +     BTINTEL_PCIE_RECOVERY_IN_PROGRESS,
> > +     BTINTEL_PCIE_SETUP_DONE
> >   };
> >
> >   enum btintel_pcie_tlv_type {
>
>
> Kind regards,
>
> Paul
>


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download
  2025-06-10 14:00 [PATCH v3 1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download Kiran K
  2025-06-10 14:00 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Support Function level reset Kiran K
  2025-06-10 14:10 ` [v3,1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download bluez.test.bot
@ 2025-06-11 14:40 ` patchwork-bot+bluetooth
  2025-06-11 14:45   ` Luiz Augusto von Dentz
  2 siblings, 1 reply; 7+ messages in thread
From: patchwork-bot+bluetooth @ 2025-06-11 14:40 UTC (permalink / raw)
  To: Kiran K
  Cc: linux-bluetooth, ravishankar.srivatsa, chethan.tumkur.narayan,
	chandrashekar.devegowda, aluvala.sai.teja

Hello:

This series was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Tue, 10 Jun 2025 19:30:37 +0530 you wrote:
> During firmware download, if an error occurs, interrupts must be
> disabled, synchronized, and re-enabled before retrying the download.
> This change ensures proper interrupt handling to prevent race
> conditions.
> 
> Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
> Signed-off-by: Kiran K <kiran.k@intel.com>
> 
> [...]

Here is the summary with links:
  - [v3,1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download
    https://git.kernel.org/bluetooth/bluetooth-next/c/866fd57640ce
  - [v3,2/2] Bluetooth: btintel_pcie: Support Function level reset
    https://git.kernel.org/bluetooth/bluetooth-next/c/ba6b287d9f91

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download
  2025-06-11 14:40 ` [PATCH v3 1/2] " patchwork-bot+bluetooth
@ 2025-06-11 14:45   ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2025-06-11 14:45 UTC (permalink / raw)
  To: patchwork-bot+bluetooth
  Cc: Kiran K, linux-bluetooth, ravishankar.srivatsa,
	chethan.tumkur.narayan, chandrashekar.devegowda, aluvala.sai.teja

Hi Kiran, Chandru,

On Wed, Jun 11, 2025 at 10:42 AM <patchwork-bot+bluetooth@kernel.org> wrote:
>
> Hello:
>
> This series was applied to bluetooth/bluetooth-next.git (master)
> by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
>
> On Tue, 10 Jun 2025 19:30:37 +0530 you wrote:
> > During firmware download, if an error occurs, interrupts must be
> > disabled, synchronized, and re-enabled before retrying the download.
> > This change ensures proper interrupt handling to prevent race
> > conditions.
> >
> > Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
> > Signed-off-by: Kiran K <kiran.k@intel.com>
> >
> > [...]
>
> Here is the summary with links:
>   - [v3,1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download
>     https://git.kernel.org/bluetooth/bluetooth-next/c/866fd57640ce
>   - [v3,2/2] Bluetooth: btintel_pcie: Support Function level reset
>     https://git.kernel.org/bluetooth/bluetooth-next/c/ba6b287d9f91

Note that I did add the following changes on top:

https://github.com/bluez/bluetooth-next/commit/bd35cd12d915bc410c721ba28afcada16f0ebd16

> You are awesome, thank you!
> --
> Deet-doot-dot, I am a bot.
> https://korg.docs.kernel.org/patchwork/pwbot.html
>
>
>


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-06-11 14:46 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-10 14:00 [PATCH v3 1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download Kiran K
2025-06-10 14:00 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Support Function level reset Kiran K
2025-06-10 15:01   ` Paul Menzel
2025-06-10 15:19     ` Luiz Augusto von Dentz
2025-06-10 14:10 ` [v3,1/2] Bluetooth: btintel_pcie: Fix potential race condition in firmware download bluez.test.bot
2025-06-11 14:40 ` [PATCH v3 1/2] " patchwork-bot+bluetooth
2025-06-11 14:45   ` Luiz Augusto von Dentz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox