Re: qstor driver -> irq 193: nobody cared

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Alberto Alonso wrote:
Sounds good, let me know if you need me to do any
testing or help on the programming.

Okay, try this (untested) and see if it cleans things up.
I'm also including the old "printk" patch, so that we can
tell whether the "fix" is actually working or not.

Thanks
--- old/drivers/scsi/sata_qstor.c	2006-09-19 23:42:06.000000000 -0400
+++ linux/drivers/scsi/sata_qstor.c	2006-11-06 09:50:02.000000000 -0500
@@ -459,6 +459,7 @@
 {
 	struct ata_host_set *host_set = dev_instance;
 	unsigned int handled = 0;
+	static int spurious = 0;
 
 	VPRINTK("ENTER\n");
 
@@ -466,6 +467,20 @@
 	handled  = qs_intr_pkt(host_set) | qs_intr_mmio(host_set);
 	spin_unlock(&host_set->lock);
 
+	/* There are reports of at least one system with glitchy interrupts,
+	 * and if we return !handled here for those then the kernel may totally
+	 * disable our own IRQ line (duh!).
+	 * So, try and be tolerant, but not *too* tolerant.
+	 */
+	if (!handled) {
+		if (spurious < 10) {
+			printk("sata_qstor: spurious=%d\n", spurious);
+			++spurious;
+			handled = 1;
+		}
+	} else if (spurious)
+		--spurious;
+
 	VPRINTK("EXIT\n");
 
 	return IRQ_RETVAL(handled);
--- old/drivers/scsi/sata_qstor.c	2006-11-14 11:30:37.000000000 -0500
+++ linux/drivers/scsi/sata_qstor.c	2006-11-14 13:22:05.000000000 -0500
@@ -299,6 +299,19 @@
 	return nelem;
 }
 
+static void qs_set_nien (struct ata_port *ap, int new_nien)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	if ((ap->ctl & ATA_NIEN) != new_nien) {
+		ap->ctl = (ap->ctl & ~ATA_NIEN) | new_nien;
+		ap->last_ctl = ap->ctl;
+		writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr);
+		wmb();
+		ata_check_status(ap);
+	}
+}
+
 static void qs_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct qs_port_priv *pp = qc->ap->private_data;
@@ -357,6 +370,8 @@
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
+		/* packet mode requires that the NIEN bit be turned on */
+		qs_set_nien(qc->ap, ATA_NIEN);
 
 		pp->state = qs_state_pkt;
 		qs_packet_start(qc);
@@ -370,6 +385,7 @@
 		break;
 	}
 
+	qs_set_nien(qc->ap, 0); // FIXME: is this necessary here?
 	pp->state = qs_state_mmio;
 	return ata_qc_issue_prot(qc);
 }

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux