]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/marvell/mwifiex/usb.c
mwifiex: resolve races between async FW init (failure) and device removal
[karo-tx-linux.git] / drivers / net / wireless / marvell / mwifiex / usb.c
index 73eb0846db210be16476e94f0d7f872992154112..63a755c1e38ca958c32b139a72c5d6d19cfd9bc2 100644 (file)
@@ -24,7 +24,6 @@
 
 static u8 user_rmmod;
 static struct mwifiex_if_ops usb_ops;
-static struct semaphore add_remove_card_sem;
 
 static struct usb_device_id mwifiex_usb_table[] = {
        /* 8766 */
@@ -382,10 +381,12 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
        struct usb_card_rec *card;
        u16 id_vendor, id_product, bcd_device, bcd_usb;
 
-       card = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
+       card = devm_kzalloc(&intf->dev, sizeof(*card), GFP_KERNEL);
        if (!card)
                return -ENOMEM;
 
+       init_completion(&card->fw_done);
+
        id_vendor = le16_to_cpu(udev->descriptor.idVendor);
        id_product = le16_to_cpu(udev->descriptor.idProduct);
        bcd_device = le16_to_cpu(udev->descriptor.bcdDevice);
@@ -475,12 +476,11 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
 
        usb_set_intfdata(intf, card);
 
-       ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
-                              MWIFIEX_USB);
+       ret = mwifiex_add_card(card, &card->fw_done, &usb_ops,
+                              MWIFIEX_USB, &card->udev->dev);
        if (ret) {
                pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
                usb_reset_device(udev);
-               kfree(card);
                return ret;
        }
 
@@ -602,13 +602,15 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
        struct usb_card_rec *card = usb_get_intfdata(intf);
        struct mwifiex_adapter *adapter;
 
-       if (!card || !card->adapter) {
-               pr_err("%s: card or card->adapter is NULL\n", __func__);
+       if (!card) {
+               dev_err(&intf->dev, "%s: card is NULL\n", __func__);
                return;
        }
 
+       wait_for_completion(&card->fw_done);
+
        adapter = card->adapter;
-       if (!adapter->priv_num)
+       if (!adapter || !adapter->priv_num)
                return;
 
        if (user_rmmod && !adapter->mfg_mode) {
@@ -628,13 +630,9 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
 
        mwifiex_dbg(adapter, FATAL,
                    "%s: removing card\n", __func__);
-       mwifiex_remove_card(adapter, &add_remove_card_sem);
+       mwifiex_remove_card(adapter);
 
-       usb_set_intfdata(intf, NULL);
        usb_put_dev(interface_to_usbdev(intf));
-       kfree(card);
-
-       return;
 }
 
 static struct usb_driver mwifiex_usb_driver = {
@@ -932,7 +930,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
        struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
 
        card->adapter = adapter;
-       adapter->dev = &card->udev->dev;
 
        switch (le16_to_cpu(card->udev->descriptor.idProduct)) {
        case USB8997_PID_1:
@@ -1206,8 +1203,7 @@ static struct mwifiex_if_ops usb_ops = {
 
 /* This function initializes the USB driver module.
  *
- * This initiates the semaphore and registers the device with
- * USB bus.
+ * This registers the device with USB bus.
  */
 static int mwifiex_usb_init_module(void)
 {
@@ -1215,8 +1211,6 @@ static int mwifiex_usb_init_module(void)
 
        pr_debug("Marvell USB8797 Driver\n");
 
-       sema_init(&add_remove_card_sem, 1);
-
        ret = usb_register(&mwifiex_usb_driver);
        if (ret)
                pr_err("Driver register failed!\n");
@@ -1236,9 +1230,6 @@ static int mwifiex_usb_init_module(void)
  */
 static void mwifiex_usb_cleanup_module(void)
 {
-       if (!down_interruptible(&add_remove_card_sem))
-               up(&add_remove_card_sem);
-
        /* set the flag as user is removing this module */
        user_rmmod = 1;