brcmfmac: properly check for bus register errors

[ Upstream commit 419b4a142a7ece36cebcd434f8ce2af59ef94b85 ]

The brcmfmac driver ignores any errors on initialization with the
different busses by deferring the initialization to a workqueue and
ignoring all possible errors that might happen.  Fix up all of this by
only allowing the module to load if all bus registering worked properly.

Cc: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210503115736.2104747-70-gregkh@linuxfoundation.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Greg Kroah-Hartman 2021-05-03 13:57:36 +02:00
parent 26fb7a61de
commit a3dea6dc1e
6 changed files with 41 additions and 46 deletions

View File

@ -1168,13 +1168,9 @@ static struct sdio_driver brcmf_sdmmc_driver = {
},
};
void brcmf_sdio_register(void)
int brcmf_sdio_register(void)
{
int ret;
ret = sdio_register_driver(&brcmf_sdmmc_driver);
if (ret)
brcmf_err("sdio_register_driver failed: %d\n", ret);
return sdio_register_driver(&brcmf_sdmmc_driver);
}
void brcmf_sdio_exit(void)

View File

@ -274,11 +274,26 @@ void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
#ifdef CONFIG_BRCMFMAC_SDIO
void brcmf_sdio_exit(void);
void brcmf_sdio_register(void);
int brcmf_sdio_register(void);
#else
static inline void brcmf_sdio_exit(void) { }
static inline int brcmf_sdio_register(void) { return 0; }
#endif
#ifdef CONFIG_BRCMFMAC_USB
void brcmf_usb_exit(void);
void brcmf_usb_register(void);
int brcmf_usb_register(void);
#else
static inline void brcmf_usb_exit(void) { }
static inline int brcmf_usb_register(void) { return 0; }
#endif
#ifdef CONFIG_BRCMFMAC_PCIE
void brcmf_pcie_exit(void);
int brcmf_pcie_register(void);
#else
static inline void brcmf_pcie_exit(void) { }
static inline int brcmf_pcie_register(void) { return 0; }
#endif
#endif /* BRCMFMAC_BUS_H */

View File

@ -1438,40 +1438,34 @@ void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state)
}
}
static void brcmf_driver_register(struct work_struct *work)
{
#ifdef CONFIG_BRCMFMAC_SDIO
brcmf_sdio_register();
#endif
#ifdef CONFIG_BRCMFMAC_USB
brcmf_usb_register();
#endif
#ifdef CONFIG_BRCMFMAC_PCIE
brcmf_pcie_register();
#endif
}
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register);
int __init brcmf_core_init(void)
{
if (!schedule_work(&brcmf_driver_work))
return -EBUSY;
int err;
err = brcmf_sdio_register();
if (err)
return err;
err = brcmf_usb_register();
if (err)
goto error_usb_register;
err = brcmf_pcie_register();
if (err)
goto error_pcie_register;
return 0;
error_pcie_register:
brcmf_usb_exit();
error_usb_register:
brcmf_sdio_exit();
return err;
}
void __exit brcmf_core_exit(void)
{
cancel_work_sync(&brcmf_driver_work);
#ifdef CONFIG_BRCMFMAC_SDIO
brcmf_sdio_exit();
#endif
#ifdef CONFIG_BRCMFMAC_USB
brcmf_usb_exit();
#endif
#ifdef CONFIG_BRCMFMAC_PCIE
brcmf_pcie_exit();
#endif
}

View File

@ -2137,15 +2137,10 @@ static struct pci_driver brcmf_pciedrvr = {
};
void brcmf_pcie_register(void)
int brcmf_pcie_register(void)
{
int err;
brcmf_dbg(PCIE, "Enter\n");
err = pci_register_driver(&brcmf_pciedrvr);
if (err)
brcmf_err(NULL, "PCIE driver registration failed, err=%d\n",
err);
return pci_register_driver(&brcmf_pciedrvr);
}

View File

@ -11,9 +11,4 @@ struct brcmf_pciedev {
struct brcmf_pciedev_info *devinfo;
};
void brcmf_pcie_exit(void);
void brcmf_pcie_register(void);
#endif /* BRCMFMAC_PCIE_H */

View File

@ -1558,8 +1558,8 @@ void brcmf_usb_exit(void)
usb_deregister(&brcmf_usbdrvr);
}
void brcmf_usb_register(void)
int brcmf_usb_register(void)
{
brcmf_dbg(USB, "Enter\n");
usb_register(&brcmf_usbdrvr);
return usb_register(&brcmf_usbdrvr);
}