ncr5380: Split NCR5380_init() into two functions
authorFinn Thain <fthain@telegraphics.com.au>
Sun, 3 Jan 2016 05:05:08 +0000 (16:05 +1100)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 7 Jan 2016 02:42:52 +0000 (21:42 -0500)
This patch splits the NCR5380_init() function into two parts, similar
to the scheme used with atari_NCR5380.c. This avoids two problems.

Firstly, NCR5380_init() may perform a bus reset, which would cause the
chip to assert IRQ. The chip is unable to mask its bus reset interrupt.
Drivers can't call request_irq() before calling NCR5380_init(), because
initialization must happen before the interrupt handler executes. If
driver initialization causes an interrupt it may be problematic on some
platforms. To avoid that, first move the bus reset code into
NCR5380_maybe_reset_bus().

Secondly, NCR5380_init() contains some board-specific interrupt setup code
for the NCR53C400 that does not belong in the core driver. In moving this
code, better not re-order interrupt initialization and bus reset. Again,
the solution is to move the bus reset code into NCR5380_maybe_reset_bus().

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

index 78d7858c4404be815bd98027f303cb8873ec6fb0..1f9028a0e7eaa28261b60e0ca417b3016974da9a 100644 (file)
@@ -777,8 +777,7 @@ static void lprint_opcode(int opcode, struct seq_file *m)
 
 static int NCR5380_init(struct Scsi_Host *instance, int flags)
 {
-       int i, pass;
-       unsigned long timeout;
+       int i;
        struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
        if(in_interrupt())
@@ -831,18 +830,26 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
                NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
        }
 #endif
+       return 0;
+}
 
-       /* 
-        * Detect and correct bus wedge problems.
-        *
-        * If the system crashed, it may have crashed in a state 
-        * where a SCSI command was still executing, and the 
-        * SCSI bus is not in a BUS FREE STATE.
-        *
-        * If this is the case, we'll try to abort the currently
-        * established nexus which we know nothing about, and that
-        * failing, do a hard reset of the SCSI bus 
-        */
+/**
+ * NCR5380_maybe_reset_bus - Detect and correct bus wedge problems.
+ * @instance: adapter to check
+ *
+ * If the system crashed, it may have crashed with a connected target and
+ * the SCSI bus busy. Check for BUS FREE phase. If not, try to abort the
+ * currently established nexus, which we know nothing about. Failing that
+ * do a bus reset.
+ *
+ * Note that a bus reset will cause the chip to assert IRQ.
+ *
+ * Returns 0 if successful, otherwise -ENXIO.
+ */
+
+static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance)
+{
+       int pass;
 
        for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) {
                switch (pass) {
@@ -850,7 +857,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
                case 3:
                case 5:
                        printk(KERN_INFO "scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no);
-                       timeout = jiffies + 5 * HZ;
                        NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, 0, 5*HZ);
                        break;
                case 2:
index 24c784140db6ec5ae2e209f8bf6a83c834a5921b..2057eaa66c20cbc4e1c4d40cd6ba521be782f148 100644 (file)
@@ -318,6 +318,7 @@ static void NCR5380_print(struct Scsi_Host *instance);
 static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
 #endif
 static int NCR5380_init(struct Scsi_Host *instance, int flags);
+static int NCR5380_maybe_reset_bus(struct Scsi_Host *);
 static void NCR5380_exit(struct Scsi_Host *instance);
 static void NCR5380_information_transfer(struct Scsi_Host *instance);
 #ifndef DONT_USE_INTR
index 8996a6ccc08fbeec06b4eeca6182f3c25274f2f4..c7dc65e39cdbcc9d19168675ce88424e001ef959 100644 (file)
@@ -240,6 +240,8 @@ static int cumanascsi1_probe(struct expansion_card *ec,
 
        NCR5380_init(host, 0);
 
+       NCR5380_maybe_reset_bus(host);
+
         priv(host)->ctrl = 0;
         writeb(0, priv(host)->base + CTRL);
 
index aa5310bef9b78624e6266032500f1f36081ca167..ca0f31d22f43ccd5785f10984e40c215d4946bac 100644 (file)
@@ -145,6 +145,8 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
 
        NCR5380_init(host, 0);
 
+       NCR5380_maybe_reset_bus(host);
+
        ret = scsi_add_host(host, &ec->dev);
        if (ret)
                goto out_unmap;
index 8d2984d7fa9ca2a74ad18d669f9c00aebc626321..2c0fd76410755ffa9f67747d5437eb428ab7db9c 100644 (file)
@@ -97,6 +97,8 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
 
        NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
 
+       NCR5380_maybe_reset_bus(shost);
+
        pci_set_drvdata(pdev, shost);
 
        error = scsi_add_host(shost, &pdev->dev);
index 43c1739639ba32780e92d9f03536da11e0928b8a..02a5532f4267e7f932b8a4e7fef753aae51054fb 100644 (file)
@@ -237,6 +237,8 @@ found:
 
                NCR5380_init(instance, 0);
 
+               NCR5380_maybe_reset_bus(instance);
+
                NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);  /* Enable int's */
                if (overrides[current_override].irq != IRQ_AUTO)
                        instance->irq = overrides[current_override].irq;
index 4559fbc7f3428f1827e9e4f3cadaa16d73992fc3..6f5fdf642296d68c15536a010a00422fd4e3de20 100644 (file)
@@ -422,6 +422,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
 
                NCR5380_init(instance, flags);
 
+               NCR5380_maybe_reset_bus(instance);
+
                if (overrides[current_override].irq != IRQ_AUTO)
                        instance->irq = overrides[current_override].irq;
                else
index e147f5667f2765958576492d7b4b9db53f296fe9..c316ff7ffef6dc49dfafe62df23db313852afe1a 100644 (file)
@@ -384,6 +384,8 @@ static int __init pas16_detect(struct scsi_host_template *tpnt)
 
        NCR5380_init(instance, 0);
 
+       NCR5380_maybe_reset_bus(instance);
+
        if (overrides[current_override].irq != IRQ_AUTO)
            instance->irq = overrides[current_override].irq;
        else 
index d06ae1d11ca4b7a32f45d594950193d2d0c2f249..d5e6b676d75e49d60d3ed302142a7250dcef5b97 100644 (file)
@@ -215,6 +215,8 @@ found:
 
        NCR5380_init(instance, 0);
 
+       NCR5380_maybe_reset_bus(instance);
+
        if (overrides[current_override].irq != IRQ_AUTO)
            instance->irq = overrides[current_override].irq;
        else