From patchwork Sun Dec 6 01:31:33 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Finn Thain X-Patchwork-Id: 7776441 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 9F7B59F350 for ; Sun, 6 Dec 2015 03:46:31 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 85A4420435 for ; Sun, 6 Dec 2015 03:46:30 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6B16520430 for ; Sun, 6 Dec 2015 03:46:29 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1a5QFT-0001H2-2q; Sun, 06 Dec 2015 03:44:31 +0000 Received: from kvm5.telegraphics.com.au ([98.124.60.144]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1a5QFH-0001DF-Fd for linux-arm-kernel@lists.infradead.org; Sun, 06 Dec 2015 03:44:21 +0000 Received: by kvm5.telegraphics.com.au (Postfix, from userid 502) id B5213200FC; Sat, 5 Dec 2015 22:43:53 -0500 (EST) Message-Id: <20151206013128.725501578@telegraphics.com.au> User-Agent: quilt/0.50-1 Date: Sun, 06 Dec 2015 12:31:33 +1100 From: Finn Thain To: "James E.J. Bottomley" , Michael Schmitz , , , , Russell King , linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 07/72] ncr5380: Split NCR5380_init() into two functions References: <20151206013126.995379403@telegraphics.com.au> Content-Disposition: inline; filename=ncr5380-bus-wedge X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151205_194419_823154_590F7666 X-CRM114-Status: GOOD ( 14.94 ) X-Spam-Score: -1.9 (-) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Hannes Reinecke --- drivers/scsi/NCR5380.c | 34 ++++++++++++++++++++-------------- drivers/scsi/NCR5380.h | 1 + drivers/scsi/arm/cumana_1.c | 2 ++ drivers/scsi/arm/oak.c | 2 ++ drivers/scsi/dmx3191d.c | 2 ++ drivers/scsi/dtc.c | 2 ++ drivers/scsi/g_NCR5380.c | 2 ++ drivers/scsi/pas16.c | 2 ++ drivers/scsi/t128.c | 2 ++ 9 files changed, 35 insertions(+), 14 deletions(-) Index: linux/drivers/scsi/NCR5380.c =================================================================== --- linux.orig/drivers/scsi/NCR5380.c 2015-12-06 12:29:29.000000000 +1100 +++ linux/drivers/scsi/NCR5380.c 2015-12-06 12:29:30.000000000 +1100 @@ -777,8 +777,7 @@ static void lprint_opcode(int opcode, st 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 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 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: linux/drivers/scsi/NCR5380.h =================================================================== --- linux.orig/drivers/scsi/NCR5380.h 2015-12-06 12:29:23.000000000 +1100 +++ linux/drivers/scsi/NCR5380.h 2015-12-06 12:29:30.000000000 +1100 @@ -318,6 +318,7 @@ static void NCR5380_print(struct Scsi_Ho 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: linux/drivers/scsi/arm/cumana_1.c =================================================================== --- linux.orig/drivers/scsi/arm/cumana_1.c 2015-12-06 12:29:25.000000000 +1100 +++ linux/drivers/scsi/arm/cumana_1.c 2015-12-06 12:29:30.000000000 +1100 @@ -240,6 +240,8 @@ static int cumanascsi1_probe(struct expa NCR5380_init(host, 0); + NCR5380_maybe_reset_bus(host); + priv(host)->ctrl = 0; writeb(0, priv(host)->base + CTRL); Index: linux/drivers/scsi/arm/oak.c =================================================================== --- linux.orig/drivers/scsi/arm/oak.c 2015-12-06 12:29:25.000000000 +1100 +++ linux/drivers/scsi/arm/oak.c 2015-12-06 12:29:30.000000000 +1100 @@ -145,6 +145,8 @@ static int oakscsi_probe(struct expansio NCR5380_init(host, 0); + NCR5380_maybe_reset_bus(host); + ret = scsi_add_host(host, &ec->dev); if (ret) goto out_unmap; Index: linux/drivers/scsi/dmx3191d.c =================================================================== --- linux.orig/drivers/scsi/dmx3191d.c 2015-12-06 12:29:25.000000000 +1100 +++ linux/drivers/scsi/dmx3191d.c 2015-12-06 12:29:30.000000000 +1100 @@ -97,6 +97,8 @@ static int dmx3191d_probe_one(struct pci 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: linux/drivers/scsi/dtc.c =================================================================== --- linux.orig/drivers/scsi/dtc.c 2015-12-06 12:29:25.000000000 +1100 +++ linux/drivers/scsi/dtc.c 2015-12-06 12:29:30.000000000 +1100 @@ -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: linux/drivers/scsi/g_NCR5380.c =================================================================== --- linux.orig/drivers/scsi/g_NCR5380.c 2015-12-06 12:29:29.000000000 +1100 +++ linux/drivers/scsi/g_NCR5380.c 2015-12-06 12:29:30.000000000 +1100 @@ -422,6 +422,8 @@ static int __init generic_NCR5380_detect NCR5380_init(instance, flags); + NCR5380_maybe_reset_bus(instance); + if (overrides[current_override].irq != IRQ_AUTO) instance->irq = overrides[current_override].irq; else Index: linux/drivers/scsi/pas16.c =================================================================== --- linux.orig/drivers/scsi/pas16.c 2015-12-06 12:29:25.000000000 +1100 +++ linux/drivers/scsi/pas16.c 2015-12-06 12:29:30.000000000 +1100 @@ -384,6 +384,8 @@ static int __init pas16_detect(struct sc NCR5380_init(instance, 0); + NCR5380_maybe_reset_bus(instance); + if (overrides[current_override].irq != IRQ_AUTO) instance->irq = overrides[current_override].irq; else Index: linux/drivers/scsi/t128.c =================================================================== --- linux.orig/drivers/scsi/t128.c 2015-12-06 12:29:25.000000000 +1100 +++ linux/drivers/scsi/t128.c 2015-12-06 12:29:30.000000000 +1100 @@ -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