ncr5380: Introduce unbound workqueue
authorFinn Thain <fthain@telegraphics.com.au>
Sun, 3 Jan 2016 05:05:21 +0000 (16:05 +1100)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 7 Jan 2016 02:42:56 +0000 (21:42 -0500)
Allocate a work queue that will permit busy waiting and sleeping. This
means NCR5380_init() can potentially fail, so add this error path.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Tested-by: Ondrej Zary <linux@rainbow-software.org>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
13 files changed:
drivers/scsi/NCR5380.c
drivers/scsi/NCR5380.h
drivers/scsi/arm/cumana_1.c
drivers/scsi/arm/oak.c
drivers/scsi/atari_NCR5380.c
drivers/scsi/atari_scsi.c
drivers/scsi/dmx3191d.c
drivers/scsi/dtc.c
drivers/scsi/g_NCR5380.c
drivers/scsi/mac_scsi.c
drivers/scsi/pas16.c
drivers/scsi/sun3_scsi.c
drivers/scsi/t128.c

index 103c23e6d565c99b8c9c5def183684e5e3dd56dc..a66fffc834755db9b6a25dd08d3855e5ae01f459 100644 (file)
@@ -514,7 +514,7 @@ static int should_disconnect(unsigned char cmd)
 static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout)
 {
        hostdata->time_expires = jiffies + timeout;
-       schedule_delayed_work(&hostdata->coroutine, timeout);
+       queue_delayed_work(hostdata->work_q, &hostdata->coroutine, timeout);
 }
 
 
@@ -791,7 +791,12 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
        hostdata->disconnected_queue = NULL;
        
        INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main);
-       
+       hostdata->work_q = alloc_workqueue("ncr5380_%d",
+                               WQ_UNBOUND | WQ_MEM_RECLAIM,
+                               1, instance->host_no);
+       if (!hostdata->work_q)
+               return -ENOMEM;
+
        /* The CHECK code seems to break the 53C400. Will check it later maybe */
        if (flags & FLAG_NCR53C400)
                hostdata->flags = FLAG_HAS_LAST_BYTE_SENT | flags;
@@ -872,6 +877,7 @@ static void NCR5380_exit(struct Scsi_Host *instance)
        struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
        cancel_delayed_work_sync(&hostdata->coroutine);
+       destroy_workqueue(hostdata->work_q);
 }
 
 /**
@@ -932,7 +938,7 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct
 
        /* Run the coroutine if it isn't already running. */
        /* Kick off command processing */
-       schedule_delayed_work(&hostdata->coroutine, 0);
+       queue_delayed_work(hostdata->work_q, &hostdata->coroutine, 0);
        return 0;
 }
 
@@ -1128,7 +1134,8 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id)
                }       /* if BASR_IRQ */
                spin_unlock_irqrestore(instance->host_lock, flags);
                if(!done)
-                       schedule_delayed_work(&hostdata->coroutine, 0);
+                       queue_delayed_work(hostdata->work_q,
+                                          &hostdata->coroutine, 0);
        } while (!done);
        return IRQ_HANDLED;
 }
index 25e28add0db8d722031d807414b91418c8060344..f9c861d083d0c4e57481a015f9a0900e63b9a202 100644 (file)
@@ -284,6 +284,7 @@ struct NCR5380_hostdata {
        unsigned spin_max_r;
        unsigned spin_max_w;
 #endif
+       struct workqueue_struct *work_q;
 };
 
 #ifdef __KERNEL__
index 3b5ff105f1d66a3a2cae37f8687ae15c96871b87..0d0cb62b8cdb44c75faa8f24199ce8b3c1360be2 100644 (file)
@@ -238,7 +238,9 @@ static int cumanascsi1_probe(struct expansion_card *ec,
 
        host->irq = ec->irq;
 
-       NCR5380_init(host, 0);
+       ret = NCR5380_init(host, 0);
+       if (ret)
+               goto out_unmap;
 
        NCR5380_maybe_reset_bus(host);
 
@@ -250,7 +252,7 @@ static int cumanascsi1_probe(struct expansion_card *ec,
        if (ret) {
                printk("scsi%d: IRQ%d not free: %d\n",
                    host->host_no, host->irq, ret);
-               goto out_unmap;
+               goto out_exit;
        }
 
        ret = scsi_add_host(host, &ec->dev);
@@ -262,6 +264,8 @@ static int cumanascsi1_probe(struct expansion_card *ec,
 
  out_free_irq:
        free_irq(host->irq, host);
+ out_exit:
+       NCR5380_exit(host);
  out_unmap:
        iounmap(priv(host)->base);
        iounmap(priv(host)->dma);
index ca0f31d22f43ccd5785f10984e40c215d4946bac..db337b998299b0941180bce973a509c8f415f4a9 100644 (file)
@@ -143,17 +143,21 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
        host->irq = NO_IRQ;
        host->n_io_port = 255;
 
-       NCR5380_init(host, 0);
+       ret = NCR5380_init(host, 0);
+       if (ret)
+               goto out_unmap;
 
        NCR5380_maybe_reset_bus(host);
 
        ret = scsi_add_host(host, &ec->dev);
        if (ret)
-               goto out_unmap;
+               goto out_exit;
 
        scsi_scan_host(host);
        goto out;
 
+ out_exit:
+       NCR5380_exit(host);
  out_unmap:
        iounmap(priv(host)->base);
  unreg:
index 1dd341ef89d4fc895d2637b176e4281de540c99e..0b0a225167bc5218561301caa4aa856711e2104b 100644 (file)
@@ -643,7 +643,7 @@ static inline void queue_main(struct NCR5380_hostdata *hostdata)
                   queue it on the 'immediate' task queue, to be processed
                   immediately after the current interrupt processing has
                   finished. */
-               schedule_work(&hostdata->main_task);
+               queue_work(hostdata->work_q, &hostdata->main_task);
        }
        /* else: nothing to do: the running NCR5380_main() will pick up
           any newly queued command. */
@@ -832,6 +832,11 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
        hostdata->flags = flags;
 
        INIT_WORK(&hostdata->main_task, NCR5380_main);
+       hostdata->work_q = alloc_workqueue("ncr5380_%d",
+                               WQ_UNBOUND | WQ_MEM_RECLAIM,
+                               1, instance->host_no);
+       if (!hostdata->work_q)
+               return -ENOMEM;
 
        prepare_info(instance);
 
@@ -907,6 +912,7 @@ static void NCR5380_exit(struct Scsi_Host *instance)
        struct NCR5380_hostdata *hostdata = shost_priv(instance);
 
        cancel_work_sync(&hostdata->main_task);
+       destroy_workqueue(hostdata->work_q);
 }
 
 /**
index 5b233ccae962e5b4911539ad6304d9253299a117..1c6c4ca0a82fdc90107e15d09d1b988e2cf1a5ad 100644 (file)
@@ -885,7 +885,9 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
 #endif
        host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0;
 
-       NCR5380_init(instance, host_flags);
+       error = NCR5380_init(instance, host_flags);
+       if (error)
+               goto fail_init;
 
        if (IS_A_TT()) {
                error = request_irq(instance->irq, scsi_tt_intr, 0,
@@ -947,6 +949,7 @@ fail_host:
                free_irq(instance->irq, instance);
 fail_irq:
        NCR5380_exit(instance);
+fail_init:
        scsi_host_put(instance);
 fail_alloc:
        if (atari_dma_buffer)
index 2c0fd76410755ffa9f67747d5437eb428ab7db9c..db415359fee83196739906a59d12410b1aa94ca3 100644 (file)
@@ -95,7 +95,9 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
         */
        shost->irq = NO_IRQ;
 
-       NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
+       error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
+       if (error)
+               goto out_host_put;
 
        NCR5380_maybe_reset_bus(shost);
 
@@ -103,11 +105,15 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
 
        error = scsi_add_host(shost, &pdev->dev);
        if (error)
-               goto out_release_region;
+               goto out_exit;
 
        scsi_scan_host(shost);
        return 0;
 
+out_exit:
+       NCR5380_exit(shost);
+out_host_put:
+       scsi_host_put(shost);
  out_release_region:
        release_region(io, DMX3191D_REGION_LEN);
  out_disable_device:
@@ -119,15 +125,14 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
 static void dmx3191d_remove_one(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       unsigned long io = shost->io_port;
 
        scsi_remove_host(shost);
 
        NCR5380_exit(shost);
-
-       release_region(shost->io_port, DMX3191D_REGION_LEN);
-       pci_disable_device(pdev);
-
        scsi_host_put(shost);
+       release_region(io, DMX3191D_REGION_LEN);
+       pci_disable_device(pdev);
 }
 
 static struct pci_device_id dmx3191d_pci_tbl[] = {
index 698bea067af9438f597bd2101f63ce00f24c05d0..bc856c8ba0dd280151c69dabc854fda0405ac0c0 100644 (file)
@@ -230,12 +230,13 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
 found:
                instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
                if (instance == NULL)
-                       break;
+                       goto out_unmap;
 
                instance->base = addr;
                ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base;
 
-               NCR5380_init(instance, 0);
+               if (NCR5380_init(instance, 0))
+                       goto out_unregister;
 
                NCR5380_maybe_reset_bus(instance);
 
@@ -275,6 +276,12 @@ found:
                ++count;
        }
        return count;
+
+out_unregister:
+       scsi_unregister(instance);
+out_unmap:
+       iounmap(base);
+       return count;
 }
 
 /*
index fa9f6d41548bf4322214d9fa8c6084a562957e75..afd092ff0c2e01cb7d7226a9e3621b218add5ff9 100644 (file)
@@ -239,9 +239,6 @@ static int __init do_DTC3181E_setup(char *str)
  *     and DTC436(ISAPnP) controllers. If overrides have been set we use
  *     them.
  *
- *     The caller supplied NCR5380_init function is invoked from here, before
- *     the interrupt line is taken.
- *
  *     Locks: none
  */
 
@@ -402,15 +399,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
                }
 #endif
                instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
-               if (instance == NULL) {
-#ifndef SCSI_G_NCR5380_MEM
-                       release_region(overrides[current_override].NCR5380_map_name, region_size);
-#else
-                       iounmap(iomem);
-                       release_mem_region(base, NCR5380_region_size);
-#endif
-                       continue;
-               }
+               if (instance == NULL)
+                       goto out_release;
 
 #ifndef SCSI_G_NCR5380_MEM
                instance->io_port = overrides[current_override].NCR5380_map_name;
@@ -427,7 +417,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
                ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem;
 #endif
 
-               NCR5380_init(instance, flags);
+               if (NCR5380_init(instance, flags))
+                       goto out_unregister;
 
                if (overrides[current_override].board == BOARD_NCR53C400)
                        NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
@@ -459,6 +450,17 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
                ++count;
        }
        return count;
+
+out_unregister:
+       scsi_unregister(instance);
+out_release:
+#ifndef SCSI_G_NCR5380_MEM
+       release_region(overrides[current_override].NCR5380_map_name, region_size);
+#else
+       iounmap(iomem);
+       release_mem_region(base, NCR5380_region_size);
+#endif
+       return count;
 }
 
 /**
@@ -475,15 +477,12 @@ static int generic_NCR5380_release_resources(struct Scsi_Host *instance)
        if (instance->irq != NO_IRQ)
                free_irq(instance->irq, instance);
        NCR5380_exit(instance);
-
 #ifndef SCSI_G_NCR5380_MEM
        release_region(instance->io_port, instance->n_io_port);
 #else
        iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem);
        release_mem_region(instance->base, NCR5380_region_size);
 #endif
-
-
        return 0;
 }
 
index 4d26ef93e6560fa743c30f0e8d9dbe030d2aeb50..1317f54bab92d51b48da71f57244e80aa3862027 100644 (file)
@@ -382,7 +382,9 @@ static int __init mac_scsi_probe(struct platform_device *pdev)
 #endif
        host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0;
 
-       NCR5380_init(instance, host_flags);
+       error = NCR5380_init(instance, host_flags);
+       if (error)
+               goto fail_init;
 
        if (instance->irq != NO_IRQ) {
                error = request_irq(instance->irq, macscsi_intr, IRQF_SHARED,
@@ -407,6 +409,7 @@ fail_host:
                free_irq(instance->irq, instance);
 fail_irq:
        NCR5380_exit(instance);
+fail_init:
        scsi_host_put(instance);
        return error;
 }
index e5c76eefa5e08829a7694a701ec5bef5b59eaa40..5e57ee01093c12b8ec47f57cd6f47c06c8d65115 100644 (file)
@@ -378,11 +378,12 @@ static int __init pas16_detect(struct scsi_host_template *tpnt)
 
        instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
        if(instance == NULL)
-               break;
+               goto out;
                
        instance->io_port = io_port;
 
-       NCR5380_init(instance, 0);
+       if (NCR5380_init(instance, 0))
+               goto out_unregister;
 
        NCR5380_maybe_reset_bus(instance);
 
@@ -418,6 +419,11 @@ static int __init pas16_detect(struct scsi_host_template *tpnt)
        ++count;
     }
     return count;
+
+out_unregister:
+       scsi_unregister(instance);
+out:
+       return count;
 }
 
 /*
index 9376b3d8bfdc6396e56e304a04d5feacada16114..c4fcf2fa74fc48aab364301dd4c5554fd3926f13 100644 (file)
@@ -557,7 +557,9 @@ static int __init sun3_scsi_probe(struct platform_device *pdev)
        host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0;
 #endif
 
-       NCR5380_init(instance, host_flags);
+       error = NCR5380_init(instance, host_flags);
+       if (error)
+               goto fail_init;
 
        error = request_irq(instance->irq, scsi_sun3_intr, 0,
                            "NCR5380", instance);
@@ -604,6 +606,7 @@ fail_host:
                free_irq(instance->irq, instance);
 fail_irq:
        NCR5380_exit(instance);
+fail_init:
        scsi_host_put(instance);
 fail_alloc:
        if (udc_regs)
index 3adcae1150d28bd2c3f96d653c1a145e94461514..3dac6d7f5d22c9d532e74b7c2705a25b809ad1d2 100644 (file)
@@ -208,12 +208,13 @@ static int __init t128_detect(struct scsi_host_template *tpnt)
 found:
        instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
        if(instance == NULL)
-               break;
-               
+               goto out_unmap;
+
        instance->base = base;
        ((struct NCR5380_hostdata *)instance->hostdata)->base = p;
 
-       NCR5380_init(instance, 0);
+       if (NCR5380_init(instance, 0))
+               goto out_unregister;
 
        NCR5380_maybe_reset_bus(instance);
 
@@ -246,6 +247,12 @@ found:
        ++count;
     }
     return count;
+
+out_unregister:
+       scsi_unregister(instance);
+out_unmap:
+       iounmap(p);
+       return count;
 }
 
 static int t128_release(struct Scsi_Host *shost)