wifi: ath11k: Register shutdown handler for WCN6750
authorManikanta Pubbisetty <quic_mpubbise@quicinc.com>
Wed, 31 Aug 2022 06:04:19 +0000 (09:04 +0300)
committerKalle Valo <quic_kvalo@quicinc.com>
Thu, 1 Sep 2022 16:09:33 +0000 (19:09 +0300)
When the system shuts down, SMMU driver will be stopped and
will not assist in IOVA translations. SMMU driver expects all
of its consumers to shutdown before shutting down itself.
WCN6750 being one of the consumer device should not perform any
DMA operations after the SMMU has shutdown which will otherwise
result in SMMU faults.

SMMU driver will call the shutdown() callback of all its
consumer devices and the consumers shall stop further DMA
activity after the invocation of their respective shutdown()
callbacks.

Register the shutdown() callback to the platform core for WCN6750.
Change will not impact other AHB ath11k devices.

Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1

Signed-off-by: Manikanta Pubbisetty <quic_mpubbise@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220720134710.15523-1-quic_mpubbise@quicinc.com
drivers/net/wireless/ath/ath11k/ahb.c
drivers/net/wireless/ath/ath11k/core.c

index c4741471013822f5f870f1ed407f1c74b9117ab1..911eee9646a454291727e1cb86c9ada60fe0aa49 100644 (file)
@@ -1088,20 +1088,10 @@ err_core_free:
        return ret;
 }
 
-static int ath11k_ahb_remove(struct platform_device *pdev)
+static void ath11k_ahb_remove_prepare(struct ath11k_base *ab)
 {
-       struct ath11k_base *ab = platform_get_drvdata(pdev);
        unsigned long left;
 
-       if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
-               ath11k_ahb_power_down(ab);
-               ath11k_debugfs_soc_destroy(ab);
-               ath11k_qmi_deinit_service(ab);
-               goto qmi_fail;
-       }
-
-       reinit_completion(&ab->driver_recovery);
-
        if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags)) {
                left = wait_for_completion_timeout(&ab->driver_recovery,
                                                   ATH11K_AHB_RECOVERY_TIMEOUT);
@@ -1111,19 +1101,60 @@ static int ath11k_ahb_remove(struct platform_device *pdev)
 
        set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
        cancel_work_sync(&ab->restart_work);
+       cancel_work_sync(&ab->qmi.event_work);
+}
+
+static void ath11k_ahb_free_resources(struct ath11k_base *ab)
+{
+       struct platform_device *pdev = ab->pdev;
 
-       ath11k_core_deinit(ab);
-qmi_fail:
        ath11k_ahb_free_irq(ab);
        ath11k_hal_srng_deinit(ab);
        ath11k_ahb_fw_resource_deinit(ab);
        ath11k_ce_free_pipes(ab);
        ath11k_core_free(ab);
        platform_set_drvdata(pdev, NULL);
+}
+
+static int ath11k_ahb_remove(struct platform_device *pdev)
+{
+       struct ath11k_base *ab = platform_get_drvdata(pdev);
+
+       if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
+               ath11k_ahb_power_down(ab);
+               ath11k_debugfs_soc_destroy(ab);
+               ath11k_qmi_deinit_service(ab);
+               goto qmi_fail;
+       }
+
+       ath11k_ahb_remove_prepare(ab);
+       ath11k_core_deinit(ab);
+
+qmi_fail:
+       ath11k_ahb_free_resources(ab);
 
        return 0;
 }
 
+static void ath11k_ahb_shutdown(struct platform_device *pdev)
+{
+       struct ath11k_base *ab = platform_get_drvdata(pdev);
+
+       /* platform shutdown() & remove() are mutually exclusive.
+        * remove() is invoked during rmmod & shutdown() during
+        * system reboot/shutdown.
+        */
+       ath11k_ahb_remove_prepare(ab);
+
+       if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)))
+               goto free_resources;
+
+       ath11k_core_deinit(ab);
+
+free_resources:
+       ath11k_ahb_free_resources(ab);
+}
+
 static struct platform_driver ath11k_ahb_driver = {
        .driver         = {
                .name   = "ath11k",
@@ -1131,6 +1162,7 @@ static struct platform_driver ath11k_ahb_driver = {
        },
        .probe  = ath11k_ahb_probe,
        .remove = ath11k_ahb_remove,
+       .shutdown = ath11k_ahb_shutdown,
 };
 
 static int ath11k_ahb_init(void)
index c3e9e4f7bc24e75830a29015d55de6ba1ad994ca..9df6aaae8a44398c8556a5624ee9f0bf32fd2682 100644 (file)
@@ -1563,6 +1563,8 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
 
        wake_up(&ab->wmi_ab.tx_credits_wq);
        wake_up(&ab->peer_mapping_wq);
+
+       reinit_completion(&ab->driver_recovery);
 }
 
 static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab)