linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/02] sata_mv: tidy up qc->tf usage in qc_prep() functions
@ 2009-04-13 15:27 Mark Lord
  2009-04-13 15:29 ` [PATCH 02/02] sata_mv: workaround for multi_count errata sata24 Mark Lord
  2009-04-17 22:59 ` libata git repo guide (was Re: [PATCH 01/02] sata_mv: tidy up qc->tf usage in qc_prep() functions) Jeff Garzik
  0 siblings, 2 replies; 11+ messages in thread
From: Mark Lord @ 2009-04-13 15:27 UTC (permalink / raw)
  To: Jeff Garzik, IDE/ATA development list

Tidy up qc->tf accesses in the mv_qc_prep() functions.

Signed-off-by: Mark Lord <mlord@pobox.com>
---

For upstream-linus, please.
In preparation for the multi_count errata patch which follows.

--- old/drivers/ata/sata_mv.c.upstream	2009-04-13 09:46:51.000000000 -0400
+++ new/drivers/ata/sata_mv.c	2009-04-13 10:09:54.000000000 -0400
@@ -1898,17 +1898,17 @@
 	struct ata_port *ap = qc->ap;
 	struct mv_port_priv *pp = ap->private_data;
 	__le16 *cw;
-	struct ata_taskfile *tf;
+	struct ata_taskfile *tf = &qc->tf;
 	u16 flags = 0;
 	unsigned in_index;
 
-	if ((qc->tf.protocol != ATA_PROT_DMA) &&
-	    (qc->tf.protocol != ATA_PROT_NCQ))
+	if ((tf->protocol != ATA_PROT_DMA) &&
+	    (tf->protocol != ATA_PROT_NCQ))
 		return;
 
 	/* Fill in command request block
 	 */
-	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
+	if (!(tf->flags & ATA_TFLAG_WRITE))
 		flags |= CRQB_FLAG_READ;
 	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
 	flags |= qc->tag << CRQB_TAG_SHIFT;
@@ -1924,7 +1924,6 @@
 	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
 
 	cw = &pp->crqb[in_index].ata_cmd[0];
-	tf = &qc->tf;
 
 	/* Sadly, the CRQB cannot accomodate all registers--there are
 	 * only 11 bytes...so we must pick and choose required
@@ -1990,16 +1989,16 @@
 	struct ata_port *ap = qc->ap;
 	struct mv_port_priv *pp = ap->private_data;
 	struct mv_crqb_iie *crqb;
-	struct ata_taskfile *tf;
+	struct ata_taskfile *tf = &qc->tf;
 	unsigned in_index;
 	u32 flags = 0;
 
-	if ((qc->tf.protocol != ATA_PROT_DMA) &&
-	    (qc->tf.protocol != ATA_PROT_NCQ))
+	if ((tf->protocol != ATA_PROT_DMA) &&
+	    (tf->protocol != ATA_PROT_NCQ))
 		return;
 
 	/* Fill in Gen IIE command request block */
-	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
+	if (!(tf->flags & ATA_TFLAG_WRITE))
 		flags |= CRQB_FLAG_READ;
 
 	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
@@ -2015,7 +2014,6 @@
 	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
 	crqb->flags = cpu_to_le32(flags);
 
-	tf = &qc->tf;
 	crqb->ata_cmd[0] = cpu_to_le32(
 			(tf->command << 16) |
 			(tf->feature << 24)

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

* [PATCH 02/02] sata_mv: workaround for multi_count errata sata24
  2009-04-13 15:27 [PATCH 01/02] sata_mv: tidy up qc->tf usage in qc_prep() functions Mark Lord
@ 2009-04-13 15:29 ` Mark Lord
  2009-04-13 15:36   ` Mark Lord
                     ` (2 more replies)
  2009-04-17 22:59 ` libata git repo guide (was Re: [PATCH 01/02] sata_mv: tidy up qc->tf usage in qc_prep() functions) Jeff Garzik
  1 sibling, 3 replies; 11+ messages in thread
From: Mark Lord @ 2009-04-13 15:29 UTC (permalink / raw)
  To: Jeff Garzik, IDE/ATA development list

Workaround for errata SATA#24 in sata_mv.
This errata affects WRITE_MULTI* commands when
the device multi_count produces a DRQ block size >= 4Kbytes.

We work around it here by converting such operations
into ordinary PIO_WRITEs instead.

Note that this might result in a PIO FUA write unavoidably being converted
into a non-FUA write.  In practice, any system using FUA is also going to be
using DMA rather than PIO, so this shouldn't affect anyone in the real world.

Signed-off-by: Mark Lord <mlord@pobox.com>
---
For upstream-linus, please.

--- old/drivers/ata/sata_mv.c.upstream	2009-04-13 09:46:51.000000000 -0400
+++ new/drivers/ata/sata_mv.c	2009-04-13 10:11:26.000000000 -0400
@@ -1881,6 +1881,39 @@
 	return status;
 }
 
+static void mv_rw_multi_errata_sata24(struct ata_queued_cmd *qc)
+{
+	struct ata_taskfile *tf = &qc->tf;
+	/*
+	 * Workaround for 88SX60x1 FEr SATA#24.
+	 *
+	 * Chip may corrupt WRITEs if multi_count >= 4kB.
+	 * Note that READs are unaffected.
+	 *
+	 * It's not clear if this errata really means "4K bytes",
+	 * or if it always happens for multi_count > 7
+	 * regardless of device sector_size.
+	 *
+	 * So, for safety, any write with multi_count > 7
+	 * gets converted here into a regular PIO write instead:
+	 */
+	if ((tf->flags & ATA_TFLAG_WRITE) && is_multi_taskfile(tf)) {
+		if (qc->dev->multi_count > 7) {
+			switch (tf->command) {
+			case ATA_CMD_WRITE_MULTI:
+				tf->command = ATA_CMD_PIO_WRITE;
+				break;
+			case ATA_CMD_WRITE_MULTI_FUA_EXT:
+				tf->flags &= ~ATA_TFLAG_FUA; /* ugh */
+				/* fall through */
+			case ATA_CMD_WRITE_MULTI_EXT:
+				tf->command = ATA_CMD_PIO_WRITE_EXT;
+				break;
+			}
+		}
+	}
+}
+
 /**
  *      mv_qc_prep - Host specific command preparation.
  *      @qc: queued command to prepare
@@ -1902,9 +1935,16 @@
 	u16 flags = 0;
 	unsigned in_index;
 
-	if ((tf->protocol != ATA_PROT_DMA) &&
-	    (tf->protocol != ATA_PROT_NCQ))
+	switch (tf->protocol) {
+	case ATA_PROT_DMA:
+	case ATA_PROT_NCQ:
+		break;	/* continue below */
+	case ATA_PROT_PIO:
+		mv_rw_multi_errata_sata24(qc);
+		return;
+	default:
 		return;
+	}
 
 	/* Fill in command request block
 	 */

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

* Re: [PATCH 02/02] sata_mv: workaround for multi_count errata sata24
  2009-04-13 15:29 ` [PATCH 02/02] sata_mv: workaround for multi_count errata sata24 Mark Lord
@ 2009-04-13 15:36   ` Mark Lord
  2009-04-13 17:25     ` Jeff Garzik
  2009-04-13 15:40   ` Alan Cox
  2009-04-17 23:03   ` Jeff Garzik
  2 siblings, 1 reply; 11+ messages in thread
From: Mark Lord @ 2009-04-13 15:36 UTC (permalink / raw)
  To: Jeff Garzik, IDE/ATA development list, Tejun Heo, Alan Cox

Mark Lord wrote:
> Workaround for errata SATA#24 in sata_mv.
> This errata affects WRITE_MULTI* commands when
> the device multi_count produces a DRQ block size >= 4Kbytes.
> 
> We work around it here by converting such operations
> into ordinary PIO_WRITEs instead.
> 
> Note that this might result in a PIO FUA write unavoidably being converted
> into a non-FUA write.  In practice, any system using FUA is also going to be
> using DMA rather than PIO, so this shouldn't affect anyone in the real world.
..

Testing this was a real bear.

The drives I have here are among those which cannot do R/W MULTI
prior to having a SET_MULTIPLE command issued to them by libata.

Which libata currently does not do.

This means that libata is unable to cope with non-DMA devices
that report a non-zero multi_count value at startup.

I simulated this scenario in sata_mv by changing the .udma_mask field
to zero for the card under test.  System sat there retrying the
partition table read over and over and over and over..  :)

Someday I'll fix that, if you guys don't beat me to it.
I suppose we just need to issue the SET_MULTIPLE command from
the drive revalidation code.  

Cheers

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

* Re: [PATCH 02/02] sata_mv: workaround for multi_count errata sata24
  2009-04-13 15:29 ` [PATCH 02/02] sata_mv: workaround for multi_count errata sata24 Mark Lord
  2009-04-13 15:36   ` Mark Lord
@ 2009-04-13 15:40   ` Alan Cox
  2009-04-13 15:44     ` Mark Lord
  2009-04-17 23:03   ` Jeff Garzik
  2 siblings, 1 reply; 11+ messages in thread
From: Alan Cox @ 2009-04-13 15:40 UTC (permalink / raw)
  To: Mark Lord; +Cc: Jeff Garzik, IDE/ATA development list

On Mon, 13 Apr 2009 11:29:34 -0400
Mark Lord <liml@rtr.ca> wrote:

> Workaround for errata SATA#24 in sata_mv.
> This errata affects WRITE_MULTI* commands when
> the device multi_count produces a DRQ block size >= 4Kbytes.
> 
> We work around it here by converting such operations
> into ordinary PIO_WRITEs instead.
> 
> Note that this might result in a PIO FUA write unavoidably being converted
> into a non-FUA write.  In practice, any system using FUA is also going to be
> using DMA rather than PIO, so this shouldn't affect anyone in the real world.

You can just screen the FUA bit from the identify data when you do the
drive setup to avoid that bit.

Alan

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

* Re: [PATCH 02/02] sata_mv: workaround for multi_count errata sata24
  2009-04-13 15:40   ` Alan Cox
@ 2009-04-13 15:44     ` Mark Lord
  2009-04-13 15:46       ` Mark Lord
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Lord @ 2009-04-13 15:44 UTC (permalink / raw)
  To: Alan Cox; +Cc: Jeff Garzik, IDE/ATA development list

Alan Cox wrote:
> On Mon, 13 Apr 2009 11:29:34 -0400
> Mark Lord <liml@rtr.ca> wrote:
> 
>> Workaround for errata SATA#24 in sata_mv.
>> This errata affects WRITE_MULTI* commands when
>> the device multi_count produces a DRQ block size >= 4Kbytes.
>>
>> We work around it here by converting such operations
>> into ordinary PIO_WRITEs instead.
>>
>> Note that this might result in a PIO FUA write unavoidably being converted
>> into a non-FUA write.  In practice, any system using FUA is also going to be
>> using DMA rather than PIO, so this shouldn't affect anyone in the real world.
> 
> You can just screen the FUA bit from the identify data when you do the
> drive setup to avoid that bit.
..

I think doing it at identify time would prevent DMA FUA commands,
which are fine in sata_mv.

So the only place to really hit it exactly, is at command construction
or issue time.

cheers

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

* Re: [PATCH 02/02] sata_mv: workaround for multi_count errata sata24
  2009-04-13 15:44     ` Mark Lord
@ 2009-04-13 15:46       ` Mark Lord
  0 siblings, 0 replies; 11+ messages in thread
From: Mark Lord @ 2009-04-13 15:46 UTC (permalink / raw)
  To: Alan Cox; +Cc: Jeff Garzik, IDE/ATA development list

Mark Lord wrote:
> Alan Cox wrote:
>> On Mon, 13 Apr 2009 11:29:34 -0400
>> Mark Lord <liml@rtr.ca> wrote:
>>
>>> Workaround for errata SATA#24 in sata_mv.
>>> This errata affects WRITE_MULTI* commands when
>>> the device multi_count produces a DRQ block size >= 4Kbytes.
>>>
>>> We work around it here by converting such operations
>>> into ordinary PIO_WRITEs instead.
>>>
>>> Note that this might result in a PIO FUA write unavoidably being 
>>> converted
>>> into a non-FUA write.  In practice, any system using FUA is also 
>>> going to be
>>> using DMA rather than PIO, so this shouldn't affect anyone in the 
>>> real world.
>>
>> You can just screen the FUA bit from the identify data when you do the
>> drive setup to avoid that bit.
> ..
> 
> I think doing it at identify time would prevent DMA FUA commands,
> which are fine in sata_mv.
> 
> So the only place to really hit it exactly, is at command construction
> or issue time.
..

Note that libata already will convert would-be FUA commands
into non-FUA PIO commands if (dev->multi_count == 0).

So this isn't really anything new.
Nor can it be avoided.
And certainly not anything to fuss over.

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

* Re: [PATCH 02/02] sata_mv: workaround for multi_count errata sata24
  2009-04-13 15:36   ` Mark Lord
@ 2009-04-13 17:25     ` Jeff Garzik
  2009-04-13 17:36       ` Mark Lord
  0 siblings, 1 reply; 11+ messages in thread
From: Jeff Garzik @ 2009-04-13 17:25 UTC (permalink / raw)
  To: Mark Lord; +Cc: IDE/ATA development list, Tejun Heo, Alan Cox

Mark Lord wrote:
> Someday I'll fix that, if you guys don't beat me to it.
> I suppose we just need to issue the SET_MULTIPLE command from
> the drive revalidation code. 

IMO this would be a good idea to do, across many ATA devices.

IIRC there is at least one other chip that snoops the set-multiple 
command, and sets internal chip parameters.

Thus, like SET FEATURES - XFER MODE, it seems wise to unconditionally 
issue SET MULTIPLE for ATA devices, under the logic that it 
more-thoroughly initializes the controller and device, ensuring we are 
at a known state at all times.

Wanna do a patch?  :)  Although not the greatest code location, I'm 
guessing ata_dev_read_id() would probably be the place...  Ideally we 
would have a post-IDENTIFY reset sequence function.

	Jeff



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

* Re: [PATCH 02/02] sata_mv: workaround for multi_count errata sata24
  2009-04-13 17:25     ` Jeff Garzik
@ 2009-04-13 17:36       ` Mark Lord
  0 siblings, 0 replies; 11+ messages in thread
From: Mark Lord @ 2009-04-13 17:36 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: IDE/ATA development list, Tejun Heo, Alan Cox

Jeff Garzik wrote:
> Mark Lord wrote:
>> Someday I'll fix that, if you guys don't beat me to it.
>> I suppose we just need to issue the SET_MULTIPLE command from
>> the drive revalidation code. 
> 
> IMO this would be a good idea to do, across many ATA devices.
> 
> IIRC there is at least one other chip that snoops the set-multiple 
> command, and sets internal chip parameters.
> 
> Thus, like SET FEATURES - XFER MODE, it seems wise to unconditionally 
> issue SET MULTIPLE for ATA devices, under the logic that it 
> more-thoroughly initializes the controller and device, ensuring we are 
> at a known state at all times.
> 
> Wanna do a patch?  :)  Although not the greatest code location, I'm 
> guessing ata_dev_read_id() would probably be the place...  Ideally we 
> would have a post-IDENTIFY reset sequence function.
..

I agree with all of the above.

Except I have a certain other, eagerly anticipated,
patch to work on right now.  :)

Perhaps afterwards, though I'm due to disappear into the embedded
world again for a while, a couple of weeks from now.

If anyone else feels the urge, please don't wait for me!

Cheers

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

* libata git repo guide (was Re: [PATCH 01/02] sata_mv: tidy up qc->tf usage in qc_prep() functions)
  2009-04-13 15:27 [PATCH 01/02] sata_mv: tidy up qc->tf usage in qc_prep() functions Mark Lord
  2009-04-13 15:29 ` [PATCH 02/02] sata_mv: workaround for multi_count errata sata24 Mark Lord
@ 2009-04-17 22:59 ` Jeff Garzik
  1 sibling, 0 replies; 11+ messages in thread
From: Jeff Garzik @ 2009-04-17 22:59 UTC (permalink / raw)
  To: IDE/ATA development list
  Cc: Mark Lord, Stephen Rothwell, Andrew Morton, LKML, Tejun Heo,
	Matthew Wilcox

Mark Lord wrote:
> For upstream-linus, please.


Any volunteers wanna format and post this to the wiki? 
http://ata.wiki.kernel.org/

For what it's worth, upstream-linus is for Linus only, not for anyone else.

Relevant branches of libata-dev.git:

ALL		All libata code I consider acceptable for public
		testing.  Intended for Andrew Morton's -mm tree,
		but I am always looking for people to help test!

NEXT		libata code intended for current kernel + 1
		This is a subset of ALL, and is intended for
		the linux-next tree, and even more rigorous
		public testing.

upstream-fixes	This branch exists when the merge window is NOT open.
		Fixes queued for Linus go here, during -rc.  Generally
		I push to Linus pretty rapidly, though, so programmers
		are encouraged to send patches diff'd against Linus
		upstream during -rc.

upstream	libata code intended for current kernel + 1.  When the
		merge window is closed, patches are queued here.  When
		the merge window is open, fixes for Linus are also
		queued here.

		Generally upstream==NEXT, but this is not guaranteed.

		i.e. sometimes I will put a fix on a separate git
		branch, and then merge that into the mix, such that

			NEXT == upstream + fix-that-needs-testing

And then there are individual branches that pop in and out of existence, 
as I do my own work.  For example, currently active branches are

fixes-eh-freeze	  Freeze ordering fix recently discussed; needs some
		codepath review before I am sure it is safe. (NEXT)

libahci		libahci patchset recently posted (NEXT, ALL)

sectsize	Variable sector size patch.  Will not go into
		#upstream branch until I satisfy some request of
		willy's, which slips my mind at the moment (ALL)

sx4		sata_sx4 new EH conversion (ALL)

And last, but not least,

master		Vanilla Linux kernel, with no changes from me.

		Exists to indicate the root of all above branches,
		so that "git log master..libahci" or
		"git diff master..upstream" works as expected.


NOTE:  All of the branches except 'master' may be rebased.



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

* Re: [PATCH 02/02] sata_mv: workaround for multi_count errata sata24
  2009-04-13 15:29 ` [PATCH 02/02] sata_mv: workaround for multi_count errata sata24 Mark Lord
  2009-04-13 15:36   ` Mark Lord
  2009-04-13 15:40   ` Alan Cox
@ 2009-04-17 23:03   ` Jeff Garzik
  2009-04-18  1:11     ` Mark Lord
  2 siblings, 1 reply; 11+ messages in thread
From: Jeff Garzik @ 2009-04-17 23:03 UTC (permalink / raw)
  To: Mark Lord; +Cc: IDE/ATA development list

Mark Lord wrote:
> Workaround for errata SATA#24 in sata_mv.
> This errata affects WRITE_MULTI* commands when
> the device multi_count produces a DRQ block size >= 4Kbytes.
> 
> We work around it here by converting such operations
> into ordinary PIO_WRITEs instead.
> 
> Note that this might result in a PIO FUA write unavoidably being converted
> into a non-FUA write.  In practice, any system using FUA is also going 
> to be
> using DMA rather than PIO, so this shouldn't affect anyone in the real 
> world.

I'm applying this, but I think a follow-up patch would be nice:  it 
seems like a one-time printk, indicating the FUA conversion is active, 
could be a help in case someone does care.

	Jeff





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

* Re: [PATCH 02/02] sata_mv: workaround for multi_count errata sata24
  2009-04-17 23:03   ` Jeff Garzik
@ 2009-04-18  1:11     ` Mark Lord
  0 siblings, 0 replies; 11+ messages in thread
From: Mark Lord @ 2009-04-18  1:11 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: IDE/ATA development list

Jeff Garzik wrote:
> Mark Lord wrote:
>> Workaround for errata SATA#24 in sata_mv.
>> This errata affects WRITE_MULTI* commands when
>> the device multi_count produces a DRQ block size >= 4Kbytes.
>>
>> We work around it here by converting such operations
>> into ordinary PIO_WRITEs instead.
>>
>> Note that this might result in a PIO FUA write unavoidably being 
>> converted
>> into a non-FUA write.  In practice, any system using FUA is also going 
>> to be
>> using DMA rather than PIO, so this shouldn't affect anyone in the real 
>> world.
> 
> I'm applying this, but I think a follow-up patch would be nice:  it 
> seems like a one-time printk, indicating the FUA conversion is active, 
> could be a help in case someone does care.
..

Seems like .text bloat to me.

But if you want it, I'll cook up patches for both ata_rwcmd_protocol()
in libata-core.c as well as sata_mv.c later on.

Cheers

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

end of thread, other threads:[~2009-04-18  1:11 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-13 15:27 [PATCH 01/02] sata_mv: tidy up qc->tf usage in qc_prep() functions Mark Lord
2009-04-13 15:29 ` [PATCH 02/02] sata_mv: workaround for multi_count errata sata24 Mark Lord
2009-04-13 15:36   ` Mark Lord
2009-04-13 17:25     ` Jeff Garzik
2009-04-13 17:36       ` Mark Lord
2009-04-13 15:40   ` Alan Cox
2009-04-13 15:44     ` Mark Lord
2009-04-13 15:46       ` Mark Lord
2009-04-17 23:03   ` Jeff Garzik
2009-04-18  1:11     ` Mark Lord
2009-04-17 22:59 ` libata git repo guide (was Re: [PATCH 01/02] sata_mv: tidy up qc->tf usage in qc_prep() functions) 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).