wifi: brcmfmac: add function to unbind device to bus layer api
authorArend van Spriel <arend.vanspriel@broadcom.com>
Tue, 29 Nov 2022 13:54:40 +0000 (14:54 +0100)
committerKalle Valo <kvalo@kernel.org>
Thu, 8 Dec 2022 14:44:06 +0000 (16:44 +0200)
Introduce a new bus callback .remove() which will unbind the device
from the driver. This allows the common driver layer to stop handling
a device.

Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20221129135446.151065-2-arend.vanspriel@broadcom.com
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c

index 60f5645aead3adae8749444096a3c35345ec2825..256456e38108df6d0dbeafd48ad4673298bce55d 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/kernel.h>
 #include <linux/firmware.h>
+#include <linux/device.h>
 #include "debug.h"
 
 /* IDs of the 6 default common rings of msgbuf protocol */
@@ -74,6 +75,7 @@ struct brcmf_bus_dcmd {
  * @get_ramsize: obtain size of device memory.
  * @get_memdump: obtain device memory dump in provided buffer.
  * @get_blob: obtain a firmware blob.
+ * @remove: initiate unbind of the device.
  *
  * This structure provides an abstract interface towards the
  * bus specific driver. For control messages to common driver
@@ -94,6 +96,7 @@ struct brcmf_bus_ops {
                        enum brcmf_blob_type type);
        void (*debugfs_create)(struct device *dev);
        int (*reset)(struct device *dev);
+       void (*remove)(struct device *dev);
 };
 
 
@@ -257,6 +260,16 @@ int brcmf_bus_reset(struct brcmf_bus *bus)
        return bus->ops->reset(bus->dev);
 }
 
+static inline void brcmf_bus_remove(struct brcmf_bus *bus)
+{
+       if (!bus->ops->remove) {
+               device_release_driver(bus->dev);
+               return;
+       }
+
+       bus->ops->remove(bus->dev);
+}
+
 /*
  * interface functions from common layer
  */
index 244ba48cc3045d0519e8b579b267920897d8083b..c949051c4bc4fcfe391d1bb5875261f8e952cb4e 100644 (file)
@@ -4171,6 +4171,15 @@ static int brcmf_sdio_bus_reset(struct device *dev)
        return 0;
 }
 
+static void brcmf_sdio_bus_remove(struct device *dev)
+{
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiod = bus_if->bus_priv.sdio;
+
+       device_release_driver(&sdiod->func2->dev);
+       device_release_driver(&sdiod->func1->dev);
+}
+
 static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
        .stop = brcmf_sdio_bus_stop,
        .preinit = brcmf_sdio_bus_preinit,
@@ -4183,7 +4192,8 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
        .get_memdump = brcmf_sdio_bus_get_memdump,
        .get_blob = brcmf_sdio_get_blob,
        .debugfs_create = brcmf_sdio_debugfs_create,
-       .reset = brcmf_sdio_bus_reset
+       .reset = brcmf_sdio_bus_reset,
+       .remove = brcmf_sdio_bus_remove,
 };
 
 #define BRCMF_SDIO_FW_CODE     0