ncr5380: Fix soft lockups
authorFinn Thain <fthain@telegraphics.com.au>
Sun, 3 Jan 2016 05:06:07 +0000 (16:06 +1100)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 7 Jan 2016 02:43:09 +0000 (21:43 -0500)
Because of the rudimentary design of the chip, it is necessary to poll the
SCSI bus signals during PIO and this tends to hog the CPU. The driver will
accept new commands while others execute, and this causes a soft lockup
because the workqueue item will not terminate until the issue queue is
emptied.

When exercising dmx3191d using sequential IO from dd, the driver is sent
512 KiB WRITE commands and 128 KiB READs. For a PIO transfer, the rate is
is only about 300 KiB/s, so these are long-running commands. And although
PDMA may run at several MiB/s, interrupts are disabled for the duration
of the transfer.

Fix the unresponsiveness and soft lockup issues by calling cond_resched()
after each command is completed and by limiting max_sectors for drivers
that don't implement real DMA.

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>
drivers/scsi/NCR5380.c
drivers/scsi/arm/cumana_1.c
drivers/scsi/arm/oak.c
drivers/scsi/atari_NCR5380.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/t128.c

index 9616f397e134894dcba06dbd4d4c787a1f9b1cd8..38b03af36a6a86a45c385b71f7584f5f34ab09c2 100644 (file)
@@ -890,10 +890,10 @@ static void NCR5380_main(struct work_struct *work)
        struct scsi_cmnd *cmd;
        int done;
        
-       spin_lock_irq(&hostdata->lock);
        do {
                done = 1;
 
+               spin_lock_irq(&hostdata->lock);
                while (!hostdata->connected &&
                       (cmd = dequeue_next_cmd(instance))) {
 
@@ -930,8 +930,10 @@ static void NCR5380_main(struct work_struct *work)
                        NCR5380_information_transfer(instance);
                        done = 0;
                }
+               spin_unlock_irq(&hostdata->lock);
+               if (!done)
+                       cond_resched();
        } while (!done);
-       spin_unlock_irq(&hostdata->lock);
 }
 
 #ifndef DONT_USE_INTR
index b526ba579ba313e796adb0902c729047353e0487..221f18c5df9363c704d8289c2baab4b10dd89db6 100644 (file)
@@ -209,6 +209,7 @@ static struct scsi_host_template cumanascsi_template = {
        .use_clustering         = DISABLE_CLUSTERING,
        .proc_name              = "CumanaSCSI-1",
        .cmd_size               = NCR5380_CMD_SIZE,
+       .max_sectors            = 128,
 };
 
 static int cumanascsi1_probe(struct expansion_card *ec,
index 70e64851327554ad9ed597e2788e848060f599a5..1fab1d1896b1a7e81a53d2dc664e6f52a712b6d4 100644 (file)
@@ -115,6 +115,7 @@ static struct scsi_host_template oakscsi_template = {
        .use_clustering         = DISABLE_CLUSTERING,
        .proc_name              = "oakscsi",
        .cmd_size               = NCR5380_CMD_SIZE,
+       .max_sectors            = 128,
 };
 
 static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
index b36fadab422b5fffd4f0dcc69ca363b03fd6ad08..a01921dfed0b1d05ce0bac0ecfce4fba4d7af3e4 100644 (file)
@@ -976,10 +976,10 @@ static void NCR5380_main(struct work_struct *work)
         * alter queues and touch the Falcon lock.
         */
 
-       spin_lock_irq(&hostdata->lock);
        do {
                done = 1;
 
+               spin_lock_irq(&hostdata->lock);
                while (!hostdata->connected &&
                       (cmd = dequeue_next_cmd(instance))) {
 
@@ -1026,8 +1026,10 @@ static void NCR5380_main(struct work_struct *work)
                        NCR5380_information_transfer(instance);
                        done = 0;
                }
+               spin_unlock_irq(&hostdata->lock);
+               if (!done)
+                       cond_resched();
        } while (!done);
-       spin_unlock_irq(&hostdata->lock);
 }
 
 
index ddb4e616bfeda18453492efa0b08cadcd71ca5c2..6c14e68b9e1a80aab149ed3f7556ce3e22de7280 100644 (file)
@@ -62,6 +62,7 @@ static struct scsi_host_template dmx3191d_driver_template = {
        .cmd_per_lun            = 2,
        .use_clustering         = DISABLE_CLUSTERING,
        .cmd_size               = NCR5380_CMD_SIZE,
+       .max_sectors            = 128,
 };
 
 static int dmx3191d_probe_one(struct pci_dev *pdev,
index f6166e34e3b02f8c2e540516779a18f982ed2b28..6c736b071cf4bcbaf8f5fb68b19192dc039dd293 100644 (file)
@@ -453,5 +453,6 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = 2,
        .use_clustering         = DISABLE_CLUSTERING,
        .cmd_size               = NCR5380_CMD_SIZE,
+       .max_sectors            = 128,
 };
 #include "scsi_module.c"
index 30472064170ece4f639058463087f65778db7269..cd79ef402d7a88fe6981bccd4565c735da158d96 100644 (file)
@@ -729,6 +729,7 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = 2,
        .use_clustering         = DISABLE_CLUSTERING,
        .cmd_size               = NCR5380_CMD_SIZE,
+       .max_sectors            = 128,
 };
 
 #include "scsi_module.c"
index 18f74b4a0b95b184aac147dbb486bd75c8957129..bb2381314a2bfe91c1552f4f257dc41919014aac 100644 (file)
@@ -324,6 +324,7 @@ static struct scsi_host_template mac_scsi_template = {
        .cmd_per_lun            = 2,
        .use_clustering         = DISABLE_CLUSTERING,
        .cmd_size               = NCR5380_CMD_SIZE,
+       .max_sectors            = 128,
 };
 
 static int __init mac_scsi_probe(struct platform_device *pdev)
index 77789405f4a9751ceb00f22e317ef85b71214d8a..512037e27783d6192f1cea65b41eefb5fbaa9db4 100644 (file)
@@ -563,6 +563,7 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = 2,
        .use_clustering         = DISABLE_CLUSTERING,
        .cmd_size               = NCR5380_CMD_SIZE,
+       .max_sectors            = 128,
 };
 #include "scsi_module.c"
 
index e50881ab9eb48a064a72966422d5a9fc84016ac6..4615fda60dbdf6477ff28566740f59f6f51975ea 100644 (file)
@@ -407,5 +407,6 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = 2,
        .use_clustering         = DISABLE_CLUSTERING,
        .cmd_size               = NCR5380_CMD_SIZE,
+       .max_sectors            = 128,
 };
 #include "scsi_module.c"