summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2016-01-03 05:06:07 (GMT)
committerMartin K. Petersen <martin.petersen@oracle.com>2016-01-07 02:43:09 (GMT)
commit0a4e36125451165847c6d4e7d5633d92e53f5c69 (patch)
tree9512674edc9e8fbdd229e8d585d0228184fab8ac
parentcd46140a9a2f8fe0208262dc5f4d1fba15c93063 (diff)
downloadlinux-0a4e36125451165847c6d4e7d5633d92e53f5c69.tar.xz
ncr5380: Fix soft lockups
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>
-rw-r--r--drivers/scsi/NCR5380.c6
-rw-r--r--drivers/scsi/arm/cumana_1.c1
-rw-r--r--drivers/scsi/arm/oak.c1
-rw-r--r--drivers/scsi/atari_NCR5380.c6
-rw-r--r--drivers/scsi/dmx3191d.c1
-rw-r--r--drivers/scsi/dtc.c1
-rw-r--r--drivers/scsi/g_NCR5380.c1
-rw-r--r--drivers/scsi/mac_scsi.c1
-rw-r--r--drivers/scsi/pas16.c1
-rw-r--r--drivers/scsi/t128.c1
10 files changed, 16 insertions, 4 deletions
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 9616f39..38b03af 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -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
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index b526ba5..221f18c 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -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,
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index 70e6485..1fab1d18 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -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)
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index b36fada..a01921d 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -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);
}
diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
index ddb4e61..6c14e68 100644
--- a/drivers/scsi/dmx3191d.c
+++ b/drivers/scsi/dmx3191d.c
@@ -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,
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index f6166e3..6c736b0 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -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"
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 3047206..cd79ef4 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -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"
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index 18f74b4..bb23813 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -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)
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index 7778940..512037e 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -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"
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c
index e50881a..4615fda 100644
--- a/drivers/scsi/t128.c
+++ b/drivers/scsi/t128.c
@@ -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"