Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22f5f10d authored by Finn Thain's avatar Finn Thain Committed by Christoph Hellwig
Browse files

ncr5380: Fix SCSI_IRQ_NONE bugs



Oak scsi doesn't use any IRQ, but it sets irq = IRQ_NONE rather than
SCSI_IRQ_NONE. Problem is, the core NCR5380 driver expects SCSI_IRQ_NONE
if it is to issue IDENTIFY commands that prevent target disconnection.
And, as Geert points out, IRQ_NONE is part of enum irqreturn.

Other drivers, when they can't get an IRQ or can't use one, will set
host->irq = SCSI_IRQ_NONE (that is, 255). But when they exit they will
attempt to free IRQ 255 which was never requested.

Fix these bugs by using NO_IRQ in place of SCSI_IRQ_NONE and IRQ_NONE.
That means IRQ 0 is no longer probed by ISA drivers but I don't think
this matters.

Setting IRQ = 255 for these ISA drivers is understood to mean no IRQ.
This remains supported so as to avoid breaking existing ISA setups (which
can be difficult to get working) and because existing documentation
(SANE, TLDP etc) describes this usage for the ISA NCR5380 driver options.

Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Tested-by: default avatarMichael Schmitz <schmitzmic@gmail.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 3f9e986e
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -574,12 +574,12 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
	int trying_irqs, i, mask;
	NCR5380_setup(instance);

	for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1)
	for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1)
		if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0))
			trying_irqs |= mask;

	timeout = jiffies + (250 * HZ / 1000);
	probe_irq = SCSI_IRQ_NONE;
	probe_irq = NO_IRQ;

	/*
	 * A interrupt is triggered whenever BSY = false, SEL = true
@@ -596,13 +596,13 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);

	while (probe_irq == SCSI_IRQ_NONE && time_before(jiffies, timeout))
	while (probe_irq == NO_IRQ && time_before(jiffies, timeout))
		schedule_timeout_uninterruptible(1);
	
	NCR5380_write(SELECT_ENABLE_REG, 0);
	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);

	for (i = 0, mask = 1; i < 16; ++i, mask <<= 1)
	for (i = 1, mask = 2; i < 16; ++i, mask <<= 1)
		if (trying_irqs & mask)
			free_irq(i, NULL);

@@ -730,7 +730,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m,

	SPRINTF("\nBase Addr: 0x%05lX    ", (long) instance->base);
	SPRINTF("io_port: %04x      ", (int) instance->io_port);
	if (instance->irq == SCSI_IRQ_NONE)
	if (instance->irq == NO_IRQ)
		SPRINTF("IRQ: None.\n");
	else
		SPRINTF("IRQ: %d.\n", instance->irq);
@@ -1501,7 +1501,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd)
	}

	dprintk(NDEBUG_SELECTION, "scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id);
	tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->device->lun);
	tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun);

	len = 1;
	cmd->tag = 0;
+4 −1
Original line number Diff line number Diff line
@@ -232,12 +232,15 @@
 * Scsi_Host structure
 */

#define SCSI_IRQ_NONE	255
#define DMA_NONE	255
#define IRQ_AUTO	254
#define DMA_AUTO	254
#define PORT_AUTO	0xffff	/* autoprobe io port for 53c400a */

#ifndef NO_IRQ
#define NO_IRQ		0
#endif

#define FLAG_HAS_LAST_BYTE_SENT		1	/* NCR53c81 or better */
#define FLAG_CHECK_LAST_BYTE_SENT	2	/* Only test once */
#define FLAG_NCR53C400			4	/* NCR53c400 */
+1 −1
Original line number Diff line number Diff line
@@ -148,7 +148,7 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
		goto unreg;
	}

	host->irq = IRQ_NONE;
	host->irq = NO_IRQ;
	host->n_io_port = 255;

	NCR5380_init(host, 0);
+4 −3
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
		 */
		printk(KERN_WARNING "dmx3191: IRQ %d not available - "
				    "switching to polled mode.\n", pdev->irq);
		shost->irq = SCSI_IRQ_NONE;
		shost->irq = NO_IRQ;
	}

	pci_set_drvdata(pdev, shost);
@@ -113,6 +113,7 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
	return 0;

 out_free_irq:
	if (shost->irq != NO_IRQ)
		free_irq(shost->irq, shost);
 out_release_region:
	release_region(io, DMX3191D_REGION_LEN);
@@ -130,7 +131,7 @@ static void dmx3191d_remove_one(struct pci_dev *pdev)

	NCR5380_exit(shost);

	if (shost->irq != SCSI_IRQ_NONE)
	if (shost->irq != NO_IRQ)
		free_irq(shost->irq, shost);
	release_region(shost->io_port, DMX3191D_REGION_LEN);
	pci_disable_device(pdev);
+13 −9
Original line number Diff line number Diff line
@@ -254,31 +254,35 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
		else
			instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);

		/* Compatibility with documented NCR5380 kernel parameters */
		if (instance->irq == 255)
			instance->irq = NO_IRQ;

#ifndef DONT_USE_INTR
		/* With interrupts enabled, it will sometimes hang when doing heavy
		 * reads. So better not enable them until I finger it out. */
		if (instance->irq != SCSI_IRQ_NONE)
		if (instance->irq != NO_IRQ)
			if (request_irq(instance->irq, dtc_intr, 0,
					"dtc", instance)) {
				printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
				instance->irq = SCSI_IRQ_NONE;
				instance->irq = NO_IRQ;
			}

		if (instance->irq == SCSI_IRQ_NONE) {
		if (instance->irq == NO_IRQ) {
			printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
			printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
		}
#else
		if (instance->irq != SCSI_IRQ_NONE)
		if (instance->irq != NO_IRQ)
			printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no);
		instance->irq = SCSI_IRQ_NONE;
		instance->irq = NO_IRQ;
#endif
#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
		printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
#endif

		printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base);
		if (instance->irq == SCSI_IRQ_NONE)
		if (instance->irq == NO_IRQ)
			printk(" interrupts disabled");
		else
			printk(" irq %d", instance->irq);
@@ -350,7 +354,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
	i = 0;
	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
	NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
	if (instance->irq == SCSI_IRQ_NONE)
	if (instance->irq == NO_IRQ)
		NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
	else
		NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
@@ -401,7 +405,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
	NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
	/* set direction (write) */
	if (instance->irq == SCSI_IRQ_NONE)
	if (instance->irq == NO_IRQ)
		NCR5380_write(DTC_CONTROL_REG, 0);
	else
		NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
@@ -440,7 +444,7 @@ static int dtc_release(struct Scsi_Host *shost)
{
	NCR5380_local_declare();
	NCR5380_setup(shost);
	if (shost->irq)
	if (shost->irq != NO_IRQ)
		free_irq(shost->irq, shost);
	NCR5380_exit(shost);
	if (shost->io_port && shost->n_io_port)
Loading