diff options
| author | Hans de Goede <johannes.goede@oss.qualcomm.com> | 2026-02-12 15:17:21 +0100 |
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2026-04-10 10:23:02 -0400 |
| commit | 9ff5ff0b9175c37f1fc2ad4e94fa23c7bbc9504f (patch) | |
| tree | 66f51a2342336c0f09bf4f6a4616ffec2e19fc6c /drivers/bluetooth | |
| parent | 7e2e1e5859359c62b4b8f8780be2c8dea1708529 (diff) | |
| download | lwn-9ff5ff0b9175c37f1fc2ad4e94fa23c7bbc9504f.tar.gz lwn-9ff5ff0b9175c37f1fc2ad4e94fa23c7bbc9504f.zip | |
Bluetooth: hci_qca: Fix BT not getting powered-off on rmmod
The BT core skips calling the hci_dev's shutdown method when the HCI
is unregistered. This means that qca_power_off() was not getting called
leaving BT powered on.
This causes regulators / pwrseq providers to not get disabled which also
causes problem when re-loading the module because regulators and pwrseq
providers have an enablecount which now has never dropped to 0, causing
the BT to not get properly reset between rmmod and re-load which causes
initialization failure on the re-load.
Fix this by calling qca_power_off() from qca_close() when BT has not
already been powered off through a qca_hci_shutdown() call.
hci_ldisc.c will call qca_close() after freeing the hdev, so this
means that qca_power_off() can now no longer deref hu->hdev, change
the logging in qca_power_off() to no longer use hu->hdev.
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'drivers/bluetooth')
| -rw-r--r-- | drivers/bluetooth/hci_qca.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index e66d1736acf6..d6e78201a675 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -722,6 +722,10 @@ static int qca_close(struct hci_uart *hu) BT_DBG("hu %p qca close", hu); + /* BT core skips qca_hci_shutdown() which calls qca_power_off() on rmmod */ + if (!test_bit(QCA_BT_OFF, &qca->flags)) + qca_power_off(hu); + serial_clock_vote(HCI_IBS_VOTE_STATS_UPDATE, hu); skb_queue_purge(&qca->tx_wait_q); @@ -2260,7 +2264,7 @@ static void qca_power_off(struct hci_uart *hu) qca_regulator_disable(qcadev); if (qcadev->sw_ctrl) { sw_ctrl_state = gpiod_get_value_cansleep(qcadev->sw_ctrl); - bt_dev_dbg(hu->hdev, "SW_CTRL is %d", sw_ctrl_state); + BT_DBG("SW_CTRL is %d", sw_ctrl_state); } break; |
