Commit 0a4e3612 authored by Finn Thain's avatar Finn Thain Committed by Martin K. Petersen

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: default avatarFinn Thain <fthain@telegraphics.com.au>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Tested-by: default avatarOndrej Zary <linux@rainbow-software.org>
Tested-by: default avatarMichael Schmitz <schmitzmic@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent cd46140a
...@@ -890,10 +890,10 @@ static void NCR5380_main(struct work_struct *work) ...@@ -890,10 +890,10 @@ static void NCR5380_main(struct work_struct *work)
struct scsi_cmnd *cmd; struct scsi_cmnd *cmd;
int done; int done;
spin_lock_irq(&hostdata->lock);
do { do {
done = 1; done = 1;
spin_lock_irq(&hostdata->lock);
while (!hostdata->connected && while (!hostdata->connected &&
(cmd = dequeue_next_cmd(instance))) { (cmd = dequeue_next_cmd(instance))) {
...@@ -930,8 +930,10 @@ static void NCR5380_main(struct work_struct *work) ...@@ -930,8 +930,10 @@ static void NCR5380_main(struct work_struct *work)
NCR5380_information_transfer(instance); NCR5380_information_transfer(instance);
done = 0; done = 0;
} }
spin_unlock_irq(&hostdata->lock);
if (!done)
cond_resched();
} while (!done); } while (!done);
spin_unlock_irq(&hostdata->lock);
} }
#ifndef DONT_USE_INTR #ifndef DONT_USE_INTR
......
...@@ -209,6 +209,7 @@ static struct scsi_host_template cumanascsi_template = { ...@@ -209,6 +209,7 @@ static struct scsi_host_template cumanascsi_template = {
.use_clustering = DISABLE_CLUSTERING, .use_clustering = DISABLE_CLUSTERING,
.proc_name = "CumanaSCSI-1", .proc_name = "CumanaSCSI-1",
.cmd_size = NCR5380_CMD_SIZE, .cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
}; };
static int cumanascsi1_probe(struct expansion_card *ec, static int cumanascsi1_probe(struct expansion_card *ec,
......
...@@ -115,6 +115,7 @@ static struct scsi_host_template oakscsi_template = { ...@@ -115,6 +115,7 @@ static struct scsi_host_template oakscsi_template = {
.use_clustering = DISABLE_CLUSTERING, .use_clustering = DISABLE_CLUSTERING,
.proc_name = "oakscsi", .proc_name = "oakscsi",
.cmd_size = NCR5380_CMD_SIZE, .cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
}; };
static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
......
...@@ -976,10 +976,10 @@ static void NCR5380_main(struct work_struct *work) ...@@ -976,10 +976,10 @@ static void NCR5380_main(struct work_struct *work)
* alter queues and touch the Falcon lock. * alter queues and touch the Falcon lock.
*/ */
spin_lock_irq(&hostdata->lock);
do { do {
done = 1; done = 1;
spin_lock_irq(&hostdata->lock);
while (!hostdata->connected && while (!hostdata->connected &&
(cmd = dequeue_next_cmd(instance))) { (cmd = dequeue_next_cmd(instance))) {
...@@ -1026,8 +1026,10 @@ static void NCR5380_main(struct work_struct *work) ...@@ -1026,8 +1026,10 @@ static void NCR5380_main(struct work_struct *work)
NCR5380_information_transfer(instance); NCR5380_information_transfer(instance);
done = 0; done = 0;
} }
spin_unlock_irq(&hostdata->lock);
if (!done)
cond_resched();
} while (!done); } while (!done);
spin_unlock_irq(&hostdata->lock);
} }
......
...@@ -62,6 +62,7 @@ static struct scsi_host_template dmx3191d_driver_template = { ...@@ -62,6 +62,7 @@ static struct scsi_host_template dmx3191d_driver_template = {
.cmd_per_lun = 2, .cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING, .use_clustering = DISABLE_CLUSTERING,
.cmd_size = NCR5380_CMD_SIZE, .cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
}; };
static int dmx3191d_probe_one(struct pci_dev *pdev, static int dmx3191d_probe_one(struct pci_dev *pdev,
......
...@@ -453,5 +453,6 @@ static struct scsi_host_template driver_template = { ...@@ -453,5 +453,6 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = 2, .cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING, .use_clustering = DISABLE_CLUSTERING,
.cmd_size = NCR5380_CMD_SIZE, .cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
}; };
#include "scsi_module.c" #include "scsi_module.c"
...@@ -729,6 +729,7 @@ static struct scsi_host_template driver_template = { ...@@ -729,6 +729,7 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = 2, .cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING, .use_clustering = DISABLE_CLUSTERING,
.cmd_size = NCR5380_CMD_SIZE, .cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
}; };
#include "scsi_module.c" #include "scsi_module.c"
......
...@@ -324,6 +324,7 @@ static struct scsi_host_template mac_scsi_template = { ...@@ -324,6 +324,7 @@ static struct scsi_host_template mac_scsi_template = {
.cmd_per_lun = 2, .cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING, .use_clustering = DISABLE_CLUSTERING,
.cmd_size = NCR5380_CMD_SIZE, .cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
}; };
static int __init mac_scsi_probe(struct platform_device *pdev) static int __init mac_scsi_probe(struct platform_device *pdev)
......
...@@ -563,6 +563,7 @@ static struct scsi_host_template driver_template = { ...@@ -563,6 +563,7 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = 2, .cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING, .use_clustering = DISABLE_CLUSTERING,
.cmd_size = NCR5380_CMD_SIZE, .cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
}; };
#include "scsi_module.c" #include "scsi_module.c"
......
...@@ -407,5 +407,6 @@ static struct scsi_host_template driver_template = { ...@@ -407,5 +407,6 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = 2, .cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING, .use_clustering = DISABLE_CLUSTERING,
.cmd_size = NCR5380_CMD_SIZE, .cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
}; };
#include "scsi_module.c" #include "scsi_module.c"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment