linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13
       [not found] <1121894035.4885.15.camel@drevil.aslab.com>
@ 2005-07-28 14:12 ` Tejun Heo
  2005-08-21 19:19   ` Jeff Garzik
  2005-08-21 19:34   ` [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13 Jeff Garzik
  0 siblings, 2 replies; 15+ messages in thread
From: Tejun Heo @ 2005-07-28 14:12 UTC (permalink / raw)
  To: Michael Madore; +Cc: Jeff Garzik, linux-ide, albertcc

On Wed, Jul 20, 2005 at 02:13:55PM -0700, Michael Madore wrote:
> Hi,
> 
> I have been successfully using your mod15write quirk patch with 2.6.12-
> rc3.  I recently applied the patch (with a minor reject) to 2.6.12.3.
> Reading seems to work fine, but writing to the disk results in the
> following output:
> 
> irq 169: nobody cared!
> 
> Call Trace: <IRQ> <ffffffff80161e15>{__report_bad_irq+53}
> <ffffffff80161eec>{note_interrupt+92}
>        <ffffffff80161730>{__do_IRQ+256} <ffffffff801116b8>{do_IRQ+72}
>        <ffffffff8010f057>{ret_from_intr+0}  <EOI>
> <ffffffff8010d390>{default_idle+0}
>        <ffffffff8010d3b2>{default_idle+34} <ffffffff8010d407>{cpu_idle
> +71}
>        <ffffffff80515094>{start_secondary+564} 
> handlers:
> [<ffffffff88035490>] (ata_interrupt+0x0/0x180 [libata])
> [<ffffffff88151440>] (snd_intel8x0_interrupt+0x0/0x240 [snd_intel8x0])
> Disabling IRQ #169
> 
> Shortly thereafter, there is a kernel oops and the machine has to be
> rebooted.  Do you have an updated driver for 2.6.12?  I assume something
> has changed in libata.
> 

 Hello, Michael, again.
 Hello, Jeff, Albert & ATA guys.

 This is reply message to Michael's private mail reporting patch apply
failure and (after hand-fixing it) malfunction.  I hope Michael
wouldn't mind adding recipients to this reply.

 sata_sil Mod15Write workaround was broken by the following commit by
Albert Lee.

Commit: 21b1ed74ee3667dcabcba92e486988ea9119a085
[PATCH] libata: Prevent the interrupt handler from completing a command twice

 This commit clears ATA_QCFLAG_ACTIVE in ata_qc_complete() and doesn't
handle IRQ if ATA_QCFLAG_ACTIVE is cleared on entry to interrupt
routine.  As m15w workaround executes single command multiple times,
the flag is cleared after the first chunk completion and the following
interrupt gets ignored resulting in "nobody cared" interrupt error.

 The following changes are made in m15w workaround to fix this.

 * Moved clearing of ATA_QCFLAG_ACTIVE before invoking ->complete_fn,
   so that ->complete_fn can mangle with the flag.  This doesn't affect
   any users.
 * Added setting ATA_QCFLAG_ACTIVE in m15w chunk completion function.

 One thing that bothers me is how Albert's commit and the original
ata_host_intr tell IRQ subsystem that an interrupt isn't ours when we
know that we have generated a spurious interrupt.  IMHO, we always
should enter ata_host_intr and always tell IRQ subsystem that it's our
interrupt if bmdma_status tells us so, regardless of ata status value.
The current code is likely to cause "nobody cared" error which can be
avoided.

 Also, Jeff, I know you're very busy, but what do you think about
taking m15w workaround into ata tree?  It's been around for a while
now and I haven't received any complaints (except for this one) yet.
The workaround is ugly but it surely helps and I'm willing to maintain
it.

 This patch is against v2.6.13-rc3 but also applies to v2.6.12 (with a
fuss).

 Thanks.


Signed-off-by: Tejun Heo <htejun@gmail.com>


diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -3087,8 +3087,8 @@ void ata_qc_complete(struct ata_queued_c
 		ata_sg_clean(qc);
 
 	/* call completion callback */
-	rc = qc->complete_fn(qc, drv_stat);
 	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+	rc = qc->complete_fn(qc, drv_stat);
 
 	/* if callback indicates not to complete command (non-zero),
 	 * return immediately
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -71,9 +71,12 @@ enum {
 
 static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static void sil_dev_config(struct ata_port *ap, struct ata_device *dev);
+static void sil_qc_prep (struct ata_queued_cmd *qc);
+static void sil_eng_timeout (struct ata_port *ap);
 static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static void sil_post_set_mode (struct ata_port *ap);
+static void sil_host_stop (struct ata_host_set *host_set);
 
 static struct pci_device_id sil_pci_tbl[] = {
 	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
@@ -152,16 +155,16 @@ static struct ata_port_operations sil_op
 	.bmdma_start            = ata_bmdma_start,
 	.bmdma_stop		= ata_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
-	.qc_prep		= ata_qc_prep,
+	.qc_prep		= sil_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.eng_timeout		= ata_eng_timeout,
+	.eng_timeout		= sil_eng_timeout,
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 	.scr_read		= sil_scr_read,
 	.scr_write		= sil_scr_write,
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
+	.host_stop		= sil_host_stop,
 };
 
 static struct ata_port_info sil_port_info[] = {
@@ -204,6 +207,53 @@ static const struct {
 	/* ... port 3 */
 };
 
+/*
+ * Context to loop over write requests > 15 sectors for Mod15Write bug.
+ *
+ * The following libata layer fields are saved at the beginning and
+ * mangled as necessary.
+ *
+ * qc->sg		: To fool ata_fill_sg().
+ * qc->n_elem		: ditto.
+ * qc->flags		: Except for the last iteration, ATA_QCFLAG_DMAMAP
+ *			  should be off on entering ata_interrupt() such
+ *			  that ata_qc_complete() doesn't call ata_sg_clean()
+ *			  before sil_m15w_chunk_complete(), but the flags
+ *			  should be set for ata_qc_prep() to work.  This flag
+ *			  handling is the hackiest part of this workaround.
+ * qc->complete_fn	: Overrided to sil_m15w_chunk_complete().
+ *
+ * The following cxt fields are used to iterate over write requests.
+ *
+ * next_block		: The starting block of the next chunk.
+ * next_sg		: The first sg entry of the next chunk.
+ * left			: Total bytes left.
+ * cur_sg_ofs		: Number of processed bytes in the first sg entry
+ *			  of this chunk.
+ * next_sg_ofs		: Number of bytes to be processed in the last sg
+ *			  entry of this chunk.
+ * next_sg_len		: Number of bytes to be processed in the first sg
+ *			  entry of the next chunk.
+ */
+#define M15W_DEBUG
+struct sil_m15w_cxt {
+	u64			next_block;
+	struct scatterlist *	next_sg;
+	unsigned int		left;
+	unsigned int		cur_sg_ofs;
+	unsigned int		next_sg_ofs;
+	unsigned int		next_sg_len;
+	int			timedout;
+
+	struct scatterlist *	orig_sg;
+	unsigned int		orig_nelem;
+	unsigned long		orig_flags;
+	ata_qc_cb_t		orig_complete_fn;
+#ifdef M15W_DEBUG
+	struct scatterlist	sg_copy[LIBATA_MAX_PRD];
+#endif
+};
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller");
 MODULE_LICENSE("GPL");
@@ -244,6 +294,226 @@ static void sil_post_set_mode (struct at
 	readl(addr);	/* flush */
 }
 
+static inline u64 sil_m15w_read_tf_block (struct ata_taskfile *tf)
+{
+	u64 block = 0;
+
+	block |= (u64)tf->lbal;
+	block |= (u64)tf->lbam << 8;
+	block |= (u64)tf->lbah << 16;
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		block |= (u64)tf->hob_lbal << 24;
+		block |= (u64)tf->hob_lbam << 32;
+		block |= (u64)tf->hob_lbah << 40;
+	} else
+		block |= (u64)(tf->device & 0xf) << 24;
+
+	return block;
+}
+
+static inline void sil_m15w_rewrite_tf (struct ata_taskfile *tf,
+					u64 block, u16 nsect)
+{
+	tf->nsect = nsect & 0xff;
+	tf->lbal = block & 0xff;
+	tf->lbam = (block >> 8) & 0xff;
+	tf->lbah = (block >> 16) & 0xff;
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		tf->hob_nsect = (nsect >> 8) & 0xff;
+		tf->hob_lbal = (block >> 24) & 0xff;
+		tf->hob_lbam = (block >> 32) & 0xff;
+		tf->hob_lbah = (block >> 40) & 0xff;
+	} else {
+		tf->device &= ~0xf;
+		tf->device |= (block >> 24) & 0xf;
+	}
+}
+
+static void sil_m15w_next(struct ata_queued_cmd *qc)
+{
+	struct sil_m15w_cxt *cxt = qc->private_data;
+	struct scatterlist *sg;
+	unsigned int todo, res, nelem;
+
+	if (qc->sg != cxt->next_sg) {
+		sg_dma_address(qc->sg) -= cxt->cur_sg_ofs;
+		sg_dma_len(qc->sg) += cxt->cur_sg_ofs;
+		cxt->cur_sg_ofs = 0;
+	}
+	cxt->cur_sg_ofs += cxt->next_sg_ofs;
+
+	qc->sg = sg = cxt->next_sg;
+	sg_dma_address(sg) += cxt->next_sg_ofs;
+	sg_dma_len(sg) = cxt->next_sg_len;
+
+	res = todo = min_t(unsigned int, cxt->left, 15 << 9);
+
+	nelem = 0;
+	while (sg_dma_len(sg) <= res) {
+		res -= sg_dma_len(sg);
+		sg++;
+		nelem++;
+	}
+
+	if (todo < cxt->left) {
+		cxt->next_sg = sg;
+		cxt->next_sg_ofs = res;
+		cxt->next_sg_len = sg_dma_len(sg) - res;
+		if (res) {
+			nelem++;
+			sg_dma_len(sg) = res;
+		}
+	} else {
+		cxt->next_sg = NULL;
+		cxt->next_sg_ofs = 0;
+		cxt->next_sg_len = 0;
+	}
+
+	DPRINTK("block=%llu nelem=%u todo=%u left=%u\n",
+		cxt->next_block, nelem, todo, cxt->left);
+
+	qc->n_elem = nelem;
+	sil_m15w_rewrite_tf(&qc->tf, cxt->next_block, todo >> 9);
+	cxt->left -= todo;
+	cxt->next_block += todo >> 9;
+}
+
+static inline void sil_m15w_restore_qc (struct ata_queued_cmd *qc)
+{
+	struct sil_m15w_cxt *cxt = qc->private_data;
+
+	DPRINTK("ENTER\n");
+
+	sg_dma_address(qc->sg) -= cxt->cur_sg_ofs;
+	sg_dma_len(qc->sg) += cxt->cur_sg_ofs;
+	if (cxt->next_sg_ofs)
+		sg_dma_len(cxt->next_sg) += cxt->next_sg_len;
+	qc->sg = cxt->orig_sg;
+	qc->n_elem = cxt->orig_nelem;
+	qc->flags |= cxt->orig_flags;
+	qc->complete_fn = cxt->orig_complete_fn;
+#ifdef M15W_DEBUG
+	{
+		int i, j;
+		for (i = 0; i < qc->n_elem; i++)
+			if (memcmp(&cxt->sg_copy[i], &qc->sg[i],
+				   sizeof(qc->sg[0])))
+				break;
+		if (i < qc->n_elem) {
+			printk(KERN_ERR "sil_m15w: sg mismatch\n");
+			printk(KERN_ERR "orig: ");
+			for (j = 0; j < qc->n_elem; j++)
+				printk("%s%08x:%04u ",
+				       i == j ? "*" : "",
+				       (u32)sg_dma_address(&cxt->sg_copy[j]),
+				       sg_dma_len(&cxt->sg_copy[j]));
+			printk("\n");
+			printk(KERN_ERR "used: ");
+			for (j = 0; j < qc->n_elem; j++)
+				printk("%s%08x:%04u ",
+				       i == j ? "*" : "",
+				       (u32)sg_dma_address(&qc->sg[j]),
+				       sg_dma_len(&qc->sg[j]));
+			printk("\n");
+		}
+	}
+#endif
+}
+
+static int sil_m15w_chunk_complete (struct ata_queued_cmd *qc, u8 drv_stat)
+{
+	struct sil_m15w_cxt *cxt = qc->private_data;
+
+	DPRINTK("ENTER\n");
+
+	/* This command is still active, turn ACTIVE back on */
+	qc->flags |= ATA_QCFLAG_ACTIVE;
+
+	if (unlikely(cxt->timedout))
+		drv_stat |= ATA_BUSY;	/* Any better error status? */
+
+	/* Complete the command immediately on error */
+	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
+		sil_m15w_restore_qc(qc);
+		ata_qc_complete(qc, drv_stat);
+		return 1;
+	}
+
+	sil_m15w_next(qc);
+
+	qc->flags |= cxt->orig_flags;
+	ata_qc_prep(qc);
+	qc->flags &= ~ATA_QCFLAG_DMAMAP;
+
+	/* On last iteration, restore fields such that normal
+	 * completion path is run */
+	if (!cxt->left)
+		sil_m15w_restore_qc(qc);
+	sil_ops.qc_issue(qc);
+	return 1;
+}
+
+static void sil_qc_prep (struct ata_queued_cmd *qc)
+{
+	struct sil_m15w_cxt *cxt = qc->private_data;
+
+	if (unlikely(cxt && qc->tf.flags & ATA_TFLAG_WRITE && qc->nsect > 15)) {
+		BUG_ON(cxt->left);
+		if (qc->tf.protocol == ATA_PROT_DMA) {
+			/* Okay, begin mod15write workaround */
+			cxt->next_block = sil_m15w_read_tf_block(&qc->tf);
+			cxt->next_sg = qc->sg;
+			cxt->left = qc->nsect << 9;
+			cxt->cur_sg_ofs = 0;
+			cxt->next_sg_ofs = 0;
+			cxt->next_sg_len = sg_dma_len(qc->sg);
+			cxt->timedout = 0;
+
+			/* Save fields we're gonna mess with.  Read comments
+			 * above struct sil_m15w_cxt for more info. */
+			cxt->orig_sg = qc->sg;
+			cxt->orig_nelem = qc->n_elem;
+			cxt->orig_flags = qc->flags & ATA_QCFLAG_DMAMAP;
+			cxt->orig_complete_fn = qc->complete_fn;
+			qc->complete_fn = sil_m15w_chunk_complete;
+#ifdef M15W_DEBUG
+			{
+				int i;
+				for (i = 0; i < qc->n_elem; i++)
+					cxt->sg_copy[i] = qc->sg[i];
+			}
+#endif
+			DPRINTK("MOD15WRITE, block=%llu nsect=%u\n",
+				cxt->next_block, qc->nsect);
+			sil_m15w_next(qc);
+
+			ata_qc_prep(qc);
+			qc->flags &= ~ATA_QCFLAG_DMAMAP;
+			return;
+		} else
+			printk(KERN_WARNING "ata%u(%u): write request > 15 "
+			       "issued using non-DMA protocol.  Drive may "
+			       "lock up.\n", qc->ap->id, qc->dev->devno);
+	}
+
+	ata_qc_prep(qc);
+}
+
+static void sil_eng_timeout (struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+
+	if (qc && qc->private_data) {
+		struct sil_m15w_cxt *cxt = qc->private_data;
+		if (cxt->left)
+			cxt->timedout = 1;
+	}
+
+	ata_eng_timeout(ap);
+}
+
 static inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_reg)
 {
 	unsigned long offset = ap->ioaddr.scr_addr;
@@ -278,6 +548,14 @@ static void sil_scr_write (struct ata_po
 		writel(val, mmio);
 }
 
+static void sil_host_stop (struct ata_host_set *host_set)
+{
+	/* Free mod15write context array. */
+	kfree(host_set->private_data);
+
+	ata_host_stop(host_set);
+}
+
 /**
  *	sil_dev_config - Apply device/host-specific errata fixups
  *	@ap: Port containing device to be examined
@@ -288,17 +566,12 @@ static void sil_scr_write (struct ata_po
  *	We apply two errata fixups which are specific to Silicon Image,
  *	a Seagate and a Maxtor fixup.
  *
- *	For certain Seagate devices, we must limit the maximum sectors
- *	to under 8K.
+ *	For certain Seagate devices, we cannot issue write requests
+ *	larger than 15 sectors.
  *
  *	For certain Maxtor devices, we must not program the drive
  *	beyond udma5.
  *
- *	Both fixups are unfairly pessimistic.  As soon as I get more
- *	information on these errata, I will create a more exhaustive
- *	list, and apply the fixups to only the specific
- *	devices/hosts/firmwares that need it.
- *
  *	20040111 - Seagate drives affected by the Mod15Write bug are blacklisted
  *	The Maxtor quirk is in the blacklist, but I'm keeping the original
  *	pessimistic fix for the following reasons...
@@ -306,6 +579,15 @@ static void sil_scr_write (struct ata_po
  *	Windows	driver, maybe only one is affected.  More info would be greatly
  *	appreciated.
  *	- But then again UDMA5 is hardly anything to complain about
+ *
+ *	20050316 Tejun Heo - Proper Mod15Write workaround implemented.
+ *	sata_sil doesn't report affected Seagate drives as having max
+ *	sectors of 15 anymore, but handle write requests larger than
+ *	15 sectors by looping over it inside this driver proper.  This
+ *	is messy but it's better to isolate this kind of peculiar bug
+ *	handling inside individual drivers than tainting libata layer.
+ *	This workaround results in unhampered read performance and
+ *	much better write performance.
  */
 static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
 {
@@ -313,6 +595,7 @@ static void sil_dev_config(struct ata_po
 	unsigned char model_num[40];
 	const char *s;
 	unsigned int len;
+	int i;
 
 	ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
 			  sizeof(model_num));
@@ -330,15 +613,23 @@ static void sil_dev_config(struct ata_po
 			break;
 		}
 	
-	/* limit requests to 15 sectors */
+	/* Activate mod15write quirk workaround */
 	if (quirks & SIL_QUIRK_MOD15WRITE) {
+		struct sil_m15w_cxt *cxt;
+
 		printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
 		       ap->id, dev->devno);
-		ap->host->max_sectors = 15;
-		ap->host->hostt->max_sectors = 15;
-		dev->flags |= ATA_DFLAG_LOCK_SECTORS;
+
+		cxt = ap->host_set->private_data;
+		cxt += ap->port_no * ATA_MAX_QUEUE;
+		for (i = 0; i < ATA_MAX_QUEUE; i++)
+			ap->qcmd[i].private_data = cxt++;
+
 		return;
 	}
+	/* Clear qcmd->private_data if mod15write quirk isn't present */
+	for (i = 0; i < ATA_MAX_QUEUE; i++)
+		ap->qcmd[i].private_data = NULL;
 
 	/* limit to udma5 */
 	if (quirks & SIL_QUIRK_UDMA5MAX) {
@@ -352,7 +643,8 @@ static void sil_dev_config(struct ata_po
 static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
-	struct ata_probe_ent *probe_ent = NULL;
+	struct ata_probe_ent *probe_ent;
+	struct sil_m15w_cxt *m15w_cxt;
 	unsigned long base;
 	void *mmio_base;
 	int rc;
@@ -385,11 +677,17 @@ static int sil_init_one (struct pci_dev 
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-	if (probe_ent == NULL) {
-		rc = -ENOMEM;
+	rc = -ENOMEM;
+
+	tmp = sizeof(m15w_cxt[0]) * ATA_MAX_PORTS * ATA_MAX_QUEUE;
+	m15w_cxt = kmalloc(tmp, GFP_KERNEL);
+	if (m15w_cxt == NULL)
 		goto err_out_regions;
-	}
+	memset(m15w_cxt, 0, tmp);
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL)
+		goto err_out_free_m15w;
 
 	memset(probe_ent, 0, sizeof(*probe_ent));
 	INIT_LIST_HEAD(&probe_ent->node);
@@ -403,6 +701,7 @@ static int sil_init_one (struct pci_dev 
        	probe_ent->irq = pdev->irq;
        	probe_ent->irq_flags = SA_SHIRQ;
 	probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags;
+	probe_ent->private_data = m15w_cxt;
 
 	mmio_base = ioremap(pci_resource_start(pdev, 5),
 		            pci_resource_len(pdev, 5));
@@ -479,6 +778,8 @@ static int sil_init_one (struct pci_dev 
 
 err_out_free_ent:
 	kfree(probe_ent);
+err_out_free_m15w:
+	kfree(m15w_cxt);
 err_out_regions:
 	pci_release_regions(pdev);
 err_out:


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13
  2005-07-28 14:12 ` [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13 Tejun Heo
@ 2005-08-21 19:19   ` Jeff Garzik
  2005-08-21 20:45     ` Tejun Heo
  2005-08-21 19:34   ` [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13 Jeff Garzik
  1 sibling, 1 reply; 15+ messages in thread
From: Jeff Garzik @ 2005-08-21 19:19 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Michael Madore, linux-ide, albertcc

Tejun Heo wrote:
> Also, Jeff, I know you're very busy, but what do you think about
> taking m15w workaround into ata tree?  It's been around for a while
> now and I haven't received any complaints (except for this one) yet.
> The workaround is ugly but it surely helps and I'm willing to maintain
> it.

I think your mod15write solution is too messy to deal with long-term. 
Maintenance burden is much lower on us without it.  It's not too 
difficult to simply avoid certain combinations of hardware.

Note!  As Carlos @ Silicon Image points out, the blacklist should only 
apply to SiI 3112, not 3512/3114/etc.  That's an open FIXME that would 
benefit users.


>  One thing that bothers me is how Albert's commit and the original
> ata_host_intr tell IRQ subsystem that an interrupt isn't ours when we
> know that we have generated a spurious interrupt.  IMHO, we always
> should enter ata_host_intr and always tell IRQ subsystem that it's our
> interrupt if bmdma_status tells us so, regardless of ata status value.
> The current code is likely to cause "nobody cared" error which can be
> avoided.

If there is a mismatch between BMDMA's IRQ bit and ATA device indicating 
an interrupt, that's a host state machine[1] violation that should be 
addressed elsewhere.

I wouldn't mind using BMDMA IRQ bit as an indicator of the ATA intrq 
status, though.

(for others) As linked on

	http://www.t13.org/project/d1510r1-Host-Adapter.pdf
		via
	http://linux.yyz.us/sata/devel.html

you can find documentation on the BMDMA IRQ bit.

The main problem with using BMDMA IRQ bit is that it is likely never set 
unless the commands are READ/WRITE DMA commands, which means we must 
have separate host state machine tracking for PIO and non-data commands, 
increasing complexity.

	Jeff



[1] "host state machine"  These are illustrated by the state machine 
diagrams in ATA/ATAPI-7 Volume 3, under the chapter headings "Bus idle 
protocol", "Non-data command protocol", "DMA command protocol", "Ultra 
DMA data-{in,out} command protocol".  STUDY THESE.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13
  2005-07-28 14:12 ` [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13 Tejun Heo
  2005-08-21 19:19   ` Jeff Garzik
@ 2005-08-21 19:34   ` Jeff Garzik
  2005-08-21 19:56     ` Tejun Heo
  1 sibling, 1 reply; 15+ messages in thread
From: Jeff Garzik @ 2005-08-21 19:34 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Michael Madore, linux-ide, albertcc, Douglas Gilbert

Tejun Heo wrote:
>  sata_sil Mod15Write workaround was broken by the following commit by
> Albert Lee.
> 
> Commit: 21b1ed74ee3667dcabcba92e486988ea9119a085
> [PATCH] libata: Prevent the interrupt handler from completing a command twice
> 
>  This commit clears ATA_QCFLAG_ACTIVE in ata_qc_complete() and doesn't
> handle IRQ if ATA_QCFLAG_ACTIVE is cleared on entry to interrupt
> routine.  As m15w workaround executes single command multiple times,
> the flag is cleared after the first chunk completion and the following
> interrupt gets ignored resulting in "nobody cared" interrupt error.
> 
>  The following changes are made in m15w workaround to fix this.
> 
>  * Moved clearing of ATA_QCFLAG_ACTIVE before invoking ->complete_fn,
>    so that ->complete_fn can mangle with the flag.  This doesn't affect
>    any users.
>  * Added setting ATA_QCFLAG_ACTIVE in m15w chunk completion function.

> diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
> --- a/drivers/scsi/libata-core.c
> +++ b/drivers/scsi/libata-core.c
> @@ -3087,8 +3087,8 @@ void ata_qc_complete(struct ata_queued_c
>  		ata_sg_clean(qc);
>  
>  	/* call completion callback */
> -	rc = qc->complete_fn(qc, drv_stat);
>  	qc->flags &= ~ATA_QCFLAG_ACTIVE;
> +	rc = qc->complete_fn(qc, drv_stat);
>  
>  	/* if callback indicates not to complete command (non-zero),
>  	 * return immediately


I'm leaning towards applying latest Albert's ATA_QCFLAG_ACTIVE fix, 
which does the same thing your patch did.

For various complex tasks in the SCSI translation layer (SAT), we may 
wish to issue multiple ATA commands, before signalling completion.  As 
your mod15write patch is an example of this, it helps point out what 
parts of libata need work in order to accomplish this.

Any comments before I apply Albert's patch?

	Jeff





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13
  2005-08-21 19:34   ` [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13 Jeff Garzik
@ 2005-08-21 19:56     ` Tejun Heo
  2005-08-21 20:11       ` Jeff Garzik
  0 siblings, 1 reply; 15+ messages in thread
From: Tejun Heo @ 2005-08-21 19:56 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Michael Madore, linux-ide, albertcc, Douglas Gilbert


  Hi, Jeff.

Jeff Garzik wrote:
> Tejun Heo wrote:
> 
>>  sata_sil Mod15Write workaround was broken by the following commit by
>> Albert Lee.
>>
>> Commit: 21b1ed74ee3667dcabcba92e486988ea9119a085
>> [PATCH] libata: Prevent the interrupt handler from completing a 
>> command twice
>>
>>  This commit clears ATA_QCFLAG_ACTIVE in ata_qc_complete() and doesn't
>> handle IRQ if ATA_QCFLAG_ACTIVE is cleared on entry to interrupt
>> routine.  As m15w workaround executes single command multiple times,
>> the flag is cleared after the first chunk completion and the following
>> interrupt gets ignored resulting in "nobody cared" interrupt error.
>>
>>  The following changes are made in m15w workaround to fix this.
>>
>>  * Moved clearing of ATA_QCFLAG_ACTIVE before invoking ->complete_fn,
>>    so that ->complete_fn can mangle with the flag.  This doesn't affect
>>    any users.
>>  * Added setting ATA_QCFLAG_ACTIVE in m15w chunk completion function.
> 
> 
>> diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
>> --- a/drivers/scsi/libata-core.c
>> +++ b/drivers/scsi/libata-core.c
>> @@ -3087,8 +3087,8 @@ void ata_qc_complete(struct ata_queued_c
>>          ata_sg_clean(qc);
>>  
>>      /* call completion callback */
>> -    rc = qc->complete_fn(qc, drv_stat);
>>      qc->flags &= ~ATA_QCFLAG_ACTIVE;
>> +    rc = qc->complete_fn(qc, drv_stat);
>>  
>>      /* if callback indicates not to complete command (non-zero),
>>       * return immediately
> 
> 
> 
> I'm leaning towards applying latest Albert's ATA_QCFLAG_ACTIVE fix, 
> which does the same thing your patch did.
> 
> For various complex tasks in the SCSI translation layer (SAT), we may 
> wish to issue multiple ATA commands, before signalling completion.  As 
> your mod15write patch is an example of this, it helps point out what 
> parts of libata need work in order to accomplish this.
> 
> Any comments before I apply Albert's patch?
> 

  I think the following patch I've posted deal with the same problem.

http://marc.theaimsgroup.com/?l=linux-ide&m=112454734102242&w=2

  Which, I think, is a better way to fix it.  It's dependant on the 
previous patchset you've just NAK'ed, so it cannot be applied but please 
take a look.  The base of the problem is that we run both 
ata_qc_complete and EH concurrently.

-- 
tejun

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13
  2005-08-21 19:56     ` Tejun Heo
@ 2005-08-21 20:11       ` Jeff Garzik
  0 siblings, 0 replies; 15+ messages in thread
From: Jeff Garzik @ 2005-08-21 20:11 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Michael Madore, linux-ide, albertcc, Douglas Gilbert

Tejun Heo wrote:
> 
>  Hi, Jeff.
> 
> Jeff Garzik wrote:
> 
>> Tejun Heo wrote:
>>
>>>  sata_sil Mod15Write workaround was broken by the following commit by
>>> Albert Lee.
>>>
>>> Commit: 21b1ed74ee3667dcabcba92e486988ea9119a085
>>> [PATCH] libata: Prevent the interrupt handler from completing a 
>>> command twice
>>>
>>>  This commit clears ATA_QCFLAG_ACTIVE in ata_qc_complete() and doesn't
>>> handle IRQ if ATA_QCFLAG_ACTIVE is cleared on entry to interrupt
>>> routine.  As m15w workaround executes single command multiple times,
>>> the flag is cleared after the first chunk completion and the following
>>> interrupt gets ignored resulting in "nobody cared" interrupt error.
>>>
>>>  The following changes are made in m15w workaround to fix this.
>>>
>>>  * Moved clearing of ATA_QCFLAG_ACTIVE before invoking ->complete_fn,
>>>    so that ->complete_fn can mangle with the flag.  This doesn't affect
>>>    any users.
>>>  * Added setting ATA_QCFLAG_ACTIVE in m15w chunk completion function.
>>
>>
>>
>>> diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
>>> --- a/drivers/scsi/libata-core.c
>>> +++ b/drivers/scsi/libata-core.c
>>> @@ -3087,8 +3087,8 @@ void ata_qc_complete(struct ata_queued_c
>>>          ata_sg_clean(qc);
>>>  
>>>      /* call completion callback */
>>> -    rc = qc->complete_fn(qc, drv_stat);
>>>      qc->flags &= ~ATA_QCFLAG_ACTIVE;
>>> +    rc = qc->complete_fn(qc, drv_stat);
>>>  
>>>      /* if callback indicates not to complete command (non-zero),
>>>       * return immediately
>>
>>
>>
>>
>> I'm leaning towards applying latest Albert's ATA_QCFLAG_ACTIVE fix, 
>> which does the same thing your patch did.
>>
>> For various complex tasks in the SCSI translation layer (SAT), we may 
>> wish to issue multiple ATA commands, before signalling completion.  As 
>> your mod15write patch is an example of this, it helps point out what 
>> parts of libata need work in order to accomplish this.
>>
>> Any comments before I apply Albert's patch?
>>
> 
>  I think the following patch I've posted deal with the same problem.
> 
> http://marc.theaimsgroup.com/?l=linux-ide&m=112454734102242&w=2


In the SCSI translation layer (SAT), some simulation may require issuing 
multiple ATA commands, before indicating a completion to the upper 
layers.  That capability is something I definitely want libata to 
support.  Your mod15write patch is an excellent example of this, even 
though I NAK'd it due to long term sata_sil maintenance burden.

That's why I think move ATA_QCFLAG_ACTIVE -anyway- may be a good idea.

	Jeff



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13
  2005-08-21 19:19   ` Jeff Garzik
@ 2005-08-21 20:45     ` Tejun Heo
  2005-08-21 21:10       ` Jeff Garzik
  0 siblings, 1 reply; 15+ messages in thread
From: Tejun Heo @ 2005-08-21 20:45 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Michael Madore, linux-ide, albertcc


  Hello, Jeff.

Jeff Garzik wrote:
> Tejun Heo wrote:
> 
>> Also, Jeff, I know you're very busy, but what do you think about
>> taking m15w workaround into ata tree?  It's been around for a while
>> now and I haven't received any complaints (except for this one) yet.
>> The workaround is ugly but it surely helps and I'm willing to maintain
>> it.
> 
> 
> I think your mod15write solution is too messy to deal with long-term. 
> Maintenance burden is much lower on us without it.  It's not too 
> difficult to simply avoid certain combinations of hardware.
> 

  No problem, I'll maintain it out of tree.

> Note!  As Carlos @ Silicon Image points out, the blacklist should only 
> apply to SiI 3112, not 3512/3114/etc.  That's an open FIXME that would 
> benefit users.
> 

  Cool, I'll submit a patch right away.

> 
>>  One thing that bothers me is how Albert's commit and the original
>> ata_host_intr tell IRQ subsystem that an interrupt isn't ours when we
>> know that we have generated a spurious interrupt.  IMHO, we always
>> should enter ata_host_intr and always tell IRQ subsystem that it's our
>> interrupt if bmdma_status tells us so, regardless of ata status value.
>> The current code is likely to cause "nobody cared" error which can be
>> avoided.
> 
> 
> If there is a mismatch between BMDMA's IRQ bit and ATA device indicating 
> an interrupt, that's a host state machine[1] violation that should be 
> addressed elsewhere.
> 
> I wouldn't mind using BMDMA IRQ bit as an indicator of the ATA intrq 
> status, though.
> 
> (for others) As linked on
> 
>     http://www.t13.org/project/d1510r1-Host-Adapter.pdf
>         via
>     http://linux.yyz.us/sata/devel.html
> 
> you can find documentation on the BMDMA IRQ bit.
> 
> The main problem with using BMDMA IRQ bit is that it is likely never set 
> unless the commands are READ/WRITE DMA commands, which means we must 
> have separate host state machine tracking for PIO and non-data commands, 
> increasing complexity.
> 
>     Jeff
> 
> 
> 
> [1] "host state machine"  These are illustrated by the state machine 
> diagrams in ATA/ATAPI-7 Volume 3, under the chapter headings "Bus idle 
> protocol", "Non-data command protocol", "DMA command protocol", "Ultra 
> DMA data-{in,out} command protocol".  STUDY THESE.

  Yeap, I'll.

-- 
tejun

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13
  2005-08-21 20:45     ` Tejun Heo
@ 2005-08-21 21:10       ` Jeff Garzik
  2005-08-21 21:44         ` Tejun Heo
  0 siblings, 1 reply; 15+ messages in thread
From: Jeff Garzik @ 2005-08-21 21:10 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Michael Madore, linux-ide, albertcc

Tejun Heo wrote:
> Jeff Garzik wrote:
>> Tejun Heo wrote:
>>> Also, Jeff, I know you're very busy, but what do you think about
>>> taking m15w workaround into ata tree?  It's been around for a while
>>> now and I haven't received any complaints (except for this one) yet.
>>> The workaround is ugly but it surely helps and I'm willing to maintain
>>> it.

>> I think your mod15write solution is too messy to deal with long-term. 
>> Maintenance burden is much lower on us without it.  It's not too 
>> difficult to simply avoid certain combinations of hardware.

>  No problem, I'll maintain it out of tree.

You're welcome to maintain it as an independent branch of 
libata-dev.git, if you would prefer.


>> Note!  As Carlos @ Silicon Image points out, the blacklist should only 
>> apply to SiI 3112, not 3512/3114/etc.  That's an open FIXME that would 
>> benefit users.

>  Cool, I'll submit a patch right away.

Thanks,

	Jeff



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13
  2005-08-21 21:10       ` Jeff Garzik
@ 2005-08-21 21:44         ` Tejun Heo
  2005-08-22 10:19           ` Bartlomiej Zolnierkiewicz
  0 siblings, 1 reply; 15+ messages in thread
From: Tejun Heo @ 2005-08-21 21:44 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Michael Madore, linux-ide, albertcc


  Hello, Jeff.

Jeff Garzik wrote:
> Tejun Heo wrote:
> 
>> Jeff Garzik wrote:
>>
>>> Tejun Heo wrote:
>>>
>>>> Also, Jeff, I know you're very busy, but what do you think about
>>>> taking m15w workaround into ata tree?  It's been around for a while
>>>> now and I haven't received any complaints (except for this one) yet.
>>>> The workaround is ugly but it surely helps and I'm willing to maintain
>>>> it.
> 
> 
>>> I think your mod15write solution is too messy to deal with long-term. 
>>> Maintenance burden is much lower on us without it.  It's not too 
>>> difficult to simply avoid certain combinations of hardware.
> 
> 
>>  No problem, I'll maintain it out of tree.
> 
> 
> You're welcome to maintain it as an independent branch of 
> libata-dev.git, if you would prefer.
> 

  I think I'll just keep it out of tree.  I don't think many libata 
developers would be interested in m15w workaround.

> 
>>> Note!  As Carlos @ Silicon Image points out, the blacklist should 
>>> only apply to SiI 3112, not 3512/3114/etc.  That's an open FIXME that 
>>> would benefit users.
> 
> 
>>  Cool, I'll submit a patch right away.
> 

  Can you please tell me which are affected and which are not?

	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
	{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
	{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },

  Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13
  2005-08-21 21:44         ` Tejun Heo
@ 2005-08-22 10:19           ` Bartlomiej Zolnierkiewicz
  2005-08-22 11:46             ` [PATCH libata:upstream] sil: apply M15W quirk selectively Tejun Heo
  0 siblings, 1 reply; 15+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2005-08-22 10:19 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jeff Garzik, Michael Madore, linux-ide, albertcc

On 8/21/05, Tejun Heo <htejun@gmail.com> wrote:
> 
>   Hello, Jeff.
> 
> Jeff Garzik wrote:
> > Tejun Heo wrote:
> >
> >> Jeff Garzik wrote:
> >>
> >>> Tejun Heo wrote:
> >>>
> >>>> Also, Jeff, I know you're very busy, but what do you think about
> >>>> taking m15w workaround into ata tree?  It's been around for a while
> >>>> now and I haven't received any complaints (except for this one) yet.
> >>>> The workaround is ugly but it surely helps and I'm willing to maintain
> >>>> it.
> >
> >
> >>> I think your mod15write solution is too messy to deal with long-term.
> >>> Maintenance burden is much lower on us without it.  It's not too
> >>> difficult to simply avoid certain combinations of hardware.
> >
> >
> >>  No problem, I'll maintain it out of tree.
> >
> >
> > You're welcome to maintain it as an independent branch of
> > libata-dev.git, if you would prefer.
> >
> 
>   I think I'll just keep it out of tree.  I don't think many libata
> developers would be interested in m15w workaround.
> 
> >
> >>> Note!  As Carlos @ Silicon Image points out, the blacklist should
> >>> only apply to SiI 3112, not 3512/3114/etc.  That's an open FIXME that
> >>> would benefit users.

Weird, Windows drivers (at least *.INF files) seem to apply workarounds
to both 3112 and 3512 while 3114 is OK.

> >
> >
> >>  Cool, I'll submit a patch right away.
> >
> 
>   Can you please tell me which are affected and which are not?

What about fixing 3114 for a start? :-)

>         { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
>         { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
>         { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
>         { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
>         { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
>         { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
>         { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
> 
>   Thanks.

Bartlomiej

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH libata:upstream] sil: apply M15W quirk selectively
  2005-08-22 10:19           ` Bartlomiej Zolnierkiewicz
@ 2005-08-22 11:46             ` Tejun Heo
  2005-08-22 19:36               ` Jeff Garzik
  0 siblings, 1 reply; 15+ messages in thread
From: Tejun Heo @ 2005-08-22 11:46 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: Jeff Garzik, Michael Madore, linux-ide, albertcc

 Hello, Jeff & Bartlomiej & all.

> What about fixing 3114 for a start? :-)

 Yeap, why not?  Here it is.
--

 This patch adds chipset mask to sil_blacklist such that quirks can be
applied selectively depending on chipset.  And add sil_3112_m15w
chipset which is identical to sil_3112 except that mod15write quirk is
applied.  As we don't know which PCI IDs are affected yet, I've
changed all 3112's to sil_3112_m15w.  Later when we know which PCI IDs
are affected, we can just change them to sil_3112 later.


Signed-off-by: Tejun Heo <htejun@gmail.com>


diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -41,8 +41,10 @@
 #define DRV_VERSION	"0.9"
 
 enum {
-	sil_3112		= 0,
-	sil_3114		= 1,
+	sil_3112_m15w		= (1 << 0),
+	sil_3112		= (1 << 1),
+	sil_3114		= (1 << 2),
+	sil_all			= 0xffffffff,
 
 	SIL_FIFO_R0		= 0x40,
 	SIL_FIFO_W0		= 0x41,
@@ -76,38 +78,39 @@ static void sil_scr_write (struct ata_po
 static void sil_post_set_mode (struct ata_port *ap);
 
 static struct pci_device_id sil_pci_tbl[] = {
-	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+	{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
 	{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
-	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
 	{ }	/* terminate list */
 };
 
 
 /* TODO firmware versions should be added - eric */
-static const struct sil_drivelist {
-	const char * product;
+static const struct sil_blacklist {
+	int chipmask;
+	const char * drive;
 	unsigned int quirk;
 } sil_blacklist [] = {
-	{ "ST320012AS",		SIL_QUIRK_MOD15WRITE },
-	{ "ST330013AS",		SIL_QUIRK_MOD15WRITE },
-	{ "ST340017AS",		SIL_QUIRK_MOD15WRITE },
-	{ "ST360015AS",		SIL_QUIRK_MOD15WRITE },
-	{ "ST380013AS",		SIL_QUIRK_MOD15WRITE },
-	{ "ST380023AS",		SIL_QUIRK_MOD15WRITE },
-	{ "ST3120023AS",	SIL_QUIRK_MOD15WRITE },
-	{ "ST3160023AS",	SIL_QUIRK_MOD15WRITE },
-	{ "ST3120026AS",	SIL_QUIRK_MOD15WRITE },
-	{ "ST3200822AS",	SIL_QUIRK_MOD15WRITE },
-	{ "ST340014ASL",	SIL_QUIRK_MOD15WRITE },
-	{ "ST360014ASL",	SIL_QUIRK_MOD15WRITE },
-	{ "ST380011ASL",	SIL_QUIRK_MOD15WRITE },
-	{ "ST3120022ASL",	SIL_QUIRK_MOD15WRITE },
-	{ "ST3160021ASL",	SIL_QUIRK_MOD15WRITE },
-	{ "Maxtor 4D060H3",	SIL_QUIRK_UDMA5MAX },
+	{ sil_3112_m15w, "ST320012AS",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST330013AS",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST340017AS",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST360015AS",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST380013AS",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST380023AS",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST3120023AS",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST3160023AS",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST3120026AS",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST3200822AS",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST340014ASL",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST360014ASL",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST380011ASL",		SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST3120022ASL",	SIL_QUIRK_MOD15WRITE },
+	{ sil_3112_m15w, "ST3160021ASL",	SIL_QUIRK_MOD15WRITE },
+	{ sil_all,	 "Maxtor 4D060H3",	SIL_QUIRK_UDMA5MAX },
 	{ }
 };
 
@@ -165,7 +168,16 @@ static struct ata_port_operations sil_op
 };
 
 static struct ata_port_info sil_port_info[] = {
-	/* sil_3112 */
+	/* sil_3112_m15w, keep it sync'd w/ sil_3112 */
+	{
+		.sht		= &sil_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil_ops,
+	}, /* sil_3112 */
 	{
 		.sht		= &sil_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
@@ -309,6 +321,7 @@ static void sil_scr_write (struct ata_po
  */
 static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
 {
+	int chip = (int)ap->host_set->private_data;
 	unsigned int n, quirks = 0;
 	unsigned char model_num[40];
 	const char *s;
@@ -323,9 +336,10 @@ static void sil_dev_config(struct ata_po
 	while ((len > 0) && (s[len - 1] == ' '))
 		len--;
 
-	for (n = 0; sil_blacklist[n].product; n++)
-		if (!memcmp(sil_blacklist[n].product, s,
-			    strlen(sil_blacklist[n].product))) {
+	for (n = 0; sil_blacklist[n].drive; n++)
+		if ((sil_blacklist[n].chipmask & chip) &&
+		    !memcmp(sil_blacklist[n].drive, s,
+			    strlen(sil_blacklist[n].drive))) {
 			quirks = sil_blacklist[n].quirk;
 			break;
 		}
@@ -403,6 +417,7 @@ static int sil_init_one (struct pci_dev 
        	probe_ent->irq = pdev->irq;
        	probe_ent->irq_flags = SA_SHIRQ;
 	probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags;
+	probe_ent->private_data = (void *)ent->driver_data;
 
 	mmio_base = ioremap(pci_resource_start(pdev, 5),
 		            pci_resource_len(pdev, 5));

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH libata:upstream] sil: apply M15W quirk selectively
  2005-08-22 11:46             ` [PATCH libata:upstream] sil: apply M15W quirk selectively Tejun Heo
@ 2005-08-22 19:36               ` Jeff Garzik
  2005-08-22 21:39                 ` Tejun Heo
  0 siblings, 1 reply; 15+ messages in thread
From: Jeff Garzik @ 2005-08-22 19:36 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Bartlomiej Zolnierkiewicz, Michael Madore, linux-ide, albertcc

Tejun Heo wrote:
>  Hello, Jeff & Bartlomiej & all.
> 
> 
>>What about fixing 3114 for a start? :-)
> 
> 
>  Yeap, why not?  Here it is.
> --
> 
>  This patch adds chipset mask to sil_blacklist such that quirks can be
> applied selectively depending on chipset.  And add sil_3112_m15w
> chipset which is identical to sil_3112 except that mod15write quirk is
> applied.  As we don't know which PCI IDs are affected yet, I've
> changed all 3112's to sil_3112_m15w.  Later when we know which PCI IDs
> are affected, we can just change them to sil_3112 later.
> 
> 
> Signed-off-by: Tejun Heo <htejun@gmail.com>

Thanks for tackling this.  I would approach it in a different manner:

1) add to the enum at the top,
+	SIL_FLAG_M15W		= (1 << 30),

2) do
         sil_3112                = 0,
-       sil_3114                = 1,
+	sil_3112_m15w		= 1,
+	sil_3114		= 2,


3) in sil_pci_tbl[], change all the sil_3112 entries to sil_3112_m15w, 
EXCEPT for PCI ID 0x1095, 0x3512, which should remain sil_3112.



4) in sil_port_info[], duplicate sil_3112 entry to new entry 
sil_3112_m15w.  make sure order in sil_port_info[] array matches the 
values in step #2.


5) add SIL_FLAG_M15W to the list of host_flags in the new sil_3112_m15w 
entry created in step #4.


6) in sil_dev_config(), change
        if (quirks & SIL_QUIRK_MOD15WRITE) {
test to also test (ap->flags & SIL_FLAG_M15W)


Check over these steps to see if I missing anything...  at the very 
least, I have illustrated the approach that should be taken.

	Jeff



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH libata:upstream] sil: apply M15W quirk selectively
  2005-08-22 19:36               ` Jeff Garzik
@ 2005-08-22 21:39                 ` Tejun Heo
  2005-08-22 21:45                   ` Jeff Garzik
  2005-08-22 22:27                   ` [PATCH libata:upstream] sil: apply M15W quirk selectively (take 2) Tejun Heo
  0 siblings, 2 replies; 15+ messages in thread
From: Tejun Heo @ 2005-08-22 21:39 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Bartlomiej Zolnierkiewicz, Michael Madore, linux-ide, albertcc

 Hi, Jeff.

 My posted patch is broken anyway.  I was indexing sil_port_info w/
bit masks.  :-(

On Mon, Aug 22, 2005 at 03:36:57PM -0400, Jeff Garzik wrote:
> Tejun Heo wrote:
> > Hello, Jeff & Bartlomiej & all.
> >
> >
> >>What about fixing 3114 for a start? :-)
> >
> >
> > Yeap, why not?  Here it is.
> >--
> >
> > This patch adds chipset mask to sil_blacklist such that quirks can be
> >applied selectively depending on chipset.  And add sil_3112_m15w
> >chipset which is identical to sil_3112 except that mod15write quirk is
> >applied.  As we don't know which PCI IDs are affected yet, I've
> >changed all 3112's to sil_3112_m15w.  Later when we know which PCI IDs
> >are affected, we can just change them to sil_3112 later.
> >
> >
> >Signed-off-by: Tejun Heo <htejun@gmail.com>
> 
> Thanks for tackling this.  I would approach it in a different manner:
> 
> 1) add to the enum at the top,
> +	SIL_FLAG_M15W		= (1 << 30),
> 
> 2) do
>         sil_3112                = 0,
> -       sil_3114                = 1,
> +	sil_3112_m15w		= 1,
> +	sil_3114		= 2,
> 
> 
> 3) in sil_pci_tbl[], change all the sil_3112 entries to sil_3112_m15w, 
> EXCEPT for PCI ID 0x1095, 0x3512, which should remain sil_3112.
> 
> 
> 
> 4) in sil_port_info[], duplicate sil_3112 entry to new entry 
> sil_3112_m15w.  make sure order in sil_port_info[] array matches the 
> values in step #2.
> 
> 
> 5) add SIL_FLAG_M15W to the list of host_flags in the new sil_3112_m15w 
> entry created in step #4.

 Can we use host_flags for that?  It seems that it's for ATA_FLAG_*
flags, and we currently don't explicitly reserve any bits from
ATA_FLAG_*.

> 
> 
> 6) in sil_dev_config(), change
>        if (quirks & SIL_QUIRK_MOD15WRITE) {
> test to also test (ap->flags & SIL_FLAG_M15W)
> 
> 
> Check over these steps to see if I missing anything...  at the very 
> least, I have illustrated the approach that should be taken.
> 
> 	Jeff
> 

 Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH libata:upstream] sil: apply M15W quirk selectively
  2005-08-22 21:39                 ` Tejun Heo
@ 2005-08-22 21:45                   ` Jeff Garzik
  2005-08-22 22:27                   ` [PATCH libata:upstream] sil: apply M15W quirk selectively (take 2) Tejun Heo
  1 sibling, 0 replies; 15+ messages in thread
From: Jeff Garzik @ 2005-08-22 21:45 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Bartlomiej Zolnierkiewicz, Michael Madore, linux-ide, albertcc

Tejun Heo wrote:
> On Mon, Aug 22, 2005 at 03:36:57PM -0400, Jeff Garzik wrote:
>>Tejun Heo wrote:

>>5) add SIL_FLAG_M15W to the list of host_flags in the new sil_3112_m15w 
>>entry created in step #4.

>  Can we use host_flags for that?  It seems that it's for ATA_FLAG_*
> flags, and we currently don't explicitly reserve any bits from
> ATA_FLAG_*.

The drivers are free to use the upper bits of ap->flags for their own 
purposes.  ata_piix.c is an example of this, with PIIX_FLAG_xxx.

We can worry about bitspace collision when libata general flags and 
driver-specific flags get so numerous its a problem.

	Jeff




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH libata:upstream] sil: apply M15W quirk selectively (take 2)
  2005-08-22 21:39                 ` Tejun Heo
  2005-08-22 21:45                   ` Jeff Garzik
@ 2005-08-22 22:27                   ` Tejun Heo
  2005-08-23  5:06                     ` Jeff Garzik
  1 sibling, 1 reply; 15+ messages in thread
From: Tejun Heo @ 2005-08-22 22:27 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Bartlomiej Zolnierkiewicz, Michael Madore, linux-ide, albertcc

 As SII reports that only original 3112's are affected by M15W quirk,
This patch adds SIL_FLAG_MOD15WRITE to selectively apply M15W quirk
depending on chipsets.  As of yet, we don't know exactly which PCI IDs
are for original 3112, so M15W quirk is applied to all except for 3512
and 3124.  Once more info is avaliable, we can change some of these
sil_3112_m15w's to sil_3112.

Signed-off-by: Tejun Heo <htejun@gmail.com>

diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -41,8 +41,11 @@
 #define DRV_VERSION	"0.9"
 
 enum {
+	SIL_FLAG_MOD15WRITE	= (1 << 30),
+
 	sil_3112		= 0,
-	sil_3114		= 1,
+	sil_3112_m15w		= 1,
+	sil_3114		= 2,
 
 	SIL_FIFO_R0		= 0x40,
 	SIL_FIFO_W0		= 0x41,
@@ -76,13 +79,13 @@ static void sil_scr_write (struct ata_po
 static void sil_post_set_mode (struct ata_port *ap);
 
 static struct pci_device_id sil_pci_tbl[] = {
-	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
 	{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
 	{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
-	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
 	{ }	/* terminate list */
 };
 
@@ -174,6 +177,16 @@ static struct ata_port_info sil_port_inf
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
 		.port_ops	= &sil_ops,
+	}, /* sil_3112_15w - keep it sync'd w/ sil_3112 */
+	{
+		.sht		= &sil_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SRST | ATA_FLAG_MMIO |
+				  SIL_FLAG_MOD15WRITE,
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil_ops,
 	}, /* sil_3114 */
 	{
 		.sht		= &sil_sht,
@@ -331,7 +344,7 @@ static void sil_dev_config(struct ata_po
 		}
 
 	/* limit requests to 15 sectors */
-	if (quirks & SIL_QUIRK_MOD15WRITE) {
+	if (ap->flags & SIL_FLAG_MOD15WRITE && quirks & SIL_QUIRK_MOD15WRITE) {
 		printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
 		       ap->id, dev->devno);
 		ap->host->max_sectors = 15;

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH libata:upstream] sil: apply M15W quirk selectively (take 2)
  2005-08-22 22:27                   ` [PATCH libata:upstream] sil: apply M15W quirk selectively (take 2) Tejun Heo
@ 2005-08-23  5:06                     ` Jeff Garzik
  0 siblings, 0 replies; 15+ messages in thread
From: Jeff Garzik @ 2005-08-23  5:06 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Bartlomiej Zolnierkiewicz, Michael Madore, linux-ide, albertcc

applied


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2005-08-23  5:06 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1121894035.4885.15.camel@drevil.aslab.com>
2005-07-28 14:12 ` [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13 Tejun Heo
2005-08-21 19:19   ` Jeff Garzik
2005-08-21 20:45     ` Tejun Heo
2005-08-21 21:10       ` Jeff Garzik
2005-08-21 21:44         ` Tejun Heo
2005-08-22 10:19           ` Bartlomiej Zolnierkiewicz
2005-08-22 11:46             ` [PATCH libata:upstream] sil: apply M15W quirk selectively Tejun Heo
2005-08-22 19:36               ` Jeff Garzik
2005-08-22 21:39                 ` Tejun Heo
2005-08-22 21:45                   ` Jeff Garzik
2005-08-22 22:27                   ` [PATCH libata:upstream] sil: apply M15W quirk selectively (take 2) Tejun Heo
2005-08-23  5:06                     ` Jeff Garzik
2005-08-21 19:34   ` [PATCH linux-2.6.13-rc3] Mod15Write quirk against v2.6.13 Jeff Garzik
2005-08-21 19:56     ` Tejun Heo
2005-08-21 20:11       ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).