From: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx> In preparation for unduplicating the hci_uart registration code, schedule a devres action for disabling the SUSCLK rather than doing it manually. We cannot really use devm_clk_get_enabled() as we also set the rate before enabling the clock. While this should in theory work, I don't want to risk breaking existing users. One solution for the future is to add devm_clk_get_enabled_with_rate() to the clock framework. Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx> --- drivers/bluetooth/hci_qca.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index bc6a49ba26f9..a34c663e337c 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2295,6 +2295,13 @@ static int qca_init_regulators(struct qca_power *qca, return 0; } +static void qca_clk_disable_unprepare(void *data) +{ + struct clk *clk = data; + + clk_disable_unprepare(clk); +} + static int qca_serdev_probe(struct serdev_device *serdev) { struct qca_serdev *qcadev; @@ -2434,10 +2441,15 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (err) return err; + err = devm_add_action_or_reset(&serdev->dev, + qca_clk_disable_unprepare, + qcadev->susclk); + if (err) + return err; + err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); if (err) { BT_ERR("Rome serdev registration failed"); - clk_disable_unprepare(qcadev->susclk); return err; } } @@ -2477,15 +2489,9 @@ static void qca_serdev_remove(struct serdev_device *serdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: - if (power->vregs_on) { + if (power->vregs_on) qca_power_shutdown(&qcadev->serdev_hu); - break; - } - fallthrough; - default: - if (qcadev->susclk) - clk_disable_unprepare(qcadev->susclk); } hci_uart_unregister_device(&qcadev->serdev_hu); -- 2.43.0