Re: something strange in libata-core.c for kernel 2.6.22-rc3

2007-05-21 Thread Robert Hancock

Tejun Heo wrote:

[EMAIL PROTECTED] wrote:

Mybe I am wrong, but if you are detecting 40-wire cable to set them to
DMA/33, why the check includes also 80-wire cables configuring them to
DMA/33 too?

With this patch my nvidia4 IDE controllers detects correctly and
configure correctly DMA/100 for my HD and DMA/33 for my DVD (the first
uses a 80-wire cable, the second a 40-wire cable).

Am I wrong somewhere?


That's the drive side verification of 80c cable check, so if the
condition triggers we downgrade 80c or unknown to 40c.  Cable detection
on nvidia PATA is a disaster.  You're supposed to do some ACPI dancing
and drive side detection is completely bogus.  Eeeek

Alan, did you have a chance to test the ACPI cable detection?  It just
didn't work when I tried it.  It always returned 80c on my machine.


On a whim I started poking around in the disassembled ACPI DSDT code for 
my Asus A8N-SLI Deluxe board, which is one of these chipsets. The 
original thought was that the STM/GTM trick on these chipsets is 
supposed to allow us to determine what modes we should use based on what 
modes it sets up appropriately. Unfortunately, unless I'm missing 
something in the AML (which is possible) it doesn't seem like there is 
any validation being done on the settings passed in. The settings appear 
to essentially just get programmed into the controller when STM is 
called and read back on GTM. The only complication is some logic on the 
_PTS method (Prepare to Sleep) which stores the current settings into 
some variables, and in STM, if a flag was set by the _PTS method, the 
previous settings for all registers are stored back first before writing 
the requested values into the correct places.


So in this case, obviously the approach used by pata_acpi, etc. won't 
work for cable detection. Whatever magic register on the chipset 
contains the cable detect value, the AML doesn't seem to be accessing 
it. The ACPI spec doesn't really give any guarantee that the try STM on 
all possible modes trick will work either, since there seems to be no 
mention of the AML being required to validate the mode and the STM 
function has no return value to indicate failure.


I guess this means that what we have to do is trust that the BIOS set up 
a reasonable mode and base the cable detect on that (either by reading 
back the boot-up controller registers, or by calling GTM). I imagine 
this is what the Windows default IDE driver is doing (just using the 
boot-up mode and feeding it back using GTM/STM on suspend/resume cycles).


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: something strange in libata-core.c for kernel 2.6.22-rc3

2007-05-21 Thread Robert Hancock

Alan Cox wrote:

Yeah, that's consistent to what I've seen on my machine which is a
variant of A8N.  No matter what value I through at _STM, _GTM just
echoed the result thus always leading to 80c configuration.


I guess this means that what we have to do is trust that the BIOS set up
a reasonable mode and base the cable detect on that (either by reading
back the boot-up controller registers, or by calling GTM). I imagine
this is what the Windows default IDE driver is doing (just using the
boot-up mode and feeding it back using GTM/STM on suspend/resume cycles).

Alan, what do you think?


Interesting, sounds like it is still useful rather than just reading the
registers as the GTM/STM seem to survive resume cycles which drive config
may not (eg if the driver is loaded after a s2ram/resume.


I don't think that case is handled in this BIOS anyway - if you call GTM 
after resume without previously calling STM, it's just going to read 
whatever random values are in the controller and give you timings based 
on that, which presumably will be junk.


It looks like the main purpose for what it's doing with saving those 
registers in the _PTS method is to save and restore a couple of 
controller registers called ID20 (PCI config space offset 0x50, 16 bits) 
and ID22 (PCI config space offset 0x5C, 32 bits) which aren't otherwise 
used in the AML. According to pata_amd, for the AMD IDE interface the 
former is some reserved bits as well as the cable detect bits, while the 
latter is the cycle time and address setup time register. Presumably 
those aren't really the cable detect bits though, since the detection 
based on those bits in pata_amd doesn't really work..



If it just echoes back we should also be able to detect this by using
knowingly invalid values.


Well, this implementation doesn't purely echo back the same values, it 
echoes back values derived from what the controller was actually set to, 
so I imagine if you put in something ridiculous it would come back with 
the closest possible mode that it was set to (PIO mode 0, etc.)


I suspect the implementation we would need to use (which doesn't depend 
on anything not given in the spec) would be:


-On driver load, execute _GTM to get the timing mode the BIOS had set. 
Assume this represents the fastest modes the controller supports, and 
set cable detect based on whether it includes UDMA modes  2.


-If we decide to set a slower mode (speed down due to errors, etc.), set 
it using _STM and then read back the actual values that were set using 
_GTM (for possible use in suspend/resume).


-On resume after suspend, re-set the last mode using _STM followed by 
executing _GTF and running those commands.


This won't handle the case where the driver is loaded after the system 
was already suspended to RAM and resumed, however I don't know exactly 
how one could handle that in this situation..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Add Seagate STT20000A to DMA blacklist.

2007-05-21 Thread Robert Hancock

Dave Jones wrote:

On Mon, May 21, 2007 at 05:15:51PM +0100, Alan Cox wrote:
  On Mon, 21 May 2007 10:50:42 -0400
  Dave Jones [EMAIL PROTECTED] wrote:
  
   http://bugzilla.kernel.org/show_bug.cgi?id=1044

   has been open for _four_ years with a patch available.
   Here's a rediffed version of the same.
  
  Please update libata as well when you udpate the blacklists.


Sure, point me at the table(s) ?

Dave



ata_device_blacklist in drivers/ata/libata-core.c

--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: sd_resume redundant? [was: [PATCH] libata: implement ata_wait_after_reset()]

2007-05-20 Thread Robert Hancock

Randy Dunlap wrote:

On Sun, 20 May 2007 11:45:03 -0600 Robert Hancock wrote:


Indan Zupancic wrote:

Everything seems to work fine without sd_resume(), so why is it needed?

Because not all disks spin up without being told to do so and like it or
not spinning disks up on resume is the default behavior.  As I wrote in
the other reply, it would be worthwhile to make it configurable.

Not even after they receive a read command? Ugh.
ATA disks are supposed to spin up, yes. SCSI disks require a command to 
tell them to spin up if they're in the stopped state.


Good info, but linux-ide was dropped.  Is that due to lack of
reply-to-all or is it a newsgroup thing or what?


That would be a newsgroup thing. It seems that sometimes CCs get dropped 
when the posts are forwarded to fa.linux.kernel where I normally read them.


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] sata_sil: Greatly improve DMA support

2007-05-19 Thread Robert Hancock

Jeff Garzik wrote:

Since Alan expressed a desire to see Large Block Transfer (LBT) support
in pata_sil680, I though I would re-post my patch for adding LBT support
to sata_sil.

Silicon Image's Large Block Transfer (LBT) support is a vendor-specific
DMA scatter/gather engine, which enables 64-bit DMA addresses (where
supported by platform) and eliminates the annoying 64k DMA boundary
found in legacy PCI IDE BMDMA engines.


Looks like it doesn't allow 64-bit DMA addresses, it only gets rid of 
the 64K boundary limitation.


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] drivers/ata: Add the SW NCQ support to sata_nv for MCP51/MCP55/MCP61

2007-05-18 Thread Robert Hancock

Kuan Luo wrote:

Thanks for your comment, see the explaination inline.
We'll apply your advice in later patch.


...

Please don't duplicate this code in the driver, this is part of libata 
core in libata-scsi.c. Add an export for these functions if you need to 
use them in the driver.

[kuan]: These calls are declared in static type . I can't export them
and don't want to
modify libata code.


If you really need these functions then they should be made non-static 
and exported. Duplicating the code is not a solution.


I'm not so sure you actually need all that, though. I suspect you can 
likely handle the deferring of commands if you detect an FPDMA data 
phase inside the qc_issue function only (like you already do in some 
cases) instead of having to mess with deferring them at the SCSI layer.


I'm still puzzling out how this stuff all works, but it looks like this 
code makes you stop sending new commands if:


-the port is in the FPDMA Data Phase (DMA Setup FIS received but the 
transfer is not complete yet) - I assume the hardware doesn't handle 
this itself, which seems rather unique
-we previously deferred a command inside of qc_issue because we were in 
the FPDMA data phase
-we previously saw dhfis_flags not equal to qc_active, or we got a 
BACKOUT interrupt (whatever exactly that means), both of which set some 
value in the back_byte
[kuan]: 
-If we got BACKOUT interrupt, it means that a command just sent by

driver
backed out.The driver should resend the command.So new commands should
be defered.
-If dhfis_flags != qc_active, it indicates that the last command doesn't
generate a device to host register FIS .
After sending some commands, I found that the last command sometimes has
this problem 
but previous commands are normal.In this case, we need resend the last

command.
Both cases set back_byte. 


The case where the command didn't generate a D2H FIS should likely be 
investigated further, otherwise we don't necessarily know that this 
workaround will work in all cases?


This code seems a bit odd. Isn't this tossing out a bunch of potential 
error status, etc?

[kuan]:
If there are commands in queue, the driver can  send  a new command 
only after receiving dhfis intr of previous command and before receiving

any dmasetup fis intr.
In this place,  i do the last check before sending the command.


But the D2H FIS can contain an error indication, correct? If that 
happens here it won't detect this. In this situation error handling 
should be triggered.



+   done_mask = pp-qc_active ^ sactive;
+   if (unlikely(done_mask  sactive)) {
+   ata_port_printk(ap, KERN_ERR, illegal qc_active
transition 
+   (%08x-%08x)\n, ap-qc_active,
sactive);
+   return -EINVAL;
+   }   

Shouldn't this trigger error handling if it happens instead of just 
printing an error?

[kuan]:
I think the error handling can be triggered by timeout. In fact, 
this case should seldom happen.


There have been reports of some drives with bad NCQ implementations that 
return completion status for commands that were not issued. If we detect 
this case we should raise an HSM violation which will disable NCQ on 
this drive if it happens repeatedly. See the code in ahci.c in 
ahci_host_intr.


This comment still applies:


Additional/general comments:

Think you need some code to handle suspend and resume (re-enable SATA 
MMIO space, etc.)


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] drivers/ata: Add the SW NCQ support to sata_nv for MCP51/MCP55/MCP61

2007-05-17 Thread Robert Hancock

Peer Chen wrote:

 Add the Software NCQ support to sata_nv.c for MCP51/MCP55/MCP61 SATA
controller.

This patch base on sata_nv.c file from kernel 2.6.22-rc1

See attachment for the patch.

Signed-off-by: Kuan Luo [EMAIL PROTECTED]
Signed-off-by: Peer Chen [EMAIL PROTECTED]


Good to finally see this come out. I've pasted the code below (indented) 
in order to make some comments:


	--- linux-2.6.22-rc1/drivers/ata/sata_nv.c.orig	2007-05-17 
14:48:26.0 -0400
	+++ linux-2.6.22-rc1/drivers/ata/sata_nv.c	2007-05-17 
17:07:28.0 -0400

@@ -46,6 +46,8 @@
 #include linux/device.h
 #include scsi/scsi_host.h
 #include scsi/scsi_device.h
+#include scsi/scsi.h
+#include scsi/scsi_cmnd.h
 #include linux/libata.h

 #define DRV_NAME   sata_nv
@@ -169,6 +171,36 @@ enum {
NV_ADMA_PORT_REGISTER_MODE  = (1  0),
NV_ADMA_ATAPI_SETUP_COMPLETE= (1  1),

+   /* MCP55 reg offset */
+   NV_CTL_MCP55= 0x400,
+   NV_INT_STATUS_MCP55 = 0x440,
+   NV_INT_ENABLE_MCP55 = 0x444,
+   NV_NCQ_REG_MCP55= 0x448,
+   NV_CH1_SACTIVE_MCP55= 0x0C,
+   
+   /* MCP55 */
+   NV_INT_ALL_MCP55= 0x,
+   NV_INT_PORT_SHIFT_MCP55 = 16,   /* each port occupies 
16 bits */
+   NV_INT_MASK_MCP55   = NV_INT_ALL_MCP55  0xfffd,
+   
+   /* NCQ ENABLE BITS*/
+   NV_CTL_PRI_SWNCQ= 0x02,
+   NV_CTL_SEC_SWNCQ= 0x04,
+   
+   /* MCP55 status bits*/
+   NV_INT_DEV_MCP55= 0x01,
+   NV_INT_PM_MCP55 = 0x02,
+   NV_INT_ADDED_MCP55  = 0x04,
+   NV_INT_REMOVED_MCP55= 0x08,
+   
+   NV_INT_BACKOUT_MCP55= 0x10,
+   NV_INT_SDBFIS_MCP55 = 0x20,
+   NV_INT_DHREGFIS_MCP55   = 0x40,
+   NV_INT_DMASETUP_MCP55   = 0x80,
+   
+   NV_INT_HOTPLUG_MCP55= (NV_INT_ADDED_MCP55 |
+   NV_INT_REMOVED_MCP55),
+
 };

 /* ADMA Physical Region Descriptor - one SG segment */
@@ -264,13 +296,118 @@ static void nv_adma_host_stop(struct ata
 static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc);
 static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile 
*tf);

+static void ncq_error_handler(struct ata_port *ap);
+static void nv_mcp55_thaw(struct ata_port *ap);
+static void nv_mcp55_freeze(struct ata_port *ap);
+static void ncq_host_init(struct ata_host *host);
+static void nv_bmdma_stop(struct ata_port *ap);
+static int nv_std_qc_defer(struct ata_port *ap);
+static int  nv_port_start(struct ata_port *ap);
+static void nv_port_stop(struct ata_port *ap);
+static void ncq_clear(struct ata_port *ap);
+static void nv_qc_prep(struct ata_queued_cmd *qc);
+static void nv_fill_sg(struct ata_queued_cmd *qc);
+static void ncq_sactive_start (struct ata_queued_cmd *qc);
+static u32 ncq_sactive_value (struct ata_port *ap);
+static unsigned int nv_qc_issue_prot(struct ata_queued_cmd *qc);
+static u32 ncq_tag_value(struct ata_port *ap);
+static int nv_ncqintr_sdbfis(struct ata_port *ap);
+static int nv_ncqintr_dmasetupfis(struct ata_port *ap);
+static void ncq_clear_singlefis(struct ata_port *ap, u32 val);
+static u32 ncq_ownfisintr_value (struct ata_port *ap);
+void ncq_hotplug(struct ata_port *ap, u32 fis);
+static irqreturn_t nv_mcp55_interrupt(int irq, void *dev_instance);
+static int ncq_interrupt(struct ata_port *ap, u32 fis);
+static int nv_scsi_queuecmd(struct scsi_cmnd *cmd,
+   void (*done)(struct scsi_cmnd *));

These functions should use mcp51 or swncq or something in the name 
instead of ncq, since the latter implies it may be related to ADMA as 
well.


+
+#undef NCQ_DEBUG
+#undef NCQ_VERBOSE_DEBUG
+#ifdef NCQ_DEBUG
	+#define NPRINTK(fmt, args...) printk(KERN_ERR %s:  fmt, 
__FUNCTION__, ## args)

+#ifdef NCQ_VERBOSE_DEBUG
	+#define NVPRINTK(fmt, args...) printk(KERN_ERR %s:  fmt, 
__FUNCTION__, ## args)

+#else
+#define NVPRINTK(fmt, args...) do { } while(0)
+#endif /* NCQ_VERBOSE_DEBUG */
+#else
+#define NPRINTK(fmt, args...) do { } while(0)
+#define NVPRINTK(fmt, args...) do { } while(0)
+#endif

We don't need these private helper macros, just use 

[PATCH] libata: add human-readable error value decoding (v2)

2007-05-14 Thread Robert Hancock

This adds human-readable decoding of the ATA status and error registers (similar
to what drivers/ide does) as well as the SATA Serror register to libata error
handling output. This prevents the need to pore through standards documents
to figure out the meaning of the bits in these registers when looking at error
reports. Some bits that drivers/ide decoded are not decoded here, since the bits
are either command-dependent or obsolete, and properly parsing them would add
too much complexity.

This version reduces the length of the SError parsed output strings relative to 
the
previous version of this patch.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.21.1/drivers/ata/libata-eh.c  2007-04-27 15:49:26.0 
-0600
+++ linux-2.6.21.1edit/drivers/ata/libata-eh.c  2007-05-14 17:38:35.0 
-0600
@@ -1523,6 +1523,27 @@ static void ata_eh_report(struct ata_por
ata_port_printk(ap, KERN_ERR, (%s)\n, desc);
}

+   if (ehc-i.serror)
+   ata_port_printk(ap, KERN_ERR,
+ SError: {%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n,
+ ehc-i.serror  SERR_DATA_RECOVERED ? RecovData  : ,
+ ehc-i.serror  SERR_COMM_RECOVERED ? RecovComm  : ,
+ ehc-i.serror  SERR_DATA ? UnrecovData  : ,
+ ehc-i.serror  SERR_PERSISTENT ? Persist  : ,
+ ehc-i.serror  SERR_PROTOCOL ? Proto  : ,
+ ehc-i.serror  SERR_INTERNAL ? HostInt  : ,
+ ehc-i.serror  SERR_PHYRDY_CHG ? PHYRdyChg  : ,
+ ehc-i.serror  SERR_PHY_INT_ERR ? PHYInt  : ,
+ ehc-i.serror  SERR_COMM_WAKE ? CommWake  : ,
+ ehc-i.serror  SERR_10B_8B_ERR ? 10B8B  : ,
+ ehc-i.serror  SERR_DISPARITY ? Dispar  : ,
+ ehc-i.serror  SERR_CRC ? BadCRC  : ,
+ ehc-i.serror  SERR_HANDSHAKE ? Handshk  : ,
+ ehc-i.serror  SERR_LINK_SEQ_ERR ? LinkSeq  : ,
+ ehc-i.serror  SERR_TRANS_ST_ERROR ? TrStaTrns  : ,
+ ehc-i.serror  SERR_UNRECOG_FIS ? UnrecFIS  : ,
+ ehc-i.serror  SERR_DEV_XCHG ? DevExch  :  );
+
for (tag = 0; tag  ATA_MAX_QUEUE; tag++) {
static const char *dma_str[] = {
[DMA_BIDIRECTIONAL] = bidi,
@@ -1552,6 +1573,29 @@ static void ata_eh_report(struct ata_por
res-hob_feature, res-hob_nsect,
res-hob_lbal, res-hob_lbam, res-hob_lbah,
res-device, qc-err_mask, 
ata_err_string(qc-err_mask));
+   
+   if (res-command  (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
+   ATA_ERR) ) {
+   if (res-command  ATA_BUSY)
+   ata_dev_printk(qc-dev, KERN_ERR,
+ status: {Busy}\n );
+   else
+   ata_dev_printk(qc-dev, KERN_ERR,
+ status: {%s%s%s%s}\n,
+ res-command  ATA_DRDY ? DRDY  : ,
+ res-command  ATA_DF ? DF  : ,
+ res-command  ATA_DRQ ? DRQ  : ,
+ res-command  ATA_ERR ? ERR  :  );
+   }
+   
+   if (cmd-command != ATA_CMD_PACKET 
+   (res-feature  (ATA_ICRC | ATA_UNC | ATA_IDNF | 
ATA_ABORTED)))
+   ata_dev_printk(qc-dev, KERN_ERR,
+ error: {%s%s%s%s}\n,
+ res-feature  ATA_ICRC ? ICRC  : ,
+ res-feature  ATA_UNC ? UNC  : ,
+ res-feature  ATA_IDNF ? IDNF  : ,
+ res-feature  ATA_ABORTED ? ABRT  :  );
}
}

--- linux-2.6.21.1/include/linux/ata.h  2007-04-27 15:49:26.0 -0600
+++ linux-2.6.21.1edit/include/linux/ata.h  2007-05-09 19:25:54.0 
-0600
@@ -223,6 +223,15 @@ enum {
SERR_PROTOCOL   = (1  10), /* protocol violation */
SERR_INTERNAL   = (1  11), /* host internal error */
SERR_PHYRDY_CHG = (1  16), /* PHY RDY changed */
+   SERR_PHY_INT_ERR= (1  17), /* PHY internal error */
+   SERR_COMM_WAKE  = (1  18), /* Comm wake */
+   SERR_10B_8B_ERR = (1  19), /* 10b to 8b decode error */
+   SERR_DISPARITY  = (1  20), /* Disparity */
+   SERR_CRC= (1  21), /* CRC error */
+   SERR_HANDSHAKE  = (1  22), /* Handshake error */
+   SERR_LINK_SEQ_ERR   = (1  23), /* Link sequence error */
+   SERR_TRANS_ST_ERROR = (1  24), /* Transport state transition 
error */
+   SERR_UNRECOG_FIS= (1  25), /* Unrecognized FIS */
SERR_DEV_XCHG   = (1  26), /* device exchanged */

/* struct ata_taskfile flags */

-
To unsubscribe from

Re: [2.6.21.1] SATA freeze

2007-05-12 Thread Robert Hancock

Fred Moyer wrote:
I just joined the list today so apologies if this email breaks any email 
client post threading.


I have been seeing similar errors on two different systems.  I applied 
Robert's sata_nv patch posted to the list on May 5th, and approved today 
by Jeff Garzik.  I've taken several steps to insure that this isn't a 
faulty cable or drive issue.  This is running on a hp dl145g2.  Here is 
my lspci, dmesg, and relevant kernel config sections:


(snip)


ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x2 frozen
ata1.00: cmd b0/d2:f1:00:4f:c2/00:00:00:00:00/00 tag 0 cdb 0x0 data 
123392 in
 res 50/00:f1:00:4f:c2/00:00:00:00:00/00 Emask 0x202 (HSM 
violation)

ata1: soft resetting port
ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
ata1.00: configured for UDMA/100
ata1: EH complete


This appears to be a different problem. Something is issuing 
SMART-related commands (smartd or smartctl perhaps) which the drive 
seems to be reacting strangely to. It apparently completed the command 
but never raised DRQ to request any data being transferred even though 
we expected it to. Maybe SMART is disabled on the drive and that's 
causing it to just toss these commands? CCing linux-ide in case anyone 
knows what would cause this.


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [2.6.21.1] SATA freeze

2007-05-12 Thread Robert Hancock

Fred Moyer wrote:
This appears to be a different problem. Something is issuing 
SMART-related commands (smartd or smartctl perhaps) which the drive 
seems to be reacting strangely to. It apparently completed the command 
but never raised DRQ to request any data being transferred even though 
we expected it to. Maybe SMART is disabled on the drive and that's 
causing it to just toss these commands? CCing linux-ide in case anyone 
knows what would cause this.


Here's smartctl -a for this drive - same output for both sda and sdb. 
Smartd is currently running.  Any advice appreciated.


Previously on 2.6.15 I was seeing sdb remount as readonly under heavy 
i/o.  I have not seen that issue yet with 2.6.21 (with Robert's patch 
from May 5th for sata_nv), but that occurrence of remounts read-only was 
infrequently, so that issue may be solved.


app2 ~ # smartctl -a /dev/sda
smartctl version 5.36 [x86_64-pc-linux-gnu] Copyright (C) 2002-6 Bruce 
Allen

Home page is http://smartmontools.sourceforge.net/

Device: ATA  ST3808110AS  Version: n/a
Serial number: 5LR8895K
Device type: disk
Local Time is: Sat May 12 12:05:58 2007 PDT
Device does not support SMART

Error Counter logging not supported

[GLTSD (Global Logging Target Save Disable) set. Enable Save with '-S on']
Device does not support Self Test logging



Sounds like SMART is likely disabled on that drive. You can try doing 
smartctl -s on /dev/sda and see if that will turn it on.


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] libata: add human-readable error value decoding

2007-05-10 Thread Robert Hancock

Tejun Heo wrote:

+if (ehc-i.serror)
+ata_port_printk(ap, KERN_ERR,
+  SError: {%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n,
+  ehc-i.serror  SERR_DATA_RECOVERED ? RecovDataErr  : ,
+  ehc-i.serror  SERR_COMM_RECOVERED ? RecovCommErr  : ,
+  ehc-i.serror  SERR_DATA ? UnrecovDataErr  : ,
+  ehc-i.serror  SERR_PERSISTENT ? PersistErr  : ,
+  ehc-i.serror  SERR_PROTOCOL ? ProtocolErr  : ,
+  ehc-i.serror  SERR_INTERNAL ? HostInternalErr  : ,
+  ehc-i.serror  SERR_PHYRDY_CHG ? PHYRdyChg  : ,
+  ehc-i.serror  SERR_PHY_INT_ERR ? PHYInternalErr  : ,
+  ehc-i.serror  SERR_COMM_WAKE ? CommWake  : ,
+  ehc-i.serror  SERR_10B_8B_ERR ? 10B8BErr  : ,
+  ehc-i.serror  SERR_DISPARITY ? Disparity  : ,
+  ehc-i.serror  SERR_CRC ? CRCErr  : ,
+  ehc-i.serror  SERR_HANDSHAKE ? HandshakeErr  : ,
+  ehc-i.serror  SERR_LINK_SEQ_ERR ? LinkSeqErr  : ,
+  ehc-i.serror  SERR_TRANS_ST_ERROR ? TransStatTransErr  : ,
+  ehc-i.serror  SERR_UNRECOG_FIS ? UnrecogFIS  : ,
+  ehc-i.serror  SERR_DEV_XCHG ? DevExchanged  :  );


I'm not really convinced whether this is necessary.  The human readable
form is also a bit cryptic and can get quite long.  So, mild NACK from me.



It certainly seems useful when debugging hotplug issues or random SATA 
problems which end up being caused by communication problems. Without 
this output, Joe User stands no chance of figuring out what's going on, 
and neither does Joe libata Developer unless they really care to dig 
through the spec and count bits to figure out what they mean. At least 
with this you can see that there was a CRC error, etc. and go from that..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] libata: add human-readable error value decoding

2007-05-10 Thread Robert Hancock

Jeff Garzik wrote:

Mark Lord wrote:

If we're compiling the messages into the kernel regardless,
then it doesn't really make much sense to NOT show all of them
on the error paths.



Not true.  Uncontrolled message spewage inevitably results in critical 
information scrolling off the screen, before a user can take a digital 
photo of the output...  Or of users being confused by subsequent error 
fallout (i.e. multiple oopses reporting problem).


Moderation and restraint still have roles to play...  :)

Jeff


I don't think this is as big of a deal here as in other cases, like oops 
output. With libata errors, if they're at the console (which they'd have 
to be to see these messages), unless something has actually caused a 
panic the scrollback buffer should still be functional and they'd be 
able to see the entire output..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] libata: add human-readable error value decoding

2007-05-09 Thread Robert Hancock

This adds human-readable decoding of the ATA status and error registers (similar
to what drivers/ide does) as well as the SATA Serror register to libata error
handling output. This prevents the need to pore through standards documents
to figure out the meaning of the bits in these registers when looking at error
reports. Some bits that drivers/ide decoded are not decoded here, since the bits
are either command-dependent or obsolete, and properly parsing them would add
too much complexity.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.21.1/drivers/ata/libata-eh.c  2007-04-27 15:49:26.0 
-0600
+++ linux-2.6.21.1edit/drivers/ata/libata-eh.c  2007-05-09 19:47:53.0 
-0600
@@ -1523,6 +1523,27 @@ static void ata_eh_report(struct ata_por
ata_port_printk(ap, KERN_ERR, (%s)\n, desc);
}

+   if (ehc-i.serror)
+   ata_port_printk(ap, KERN_ERR,
+ SError: {%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n,
+ ehc-i.serror  SERR_DATA_RECOVERED ? RecovDataErr  : ,
+ ehc-i.serror  SERR_COMM_RECOVERED ? RecovCommErr  : ,
+ ehc-i.serror  SERR_DATA ? UnrecovDataErr  : ,
+ ehc-i.serror  SERR_PERSISTENT ? PersistErr  : ,
+ ehc-i.serror  SERR_PROTOCOL ? ProtocolErr  : ,
+ ehc-i.serror  SERR_INTERNAL ? HostInternalErr  : ,
+ ehc-i.serror  SERR_PHYRDY_CHG ? PHYRdyChg  : ,
+ ehc-i.serror  SERR_PHY_INT_ERR ? PHYInternalErr  : ,
+ ehc-i.serror  SERR_COMM_WAKE ? CommWake  : ,
+ ehc-i.serror  SERR_10B_8B_ERR ? 10B8BErr  : ,
+ ehc-i.serror  SERR_DISPARITY ? Disparity  : ,
+ ehc-i.serror  SERR_CRC ? CRCErr  : ,
+ ehc-i.serror  SERR_HANDSHAKE ? HandshakeErr  : ,
+ ehc-i.serror  SERR_LINK_SEQ_ERR ? LinkSeqErr  : ,
+ ehc-i.serror  SERR_TRANS_ST_ERROR ? TransStatTransErr  : 
,
+ ehc-i.serror  SERR_UNRECOG_FIS ? UnrecogFIS  : ,
+ ehc-i.serror  SERR_DEV_XCHG ? DevExchanged  :  );
+
for (tag = 0; tag  ATA_MAX_QUEUE; tag++) {
static const char *dma_str[] = {
[DMA_BIDIRECTIONAL] = bidi,
@@ -1552,6 +1573,29 @@ static void ata_eh_report(struct ata_por
res-hob_feature, res-hob_nsect,
res-hob_lbal, res-hob_lbam, res-hob_lbah,
res-device, qc-err_mask, 
ata_err_string(qc-err_mask));
+   
+   if (res-command  (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
+   ATA_ERR) ) {
+   if (res-command  ATA_BUSY)
+   ata_dev_printk(qc-dev, KERN_ERR,
+ status: {Busy}\n );
+   else
+   ata_dev_printk(qc-dev, KERN_ERR,
+ status: {%s%s%s%s}\n,
+ res-command  ATA_DRDY ? DRDY  : ,
+ res-command  ATA_DF ? DF  : ,
+ res-command  ATA_DRQ ? DRQ  : ,
+ res-command  ATA_ERR ? ERR  :  );
+   }
+   
+   if (cmd-command != ATA_CMD_PACKET 
+   (res-feature  (ATA_ICRC | ATA_UNC | ATA_IDNF | 
ATA_ABORTED)))
+   ata_dev_printk(qc-dev, KERN_ERR,
+ error: {%s%s%s%s}\n,
+ res-feature  ATA_ICRC ? ICRC  : ,
+ res-feature  ATA_UNC ? UNC  : ,
+ res-feature  ATA_IDNF ? IDNF  : ,
+ res-feature  ATA_ABORTED ? ABRT  :  );
}
}

--- linux-2.6.21.1/include/linux/ata.h  2007-04-27 15:49:26.0 -0600
+++ linux-2.6.21.1edit/include/linux/ata.h  2007-05-09 19:25:54.0 
-0600
@@ -223,6 +223,15 @@ enum {
SERR_PROTOCOL   = (1  10), /* protocol violation */
SERR_INTERNAL   = (1  11), /* host internal error */
SERR_PHYRDY_CHG = (1  16), /* PHY RDY changed */
+   SERR_PHY_INT_ERR= (1  17), /* PHY internal error */
+   SERR_COMM_WAKE  = (1  18), /* Comm wake */
+   SERR_10B_8B_ERR = (1  19), /* 10b to 8b decode error */
+   SERR_DISPARITY  = (1  20), /* Disparity */
+   SERR_CRC= (1  21), /* CRC error */
+   SERR_HANDSHAKE  = (1  22), /* Handshake error */
+   SERR_LINK_SEQ_ERR   = (1  23), /* Link sequence error */
+   SERR_TRANS_ST_ERROR = (1  24), /* Transport state transition 
error */
+   SERR_UNRECOG_FIS= (1  25), /* Unrecognized FIS */
SERR_DEV_XCHG   = (1  26), /* device exchanged */

/* struct ata_taskfile flags */

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body

[PATCH] sata_nv: fix ADMA freeze/thaw/irq_clear issues

2007-05-05 Thread Robert Hancock

This patch fixes some problems with ADMA-capable controllers with regard to 
freeze,
thaw and irq_clear libata callbacks. Freeze and thaw didn't switch the 
ADMA-specific
interrupts on or off, and more critically the irq_clear function didn't respect
the restriction that the notifier clear registers for both ports have to be 
written
at the same time even when only one port is being cleared. This could result in
timeouts on one port when error handling (i.e. as a result of hotplug)
occurred on the other port.

As well, this fixes some issues in the interrupt handler: we shouldn't check any
ADMA status if the port has ADMA switched off because of an ATAPI device, and
it also checks to see if any ADMA interrupt has been raised even when we are in
port-register mode.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.21.1/drivers/ata/sata_nv.c2007-04-27 15:49:26.0 
-0600
+++ linux-2.6.21.1edit/drivers/ata/sata_nv.c2007-05-05 15:25:04.0 
-0600
@@ -257,6 +257,8 @@ static void nv_adma_port_stop(struct ata
static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg);
static int nv_adma_port_resume(struct ata_port *ap);
#endif
+static void nv_adma_freeze(struct ata_port *ap);
+static void nv_adma_thaw(struct ata_port *ap);
static void nv_adma_error_handler(struct ata_port *ap);
static void nv_adma_host_stop(struct ata_host *host);
static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc);
@@ -446,8 +448,8 @@ static const struct ata_port_operations 
	.bmdma_status		= ata_bmdma_status,

.qc_prep= nv_adma_qc_prep,
.qc_issue   = nv_adma_qc_issue,
-   .freeze = nv_ck804_freeze,
-   .thaw   = nv_ck804_thaw,
+   .freeze = nv_adma_freeze,
+   .thaw   = nv_adma_thaw,
.error_handler  = nv_adma_error_handler,
.post_internal_cmd  = nv_adma_post_internal_cmd,
.data_xfer  = ata_data_xfer,
@@ -810,8 +812,16 @@ static irqreturn_t nv_adma_interrupt(int
u16 status;
u32 gen_ctl;
u32 notifier, notifier_error;
+   
+   /* if ADMA is disabled, use standard ata interrupt 
handler */
+   if (pp-flags  NV_ADMA_ATAPI_SETUP_COMPLETE) {
+   u8 irq_stat = readb(host-iomap[NV_MMIO_BAR] + 
NV_INT_STATUS_CK804)
+(NV_INT_PORT_SHIFT * i);
+   handled += nv_host_intr(ap, irq_stat);
+   continue;
+   }

-   /* if in ATA register mode, use standard ata interrupt 
handler */
+   /* if in ATA register mode, check for standard 
interrupts */
if (pp-flags  NV_ADMA_PORT_REGISTER_MODE) {
u8 irq_stat = readb(host-iomap[NV_MMIO_BAR] + 
NV_INT_STATUS_CK804)
 (NV_INT_PORT_SHIFT * i);
@@ -821,7 +831,6 @@ static irqreturn_t nv_adma_interrupt(int
command is active, to prevent 
losing interrupts. */
irq_stat |= NV_INT_DEV;
handled += nv_host_intr(ap, irq_stat);
-   continue;
}

notifier = readl(mmio + NV_ADMA_NOTIFIER);
@@ -907,22 +916,77 @@ static irqreturn_t nv_adma_interrupt(int
return IRQ_RETVAL(handled);
}

+static void nv_adma_freeze(struct ata_port *ap)
+{
+   struct nv_adma_port_priv *pp = ap-private_data;
+   void __iomem *mmio = pp-ctl_block;
+   u16 tmp;
+
+   nv_ck804_freeze(ap);
+
+   if (pp-flags  NV_ADMA_ATAPI_SETUP_COMPLETE)
+   return;
+
+   /* clear any outstanding CK804 notifications */
+   writeb( NV_INT_ALL  (ap-port_no * NV_INT_PORT_SHIFT),
+   ap-host-iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
+
+   /* Disable interrupt */
+   tmp = readw(mmio + NV_ADMA_CTL);
+   writew( tmp  ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
+   mmio + NV_ADMA_CTL);
+   readw( mmio + NV_ADMA_CTL );/* flush posted write */
+}
+
+static void nv_adma_thaw(struct ata_port *ap)
+{
+   struct nv_adma_port_priv *pp = ap-private_data;
+   void __iomem *mmio = pp-ctl_block;
+   u16 tmp;
+
+   nv_ck804_thaw(ap);
+
+   if (pp-flags  NV_ADMA_ATAPI_SETUP_COMPLETE)
+   return;
+
+   /* Enable interrupt */
+   tmp = readw(mmio + NV_ADMA_CTL);
+   writew( tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
+   mmio + NV_ADMA_CTL);
+   readw( mmio + NV_ADMA_CTL );/* flush posted write */
+}
+
static void nv_adma_irq_clear(struct ata_port *ap)
{
struct nv_adma_port_priv *pp = ap-private_data

Re: System freezes with kernel 2.6.19 - sata_nv [added crash info kern 2.6.21.1]

2007-05-02 Thread Robert Hancock

Stefan wrote:

First thing you should try is replacing the SATA cable to that drive.


Yeap, please apply some hardware debugging techniques - replacing /
reseating SATA cables and connecting it to different power connector.
But it's disturbing to see machine lock up even if CRC error occurs.
sata_nv non-adma interface locks the whole machine up too after certain
error conditions but I thought adma was saner than that.  I hope we can
work around this somehow.

Thanks.

  

I have just replaced the cables with brand new ones, still no change the
machine freezes ~10min after boot.
Sometimes I even have to completely power down the machine to be able to
boot again.


Power problems would be another possibility..

--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/
-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: System freezes with kernel 2.6.19 - sata_nv [added crash info kern 2.6.21.1]

2007-05-01 Thread Robert Hancock

Stefan wrote:

Okay, I had time to set this up. I'm attaching the log messages I got
via netconsole.


I tested about 20h with adma disabled, the crash won't occur.

If I remove

sata_nv.adma=0

from boot options again it doesn't take long until my machine locks up.

[Attached dmesg output with 2.6.21.1 kernel + crash info I got via
netconsole]


I hope this is useful to you guys.


It looks like you've got SError bits set from the controller, 0x20 
means link layer CRC error (btw, we really should be decoding that error 
and printing it in human readable form rather than making people pore 
through the SATA spec and count bits). First thing you should try is 
replacing the SATA cable to that drive.


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/


-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: System freezes with kernel 2.6.19 - sata_nv

2007-04-30 Thread Robert Hancock

Tejun Heo wrote:

Stefan wrote:

Hi folks,

yesterday I upgraded  kernel 2.6.19 to 2.6.20 (gentoo kernel). Now my
box locks up about 10 min after boot.
After that I tested with a vanilla 2.6.21.1 it shows the same behavior.
I'm attaching a kern log file from the 2.6.20. The 2.6.21.1 locked up so
hard, that there was no trace left in the log file.
If I switch back to 2.6.19 everything is fine again.
If necessary I will hook up a laptop to this box, so I can capture
messages via netconsole.


Yes please.


This machine is running an AMD X2 64, NFORCE4 (ASUS A8N-E)

I haven't been following the development of libata for a while, but from
the 2.6.20 changelog It looks like there have been some major changes.

Just let me know what kind of information you need in order to narrow it
down.


Does giving 'sata_nv.adma=0' kernel parameter make any difference?


If adma=0 words, then that means it's either an ADMA related problem or 
that SAMSUNG HD401LJ drive has some problems with NCQ (since ADMA off 
means NCQ off as well). I would say the latter is more likely.


We should really have some kind of noncq kernel parameter we can use 
to help debugging these problems. Though, later kernels are supposed to 
switch it off automatically after too many errors..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] libata: skip FLUSH and STADNBYNOW1 during shutdown if device is already spun down

2007-04-23 Thread Robert Hancock

Tejun Heo wrote:

libata didn't use to spin down disks properly on shutdown and userland
shutdown(8) worked around it by synchronizing cache and spinning down
by itself before telling the kernel to shutdown.  However, this
userland work around collides with libata shutdown because some drives
spin up if it receives FLUSH or STANDBYNOW1 while spun down.  This
results in unpleasant spin down-up-down sequence.

This patch makes libata skip FLUSH and STANDBYNOW1 during shutdown if
the drive is already spun down.  Note that whether FLUSH has been
performed is not checked.  This is because some userland shutdown(8)'s
only do STANDBYNOW1.  Transition to standby mode implies cache flush,
so this should be safe.


Are we sure this is true in all cases? The ATA spec doesn't explicitly 
say that STANDBY IMMEDIATE implies a cache flush. Granted it would be 
retarded for a drive to spin itself down with data still pending in the 
write cache, but firmware people have done some strange things..




libata prints informational messages when skipping commands.  This is
for debugging and to urge distributions to update shutdown(8) such
that it doesn't do superflous flush and spindown.

Signed-off-by: Tejun Heo [EMAIL PROTECTED]
---
 drivers/ata/libata-scsi.c |   29 +
 include/linux/libata.h|1 +
 2 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 8f80019..2a0717c 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1309,6 +1309,7 @@ nothing_to_do:
 static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 {
struct ata_port *ap = qc-ap;
+   struct ata_device *adev = qc-dev;
struct scsi_cmnd *cmd = qc-scsicmd;
u8 *cdb = cmd-cmnd;
int need_sense = (qc-err_mask != 0);
@@ -1349,6 +1350,13 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd 
*qc)
}
}
 
+	/* Set spundown status.  Some userland tools use STANDBY

+* instead of STANDBYNOW1.  Take both into account.
+*/
+   if (unlikely(qc-tf.command == ATA_CMD_STANDBY ||
+qc-tf.command == ATA_CMD_STANDBYNOW1))
+   adev-flags |= ATA_DFLAG_SPUNDOWN;


Is checking for STANDBY really valid here? STANDBY does not do an 
immediate entry to standby mode, it only sets the standby timer. 
Therefore just because userspace issued a standby command, does not mean 
the drive is really spun down currently.


Could we use CHECK POWER MODE to see if the drive is currently spun down 
rather than tracking whether a standby was already issued? That would 
handle the case above as well, we could tell if the drive had actually 
spun down on a timer or not.




+
if (need_sense  !ap-ops-error_handler)
ata_dump_status(ap-print_id, qc-result_tf);
 
@@ -1454,6 +1462,27 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,

if (xlat_func(qc))
goto early_finish;
 
+	/* Some userland shutdown(8) spins down device to work around

+* previous kernel bugs.  Issuing cache flush or spin down
+* again might spin up some drives.  Skip cache flush and
+* spindown for -shutdown if it's already spun down.
+*/
+   switch (qc-tf.command) {
+   case ATA_CMD_FLUSH:
+   case ATA_CMD_FLUSH_EXT:
+   case ATA_CMD_STANDBYNOW1: /* -shutdown always uses STANDBYNOW1 */
+   if (unlikely((system_state  SYSTEM_RUNNING) 
+(dev-flags  ATA_DFLAG_SPUNDOWN))) {
+   ata_dev_printk(dev, KERN_INFO, already spun down, 
+  skipping cmd 0x%x\n, qc-tf.command);
+   cmd-result = SAM_STAT_GOOD;
+   goto early_finish;
+   }
+   break;
+   default:
+   dev-flags = ~ATA_DFLAG_SPUNDOWN;
+   }
+
/* select device, send command to hardware */
ata_qc_issue(qc);
 
diff --git a/include/linux/libata.h b/include/linux/libata.h

index 6ef4055..fa551fd 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -136,6 +136,7 @@ enum {
ATA_DFLAG_CDB_INTR  = (1  2), /* device asserts INTRQ when ready 
for CDB */
ATA_DFLAG_NCQ   = (1  3), /* device supports NCQ */
ATA_DFLAG_FLUSH_EXT = (1  4), /* do FLUSH_EXT instead of FLUSH */
+   ATA_DFLAG_SPUNDOWN  = (1  5), /* device is spun down by user */
ATA_DFLAG_CFG_MASK  = (1  8) - 1,
 
 	ATA_DFLAG_PIO		= (1  8), /* device limited to PIO mode */

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] libata: add Samsung HD401LJ to the NCQ blacklist

2007-04-18 Thread Robert Hancock

Max Kellermann wrote:

Yet another hard drive which doesn't seem to get NCQ right.

 ata1: EH in ADMA mode, notifier 0x0 notifier_error 0x0 gen_ctl
 0x1501000 status 0x400 next cpb count 0xB next cpb idx 0x0
 [...]
 ata1: timeout waiting for ADMA IDLE, stat=0x400
 ata1: timeout waiting for ADMA LEGACY, stat=0x400
 ata1.00: exception Emask 0x0 SAct 0x3fff SErr 0x20 action 0x2
 frozen
 [...]
 ata1: soft resetting port


Don't know if I noticed this before, but the controller seems to be 
reporting an SError, looks like a link layer CRC error. This could be a 
potential symptom of the drive and controller just not getting along, 
but you might want to try a different SATA cable as well.


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] libata: HPA support

2007-04-13 Thread ROBERT HANCOCK
- Original Message -
From: Kyle McMartin [EMAIL PROTECTED]
Date: Friday, April 13, 2007 10:47 am
Subject: Re: [PATCH] libata: HPA support

 [Adding Robert to the CC incase he doesn't follow linux-ide]
 
 On Fri, Apr 13, 2007 at 12:33:41PM -0400, Kyle McMartin wrote:
  On Fri, Apr 13, 2007 at 12:24:34PM -0400, Jeff Garzik wrote:
   Kyle McMartin wrote:
   Oddly, the command at least executes and doesn't MCE (but 
 it's not at all
   happy either) if I use ATA_PROT_PIO. I wonder if 
 ATA_PROT_NODATA is 
   buggered
   on this sata_nv chip (Asus A8N-E).
   
   Weird...
   
   
   Try turning off ADMA using the module parameter, and see if 
   ATA_PROT_NODATA magically works.
   
   ADMA is an advanced command execution mode, and it may not be 
   appropriate for certain non-data commands.
   
  
  Thanks so much, Jeff! This did it. Think we should drop ADMA by 
 default? Do you know off-hand if there's any other drivers this 
 might bite us on?
  
 
 Seems to have been commit 382a6652e91b34d5480cfc0ed840c196650493d4 
 thatcaused it (submitting NODATA commands using ADMA.)
 
 Reverting that commit (or booting with sata_nv.adma=0) fixes HPA 
 for me
 here... Robert, is reverting that commit going to crush my little 
 world, or
 is it a safe course of action? I'd rather not disable ADMA (which 
 turns off
 NCQ, right?) wholesale, as the whizbang-gentoo crowd will hang me.

There is already a patch in libata-dev that will fix this, assuming those 
commands are marked as requiring a result taskfile in the command flags, which 
they should be:

http://git.kernel.org/?p=linux/kernel/git/jgarzik/libata-dev.git;a=commit;h=eb20a5742d230c67b9af4efd71b8b6b680ca3a09

ADMA should only be used for NODATA commands which don't require any result 
taskfile, such as cache flushes.
-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] sata_nv: Don't attempt using ADMA for (READ|SET)_MAX commands

2007-04-13 Thread Robert Hancock

Mark Lord wrote:

Alan Cox wrote:

On Fri, 13 Apr 2007 13:08:31 -0400
Kyle McMartin [EMAIL PROTECTED] wrote:

READ_NATIVE_MAX and SET_MAX were causing timeouts on sata_nv 
controllers.
Disabling ADMA helped, but that is quite a large hammer to use. 
Reverting
382a6652e91b34d5480cfc0ed840c196650493d4 also helped, but we might as 
well

fix it right, instead of disabling the performance gain on cache flushes
by using ADMA mode.


Probably not going to make any performance difference to blacklist all
non-data commands or all but a few like cache-flush. 


I agree.  The Pacific Digital ADMA stuff had some quirks for various 
non-data
commands as well, and the sensible thing was to just not use ADMA for 
anything

other than READs/WRITEs and possible CACHE FLUSHes.


I'm told by NVidia that non-data commands should be fine in ADMA mode, 
except for those that require reading back a result taskfile (which 
can't be done in ADMA mode). The patch in libata-dev which I mentioned 
in another email will ensure that we don't try to use ADMA for such 
commands, so this patch should not be needed.


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] libata: add NCQ blacklist entries from Silicon Image Windows driver (v2)

2007-04-04 Thread Robert Hancock

Jeff Garzik wrote:

Robert Hancock wrote:
This adds some NCQ blacklist entries taken from the Silicon Image 
3124/3132

Windows driver .inf files. There are some confirming reports of problems
with these drives under Linux (for example 
http://lkml.org/lkml/2007/3/4/178)

so let's disable NCQ on these drives.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.21-rc5-git9/drivers/ata/libata-core.c2007-04-02 
21:03:29.0 -0600
+++ linux-2.6.21-rc5-git9edit/drivers/ata/libata-core.c2007-04-02 
21:26:23.0 -0600
@@ -3363,6 +3363,11 @@ static const struct ata_blacklist_entry { 
Maxtor 6L250S0, BANC1G10, ATA_HORKAGE_NONCQ },
/* NCQ hard hangs device under heavier load, needs hard power 
cycle */

{ Maxtor 6B250S0,BANC1B70,ATA_HORKAGE_NONCQ },
+/* Blacklist entries taken from Silicon Image 3124/3132
+   Windows driver .inf file - also several Linux problem reports */
+{ HTS541060G9SA00,MB3OC60D, ATA_HORKAGE_NONCQ, },
+{ HTS541080G9SA00,MB4OC60D, ATA_HORKAGE_NONCQ, },
+{ HTS541010G9SA00,MBZOC60D, ATA_HORKAGE_NONCQ, },


The thread you link to seems like an irq problem, especially because it 
worked in 2.6.20 and prior?


Jeff


According to this post:

http://lkml.org/lkml/2007/3/9/475

with 2.6.21-rc3, it started working after the kernel disabled NCQ 
because of too many errors. That seems to point away from it being an 
IRQ problem, as you'd expect it to not work at all. I don't expect the 
interrupts would be handled any differently between NCQ and non-NCQ 
commands. However, apparently disabling ACPI also prevents the problem, 
which does seem a bit odd.


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] libata: add NCQ blacklist entries from Silicon Image Windows driver (v2)

2007-04-02 Thread Robert Hancock

This adds some NCQ blacklist entries taken from the Silicon Image 3124/3132
Windows driver .inf files. There are some confirming reports of problems
with these drives under Linux (for example http://lkml.org/lkml/2007/3/4/178)
so let's disable NCQ on these drives.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.21-rc5-git9/drivers/ata/libata-core.c 2007-04-02 
21:03:29.0 -0600
+++ linux-2.6.21-rc5-git9edit/drivers/ata/libata-core.c 2007-04-02 
21:26:23.0 -0600
@@ -3363,6 +3363,11 @@ static const struct ata_blacklist_entry 
	{ Maxtor 6L250S0, BANC1G10, ATA_HORKAGE_NONCQ },

/* NCQ hard hangs device under heavier load, needs hard power cycle */
{ Maxtor 6B250S0,   BANC1B70,   ATA_HORKAGE_NONCQ },
+   /* Blacklist entries taken from Silicon Image 3124/3132
+  Windows driver .inf file - also several Linux problem reports */
+   { HTS541060G9SA00,MB3OC60D, ATA_HORKAGE_NONCQ, },
+   { HTS541080G9SA00,MB4OC60D, ATA_HORKAGE_NONCQ, },
+   { HTS541010G9SA00,MBZOC60D, ATA_HORKAGE_NONCQ, },

/* Devices with NCQ limits */


-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: sata_nv ADMA controller lockup investigation

2007-03-20 Thread Robert Hancock

Neil Schemenauer wrote:

Not sure if this helps.  I'm getting this reset with 2.6.21-rc4.
After the reset the controller seems to work again.


...

ata2.00: ATA-7: Maxtor 6V300F0, VA111630, max UDMA/133
ata2.00: 586114704 sectors, multi 16: LBA48 NCQ (depth 31/32)


...


ata2: EH in ADMA mode, notifier 0x0 notifier_error 0x0 gen_ctl 0x1501000 status 
0x400 next cpb count 0x0 next cpb idx 0x0
ata2: CPB 1: ctl_flags 0x1f, resp_flags 0x2
ata2: timeout waiting for ADMA IDLE, stat=0x400
ata2: timeout waiting for ADMA LEGACY, stat=0x400
ata2.00: exception Emask 0x0 SAct 0x2 SErr 0x0 action 0x2 frozen
ata2.00: cmd 61/00:08:72:44:22/02:00:21:00:00/40 tag 1 cdb 0x0 data 262144 out
 res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x4 (timeout)
ata2: soft resetting port
ata2: SATA link up 3.0 Gbps (SStatus 123 SControl 300)
ata2.00: configured for UDMA/133
ata2: EH complete
SCSI device sda: 586114704 512-byte hdwr sectors (300091 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: write cache: enabled, read cache: enabled, doesn't support DPO 
or FUA


That one looks like a drive-side issue. CPB resp_flags 2 indicates the 
drive accepted the command and the controller is still waiting for a 
response.


Could be that this is another drive that needs to be added to the NCQ 
blacklist, some similar Maxtor models seem to have issues..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 29/30] sata_nv: don't read shadow registers when in ADMA mode

2007-03-09 Thread Robert Hancock

Jeff Garzik wrote:

[EMAIL PROTECTED] wrote:

From: Robert Hancock [EMAIL PROTECTED]

Reading from the ATA shadow registers while we are in ADMA mode may cause
undefined behavior.  Don't read the ATA status register when completing
commands for this reason, it shouldn't be needed as the controller will
notify us if the command failed.  Also, don't allow commands with result
taskfile requested to execute in ADMA mode, since that requires accessing
the shadow registers.  We also still need to override tf_read since 
libata
will read the result taskfile on a command failure, and we need to go 
into

port register mode before allowing this.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]
Signed-off-by: Andrew Morton [EMAIL PROTECTED]
---

 drivers/ata/sata_nv.c |   33 -
 1 file changed, 20 insertions(+), 13 deletions(-)


Robert, do you think this should be pushed into #upstream-fixes 
(2.6.21-rc)?


I lean towards yes, since it is a needed-by-hardware fix, but I also 
am interested in testing feedback since it is so late in the 2.6.21-rc 
game.


I would lean toward that as well, but it would be good to get some 
testing from some sata_nv ADMA users to make sure it doesn't do anything 
funny for them..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 29/30] sata_nv: don't read shadow registers when in ADMA mode

2007-03-09 Thread Robert Hancock

Alistair John Strachan wrote:

I lean towards yes, since it is a needed-by-hardware fix, but I also
am interested in testing feedback since it is so late in the 2.6.21-rc
game.

I would lean toward that as well, but it would be good to get some
testing from some sata_nv ADMA users to make sure it doesn't do anything
funny for them..


Since I've been a bit of a problem case this time, I'd be happy to test it.

Can I assume that I can apply the patch you sent to Jeff [PATCH] sata_nv: 
revert use of notifiers for now, and apply this one, to -rc3, and then be 
able to usefully test?


Yes, you should be able to.

--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/


-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] sata_nv: revert use of notifiers for now

2007-03-08 Thread Robert Hancock

Commit 721449bf0d51213fe3abf0ac3e3561ef9ea7827a added support for using the
ADMA notifier bits to determine which commands to check for completion.
However there have been reports that this causes command timeouts in certain
cases. This is still being investigated. In addition, apparently the notifiers
won't work if ADMA is disabled on the other port as a result of an ATAPI device
being connected, and we don't handle this case properly.

For now, just restore the previous behavior of checking all active commands
to see if they are complete, without relying on the notifiers.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.21-rc3-git3/drivers/ata/sata_nv.c 2007-03-08 17:15:25.0 
-0600
+++ linux-2.6.21-rc3-git3edit/drivers/ata/sata_nv.c 2007-03-08 
17:19:42.0 -0600
@@ -874,8 +874,14 @@

if (status  (NV_ADMA_STAT_DONE |
  NV_ADMA_STAT_CPBERR)) {
-   u32 check_commands = notifier | notifier_error;
+   u32 check_commands;
int pos, error = 0;
+
+   if(ata_tag_valid(ap-active_tag))
+   check_commands = 1  ap-active_tag;
+   else
+   check_commands = ap-sactive;
+
/** Check CPBs for completed commands */
while ((pos = ffs(check_commands))  !error) {
pos--;

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] sata_nv: don't read shadow registers when in ADMA mode

2007-03-05 Thread Robert Hancock

Reading from the ATA shadow registers while we are in ADMA mode may cause
undefined behavior. Don't read the ATA status register when completing commands
for this reason, it shouldn't be needed as the controller will notify us if
the command failed. Also, don't allow commands with result taskfile requested
to execute in ADMA mode, since that requires accessing the shadow registers.
We also still need to override tf_read since libata will read the result
taskfile on a command failure, and we need to go into port register mode
before allowing this.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.21-rc2-git3/drivers/ata/sata_nv.c 2007-03-04 14:44:05.0 
-0600
+++ linux-2.6.21-rc2-git3edit/drivers/ata/sata_nv.c 2007-03-05 
19:55:14.0 -0600
@@ -260,6 +260,7 @@ static int nv_adma_port_resume(struct at
static void nv_adma_error_handler(struct ata_port *ap);
static void nv_adma_host_stop(struct ata_host *host);
static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc);
+static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf);

enum nv_host_type
{
@@ -435,7 +436,7 @@ static const struct ata_port_operations 
static const struct ata_port_operations nv_adma_ops = {

.port_disable   = ata_port_disable,
.tf_load= ata_tf_load,
-   .tf_read= ata_tf_read,
+   .tf_read= nv_adma_tf_read,
.check_atapi_dma= nv_adma_check_atapi_dma,
.exec_command   = ata_exec_command,
.check_status   = ata_check_status,
@@ -667,6 +668,18 @@ static int nv_adma_check_atapi_dma(struc
return !(pp-flags  NV_ADMA_ATAPI_SETUP_COMPLETE);
}

+static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+   /* Since commands where a result TF is requested are not
+  executed in ADMA mode, the only time this function will be called
+  in ADMA mode will be if a command fails. In this case we
+  don't care about going into register mode with ADMA commands
+  pending, as the commands will all shortly be aborted anyway. */
+   nv_adma_register_mode(ap);
+
+   ata_tf_read(ap, tf);
+}
+
static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
{
unsigned int idx = 0;
@@ -738,19 +751,11 @@ static int nv_adma_check_cpb(struct ata_
return 1;
}

-   if (flags  NV_CPB_RESP_DONE) {
+   if (likely(flags  NV_CPB_RESP_DONE)) {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
VPRINTK(CPB flags done, flags=0x%x\n, flags);
if (likely(qc)) {
-   /* Grab the ATA port status for non-NCQ commands.
-  For NCQ commands the current status may have nothing 
to do with
-  the command just completed. */
-   if (qc-tf.protocol != ATA_PROT_NCQ) {
-   u8 ata_status = readb(pp-ctl_block + 
(ATA_REG_STATUS * 4));
-   qc-err_mask |= ac_err_mask(ata_status);
-   }
-   DPRINTK(Completing qc from tag %d with err_mask 
%u\n,cpb_num,
-   qc-err_mask);
+   DPRINTK(Completing qc from tag %d\n,cpb_num);
ata_qc_complete(qc);
} else {
struct ata_eh_info *ehi = ap-eh_info;
@@ -1161,9 +1166,11 @@ static int nv_adma_use_reg_mode(struct a
struct nv_adma_port_priv *pp = qc-ap-private_data;

/* ADMA engine can only be used for non-ATAPI DMA commands,
-  or interrupt-driven no-data commands. */
+  or interrupt-driven no-data commands, where a result taskfile
+  is not required. */
if((pp-flags  NV_ADMA_ATAPI_SETUP_COMPLETE) ||
-  (qc-tf.flags  ATA_TFLAG_POLLING))
+  (qc-tf.flags  ATA_TFLAG_POLLING) ||
+  (qc-flags  ATA_QCFLAG_RESULT_TF))
return 1;

if((qc-flags  ATA_QCFLAG_DMAMAP) ||

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: libata FUA revisited

2007-02-22 Thread Robert Hancock

Ric Wheeler wrote:

I think that FUA was designed for a different use case than what Linux
is using barriers for currently. The advantage with FUA is when you have
before barrier, after barrier and don't care sets, where only the
specific things you care about ordering are in the before/after barrier
sets. Then you can do this:

Issue all before barrier requests with FUA bit set
Wait for all those to complete
Issue all after barrier requests with FUA bit set
Wait for all those to complete


A couple of issues with this would be in how to support our current 
semantics of fsync().  Today, the flush behavior of the barrier/fsync 
combination means that applications can have a hard promise of data on 
platter for any file after a successful fsync command.


If I understand correctly, to get a similar semantic from a pure FUA 
implementation would require us to tag all file IO as FUA.


I suspect that this would actually be less efficient since it would not 
allow the drives to reorder IO's up to the point that we actually care 
(fsync time).


I think for the fsync case a cache flush would likely still be needed, 
unless the app was only writing small amounts of data in between the 
syncs (it may be complicated to figure out when to do that, though).


The other big user of barriers is the internal transaction of journaled 
file systems.  It would seem that we would need to tag each write from 
the journal with a FUA IO as well.  Again, we might actually go more 
slowly in some cases as you mention below.


The limited queue depth of NCQ would seem to make it much harder to have 
a win in this case...


I think the journal write case is less problematic as there are likely 
to be much fewer/smaller requests involved which would be more likely to 
fit inside the queue..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/


-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] libata: add NCQ blacklist entries from Silicon Image Windows driver

2007-02-22 Thread Robert Hancock

Ask Bjørn Hansen wrote:


On Feb 21, 2007, at 10:57 PM, Jeff Garzik wrote:


+/* The following blacklist entries are taken from the Windows
+   driver .inf files for the Silicon Image 3124 and 3132. */
+{ Maxtor 7B250S0,BANC1B70,ATA_HORKAGE_NONCQ, },

[...]


Do we have information that these drives fail on non-SiI controllers?


At least tangentially related:

On one of my boxes (running 2.6.18-1.2869 from Fedora) I have a couple 
of other Maxtor drives that didn't like NCQ.   They are on a JMicron 
20360/20363 (ahci driver).  (There's also a Promise 300 TX4 card in the 
box and an Intel ICH8 that shows up with ata_piix).


model and (partial) firmware revision of the drives:
Maxtor 7V300F0  VA11
Maxtor 7B300S0  BANC

Until I disabled NCQ I got gazillions of messages like the ones below 
and absymal performance.


  - ask


ata5: spurious interrupt (irq_stat 0x8 active_tag -84148995 sactive 0xf)


Sounds like those are some that we should be blacklisting as well, 
unless Eric has a good reason why not (CCing). Can you provide the full 
firmware revision strings from those drives, i.e. from hdparm -I?


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: libata FUA revisited

2007-02-21 Thread Robert Hancock

Tejun Heo wrote:

Aside from the issue above, as I mentioned elsewhere, lots of NCQ drives
don't support non-NCQ FUA writes..


To me, using the NCQ FUA bit on such drives doesn't seem to be a good
idea.  Maybe I'm just too chicken but it's not like we can gain a lot
from doing FUA at this point.  Are there a lot of drives which support
NCQ but not FUA opcodes?


Well, it's hard to say whether lots have this issue, but the ones I 
have in my machine, Seagate 7200.7 NCQ 160GB (ST3160827AS) and 7200.10 
320GB (ST3320620AS), both support NCQ and don't support non-NCQ FUA, and 
those (especially the latter) seem to be very popular models.


Likely Seagate didn't implement that command since they figured nobody 
would use that if they had NCQ..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] libata: add NCQ blacklist entries from Silicon Image Windows driver

2007-02-21 Thread Robert Hancock

This patch adds in some NCQ blacklist entries taken from the Silicon
Image Windows drivers' .inf files for the 3124 and 3132 controllers.
These entries were marked as DisableSataQueueing. Assume these are
in their blacklist for a reason and disable NCQ on these drives.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.21-rc1edit/drivers/ata/libata-core.c.prev 2007-02-21 
22:23:05.0 -0600
+++ linux-2.6.21-rc1edit/drivers/ata/libata-core.c  2007-02-21 
22:25:44.0 -0600
@@ -3269,6 +3269,13 @@ static const struct ata_blacklist_entry 


/* Devices with NCQ limits */

+   /* The following blacklist entries are taken from the Windows
+  driver .inf files for the Silicon Image 3124 and 3132. */
+   { Maxtor 7B250S0,   BANC1B70,   ATA_HORKAGE_NONCQ, },
+   { HTS541060G9SA00,  MB3OC60D,   ATA_HORKAGE_NONCQ, },
+   { HTS541080G9SA00,  MB4OC60D,   ATA_HORKAGE_NONCQ, },
+   { HTS541010G9SA00,  MBZOC60D,   ATA_HORKAGE_NONCQ, },
+
/* End Marker */
{ }
};

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] sata_nv: complain on spurious completion notifiers

2007-02-21 Thread Robert Hancock

Recently Tejun wrote a patch to ahci.c to make it raise a HSM violation
if the drive attempted to complete a tag that wasn't outstanding. We could
run into the same problem with sata_nv ADMA. This adds code to raise a HSM
violation error if the controller gives us a notifier tag that isn't
outstanding, since the drive may be issuing spurious completions.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.21-rc1edit/drivers/ata/sata_nv.c.prev 2007-02-21 
22:17:31.0 -0600
+++ linux-2.6.21-rc1edit/drivers/ata/sata_nv.c  2007-02-21 22:22:14.0 
-0600
@@ -740,6 +740,17 @@ static int nv_adma_check_cpb(struct ata_
DPRINTK(Completing qc from tag %d with err_mask 
%u\n,cpb_num,
qc-err_mask);
ata_qc_complete(qc);
+   } else {
+   struct ata_eh_info *ehi = ap-eh_info;
+   /* Notifier bits set without a command may indicate the 
drive
+  is misbehaving. Raise host state machine violation 
on this
+  condition. */
+   ata_port_printk(ap, KERN_ERR, notifier for tag %d with no 
command?\n,
+   cpb_num);
+   ehi-err_mask |= AC_ERR_HSM;
+   ehi-action |= ATA_EH_SOFTRESET;
+   ata_port_freeze(ap);
+   return 1;
}
}
return 0;

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] sata_nv: kill old private BMDMA helper functions

2007-02-20 Thread Robert Hancock

sata_nv implemented its own copies of the BMDMA helper functions for ADMA,
since the ADMA BMDMA status registers are PIO while the other registers
are MMIO, and this was the only way to handle this previously. Now that
we have iomap support, the standard routines should just work, so use them.
The only thing we need to override as far as ADMA and BMDMA is the
post_internal_cmd callback, where we should only call ata_post_internal_cmd
if we are in port-register mode.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-git14edit/drivers/ata/sata_nv.c.before_cleanup 2007-02-20 
19:42:32.0 -0600
+++ linux-2.6.20-git14edit/drivers/ata/sata_nv.c2007-02-20 
19:45:44.0 -0600
@@ -255,10 +255,7 @@
static int nv_adma_port_resume(struct ata_port *ap);
static void nv_adma_error_handler(struct ata_port *ap);
static void nv_adma_host_stop(struct ata_host *host);
-static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc);
-static void nv_adma_bmdma_start(struct ata_queued_cmd *qc);
-static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc);
-static u8 nv_adma_bmdma_status(struct ata_port *ap);
+static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc);

enum nv_host_type
{
@@ -433,16 +430,16 @@
.exec_command   = ata_exec_command,
.check_status   = ata_check_status,
.dev_select = ata_std_dev_select,
-   .bmdma_setup= nv_adma_bmdma_setup,
-   .bmdma_start= nv_adma_bmdma_start,
-   .bmdma_stop = nv_adma_bmdma_stop,
-   .bmdma_status   = nv_adma_bmdma_status,
+   .bmdma_setup= ata_bmdma_setup,
+   .bmdma_start= ata_bmdma_start,
+   .bmdma_stop = ata_bmdma_stop,
+   .bmdma_status   = ata_bmdma_status,
.qc_prep= nv_adma_qc_prep,
.qc_issue   = nv_adma_qc_issue,
.freeze = nv_ck804_freeze,
.thaw   = nv_ck804_thaw,
.error_handler  = nv_adma_error_handler,
-   .post_internal_cmd  = nv_adma_bmdma_stop,
+   .post_internal_cmd  = nv_adma_post_internal_cmd,
.data_xfer  = ata_data_xfer,
.irq_handler= nv_adma_interrupt,
.irq_clear  = nv_adma_irq_clear,
@@ -899,73 +896,12 @@
iowrite8(ioread8(dma_stat_addr), dma_stat_addr);
}

-static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc)
-{
-   struct ata_port *ap = qc-ap;
-   unsigned int rw = (qc-tf.flags  ATA_TFLAG_WRITE);
-   struct nv_adma_port_priv *pp = ap-private_data;
-   u8 dmactl;
-
-   if(!(pp-flags  NV_ADMA_PORT_REGISTER_MODE)) {
-   WARN_ON(1);
-   return;
-   }
-
-   /* load PRD table addr. */
-   iowrite32(ap-prd_dma, ap-ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
-
-   /* specify data direction, triple-check start bit is clear */
-   dmactl = ioread8(ap-ioaddr.bmdma_addr + ATA_DMA_CMD);
-   dmactl = ~(ATA_DMA_WR | ATA_DMA_START);
-   if (!rw)
-   dmactl |= ATA_DMA_WR;
-
-   iowrite8(dmactl, ap-ioaddr.bmdma_addr + ATA_DMA_CMD);
-
-   /* issue r/w command */
-   ata_exec_command(ap, qc-tf);
-}
-
-static void nv_adma_bmdma_start(struct ata_queued_cmd *qc)
-{
-   struct ata_port *ap = qc-ap;
-   struct nv_adma_port_priv *pp = ap-private_data;
-   u8 dmactl;
-
-   if(!(pp-flags  NV_ADMA_PORT_REGISTER_MODE)) {
-   WARN_ON(1);
-   return;
-   }
-
-   /* start host DMA transaction */
-   dmactl = ioread8(ap-ioaddr.bmdma_addr + ATA_DMA_CMD);
-   iowrite8(dmactl | ATA_DMA_START,
-ap-ioaddr.bmdma_addr + ATA_DMA_CMD);
-}
-
-static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc)
+static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc)
{
-   struct ata_port *ap = qc-ap;
-   struct nv_adma_port_priv *pp = ap-private_data;
-
-   if(!(pp-flags  NV_ADMA_PORT_REGISTER_MODE))
-   return;
-
-   /* clear start/stop bit */
-   iowrite8(ioread8(ap-ioaddr.bmdma_addr + ATA_DMA_CMD)  ~ATA_DMA_START,
-ap-ioaddr.bmdma_addr + ATA_DMA_CMD);
-
-   /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
-   ata_altstatus(ap);/* dummy read */
-}
-
-static u8 nv_adma_bmdma_status(struct ata_port *ap)
-{
-   struct nv_adma_port_priv *pp = ap-private_data;
-
-   WARN_ON(!(pp-flags  NV_ADMA_PORT_REGISTER_MODE));
+   struct nv_adma_port_priv *pp = qc-ap-private_data;

-   return ioread8(ap-ioaddr.bmdma_addr + ATA_DMA_STATUS);
+   if(pp-flags  NV_ADMA_PORT_REGISTER_MODE)
+   ata_bmdma_post_internal_cmd(qc);
}

static int nv_adma_port_start(struct ata_port *ap)

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo

Re: libata FUA revisited

2007-02-19 Thread Robert Hancock

Jens Axboe wrote:

But we can't really change that, since you need the cache flushed before
issuing the FUA write. I've been advocating for an ordered bit for
years, so that we could just do:

3. w/FUA+ORDERED

normal operation - barrier issued - write barrier FUA+ORDERED
 - normal operation resumes

So we don't have to serialize everything both at the block and device
level. I would have made FUA imply this already, but apparently it's not
what MS wanted FUA for, so... The current implementations take the FUA
bit (or WRITE FUA) as a hint to boost it to head of queue, so you are
almost certainly going to jump ahead of already queued writes. Which we
of course really do not.


I think that FUA was designed for a different use case than what Linux 
is using barriers for currently. The advantage with FUA is when you have 
before barrier, after barrier and don't care sets, where only the 
specific things you care about ordering are in the before/after barrier 
sets. Then you can do this:


Issue all before barrier requests with FUA bit set
Wait for all those to complete
Issue all after barrier requests with FUA bit set
Wait for all those to complete

Meanwhile a bunch of don't care requests could be going through on the 
device in the background. If we could do this, then I think there would 
be an advantage. Right now, it just saves a command to the drive when 
we're flushing on the post-barrier writes.


This would only be efficient with NCQ FUA, because regular FUA forces 
the requests to complete serially, whereas in this case we don't really 
care what order the individual requests finish, we just care about the 
ordering of the pre vs. post barrier requests.



I'm not too nervous about the FUA write commands, I hope we can safely
assume that if you set the FUA supported bit in the id AND the write fua
command doesn't get aborted, that FUA must work. Anything else would
just be an immensely stupid implementation. NCQ+FUA is more tricky, I
agree that it being just a command bit does make it more likely that it
could be ignored. And that is indeed a danger. Given state of NCQ in
early firmware drives, I would not at all be surprised if the drive
vendors screwed that up too.

But, since we don't have the ordered bit for NCQ/FUA anyway, we do need
to drain the drive queue before issuing the WRITE/FUA. And at that point
we may as well not use the NCQ command, just go for the regular non-NCQ
FUA write. I think that should be safe.


Aside from the issue above, as I mentioned elsewhere, lots of NCQ drives 
don't support non-NCQ FUA writes..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] sata_nv: delay on switching between NCQ and non-NCQ commands

2007-02-19 Thread Robert Hancock

This patch appears to solve some problems with commands timing out in
cases where an NCQ command is immediately followed by a non-NCQ command
(or possibly vice versa). This is a rather ugly solution, but until we
know more about why this is needed, this is about all we can do.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-git6edit/drivers/ata/sata_nv.c.before_hacking  2007-02-15 
18:19:13.0 -0600
+++ linux-2.6.20-git6edit/drivers/ata/sata_nv.c 2007-02-15 22:36:02.0 
-0600
@@ -219,6 +219,7 @@
void __iomem *  gen_block;
void __iomem *  notifier_clear_block;
u8  flags;
+   int last_issue_ncq;
};

struct nv_host_priv {
@@ -1260,6 +1261,7 @@
{
struct nv_adma_port_priv *pp = qc-ap-private_data;
void __iomem *mmio = pp-ctl_block;
+   int curr_ncq = (qc-tf.protocol == ATA_PROT_NCQ);

VPRINTK(ENTER\n);

@@ -1274,6 +1276,14 @@
/* write append register, command tag in lower 8 bits
   and (number of cpbs to append -1) in top 8 bits */
wmb();
+
+   if(curr_ncq != pp-last_issue_ncq) {
+   /* Seems to need some delay before switching between NCQ and 
non-NCQ
+  commands, else we get command timeouts and such. */
+   udelay(20);
+   pp-last_issue_ncq = curr_ncq;
+   }
+
writew(qc-tag, mmio + NV_ADMA_APPEND);

DPRINTK(Issued tag %u\n,qc-tag);

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] libata: warn if speed limited due to 40-wire cable (v2)

2007-02-19 Thread Robert Hancock

Here's a revised version of my previous patch to warn the user if a
drive's transfer rate is limited because of a 40-wire cable detection.
This one hopefully addresses Alan's previous comments - we now do this
at the very end of the function, and the ugly if condition has been
cleaned up somewhat. Also, it's been inadvertently tested (it seems that
pata_amd Nvidia cable detection is broken in current -git..)

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-git6/drivers/ata/libata-core.c 2007-02-11 17:31:19.0 
-0600
+++ linux-2.6.20-git6edit/drivers/ata/libata-core.c 2007-02-13 
19:15:58.0 -0600
@@ -3305,19 +3305,7 @@ static void ata_dev_xfermask(struct ata_
xfer_mask = ata_pack_xfermask(ap-pio_mask,
  ap-mwdma_mask, ap-udma_mask);

-   /* Apply cable rule here.  Don't apply it early because when
-* we handle hot plug the cable type can itself change.
-*/
-   if (ap-cbl == ATA_CBL_PATA40)
-   xfer_mask = ~(0xF8  ATA_SHIFT_UDMA);
-   /* Apply drive side cable rule. Unknown or 80 pin cables reported
-* host side are checked drive side as well. Cases where we know a
-* 40wire cable is used safely for 80 are not checked here.
-*/
-if (ata_drive_40wire(dev-id)  (ap-cbl == ATA_CBL_PATA_UNK || 
ap-cbl == ATA_CBL_PATA80))
-   xfer_mask = ~(0xF8  ATA_SHIFT_UDMA);
-
-
+   /* drive modes available */
xfer_mask = ata_pack_xfermask(dev-pio_mask,
   dev-mwdma_mask, dev-udma_mask);
xfer_mask = ata_id_xfermask(dev-id);
@@ -3348,6 +3336,25 @@ static void ata_dev_xfermask(struct ata_
if (ap-ops-mode_filter)
xfer_mask = ap-ops-mode_filter(ap, dev, xfer_mask);

+   /* Apply cable rule here.  Don't apply it early because when
+* we handle hot plug the cable type can itself change.
+* Check this last so that we know if the transfer rate was
+* solely limited by the cable.
+* Unknown or 80 wire cables reported host side are checked
+* drive side as well. Cases where we know a 40wire cable
+* is used safely for 80 are not checked here.
+*/
+   if (xfer_mask  (0xF8  ATA_SHIFT_UDMA))
+   /* UDMA/44 or higher would be available */
+   if((ap-cbl == ATA_CBL_PATA40) ||
+   (ata_drive_40wire(dev-id) 
+(ap-cbl == ATA_CBL_PATA_UNK ||
+ ap-cbl == ATA_CBL_PATA80))) {
+   ata_dev_printk(dev, KERN_WARNING,
+limited to UDMA/33 due to 40-wire cable\n);
+   xfer_mask = ~(0xF8  ATA_SHIFT_UDMA);
+   }
+
ata_unpack_xfermask(xfer_mask, dev-pio_mask,
dev-mwdma_mask, dev-udma_mask);
}

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/5] sata_nv: various cleanups and fixes

2007-02-19 Thread Robert Hancock

This patch series contains several fixes for issues I noticed while
debugging some command timeout problems. None of these proved to be
related to that issue, but they fall into the category of things
we should be doing anyway.

Split into separate patches to ease bisecting in case of issues.



-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] sata_nv: cleanup CPB and APRD initialization

2007-02-19 Thread Robert Hancock

Clean up the initialization of the CPB and APRD structures so that we
strictly follow the rules for ordering of writes to the CPB flags and
response flags, and prevent duplicate initialization.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-git6edit/drivers/ata/sata_nv.c 2007-02-15 22:36:02.0 
-0600
+++ linux-2.6.20-git6edit/drivers/ata/sata_nv.c.delayandfixes   2007-02-19 
17:00:14.0 -0600
@@ -1164,11 +1159,7 @@ static void nv_adma_fill_aprd(struct ata
  int idx,
  struct nv_adma_prd *aprd)
{
-   u8 flags;
-
-   memset(aprd, 0, sizeof(struct nv_adma_prd));
-
-   flags = 0;
+   u8 flags = 0;
if (qc-tf.flags  ATA_TFLAG_WRITE)
flags |= NV_APRD_WRITE;
if (idx == qc-n_elem - 1)
@@ -1179,6 +1170,7 @@ static void nv_adma_fill_aprd(struct ata
aprd-addr  = cpu_to_le64(((u64)sg_dma_address(sg)));
aprd-len   = cpu_to_le32(((u32)sg_dma_len(sg))); /* len in bytes */
aprd-flags = flags;
+   aprd-packet_len = 0;
}

static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
@@ -1199,6 +1191,8 @@ static void nv_adma_fill_sg(struct ata_q
}
if (idx  5)
cpb-next_aprd = cpu_to_le64(((u64)(pp-aprd_dma + 
NV_ADMA_SGTBL_SZ * qc-tag)));
+   else
+   cpb-next_aprd = cpu_to_le64(0);
}

static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
@@ -1231,7 +1225,10 @@ static void nv_adma_qc_prep(struct ata_q
return;
}

-   memset(cpb, 0, sizeof(struct nv_adma_cpb));
+   cpb-resp_flags = NV_CPB_RESP_DONE;
+   wmb();
+   cpb-ctl_flags = 0;
+   wmb();

cpb-len = 3;
cpb-tag = qc-tag;
@@ -1255,6 +1252,8 @@ static void nv_adma_qc_prep(struct ata_q
   finished filling in all of the contents */
wmb();
cpb-ctl_flags = ctl_flags;
+   wmb();
+   cpb-resp_flags = 0;
}

static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] sata_nv: Add CPB register info to error_handler output

2007-02-19 Thread Robert Hancock

When error handling occurs with pending commands, output the contents
of the next CPB count and next CPB index registers as well as the others,
since these may be useful for debugging.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-git6edit/drivers/ata/sata_nv.c 2007-02-15 22:36:02.0 
-0600
+++ linux-2.6.20-git6edit/drivers/ata/sata_nv.c.delayandfixes   2007-02-19 
17:00:14.0 -0600
@@ -1462,10 +1461,14 @@ static void nv_adma_error_handler(struct
u32 notifier_error = readl(mmio + 
NV_ADMA_NOTIFIER_ERROR);
u32 gen_ctl = readl(pp-gen_block + NV_ADMA_GEN_CTL);
u32 status = readw(mmio + NV_ADMA_STAT);
+   u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT);
+   u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX);

ata_port_printk(ap, KERN_ERR, EH in ADMA mode, notifier 
0x%X 
-   notifier_error 0x%X gen_ctl 0x%X status 
0x%X\n,
-   notifier, notifier_error, gen_ctl, status);
+   notifier_error 0x%X gen_ctl 0x%X status 0x%X 
+   next cpb count 0x%X next cpb idx 0x%x\n,
+   notifier, notifier_error, gen_ctl, status,
+   cpb_count, next_cpb_idx);

for( i=0;iNV_ADMA_MAX_CPBS;i++) {
struct nv_adma_cpb *cpb = pp-cpb[i];

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/5] sata_nv: enable hotplug interrupt and fix some readl/readw mismatches

2007-02-19 Thread Robert Hancock

We already have code that handles hotplug interrupt indications in ADMA
mode, this turns on the control flag that actually enables these interrupts.
Also fixes some cases in the same functions where a 16-bit register was read
using a readl instead of a readw.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-git6edit/drivers/ata/sata_nv.c 2007-02-15 22:36:02.0 
-0600
+++ linux-2.6.20-git6edit/drivers/ata/sata_nv.c.delayandfixes   2007-02-19 
17:00:14.0 -0600
@@ -1041,14 +1034,15 @@ static int nv_adma_port_start(struct ata

/* clear GO for register mode, enable interrupt */
tmp = readw(mmio + NV_ADMA_CTL);
-   writew( (tmp  ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL);
+   writew( (tmp  ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
+NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);

tmp = readw(mmio + NV_ADMA_CTL);
writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-   readl( mmio + NV_ADMA_CTL );/* flush posted write */
+   readw( mmio + NV_ADMA_CTL );/* flush posted write */
udelay(1);
writew(tmp  ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-   readl( mmio + NV_ADMA_CTL );/* flush posted write */
+   readw( mmio + NV_ADMA_CTL );/* flush posted write */

return 0;
}
@@ -1100,14 +1094,15 @@ static int nv_adma_port_resume(struct at

/* clear GO for register mode, enable interrupt */
tmp = readw(mmio + NV_ADMA_CTL);
-   writew((tmp  ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL);
+   writew( (tmp  ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN |
+NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL);

tmp = readw(mmio + NV_ADMA_CTL);
writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-   readl( mmio + NV_ADMA_CTL );/* flush posted write */
+   readw( mmio + NV_ADMA_CTL );/* flush posted write */
udelay(1);
writew(tmp  ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-   readl( mmio + NV_ADMA_CTL );/* flush posted write */
+   readw( mmio + NV_ADMA_CTL );/* flush posted write */

return 0;
}
@@ -1490,10 +1493,10 @@ static void nv_adma_error_handler(struct
/* Reset channel */
tmp = readw(mmio + NV_ADMA_CTL);
writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-   readl( mmio + NV_ADMA_CTL );/* flush posted write */
+   readw( mmio + NV_ADMA_CTL );/* flush posted write */
udelay(1);
writew(tmp  ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
-   readl( mmio + NV_ADMA_CTL );/* flush posted write */
+   readw( mmio + NV_ADMA_CTL );/* flush posted write */
}

ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/5] sata_nv: Cleanup taskfile setup

2007-02-19 Thread Robert Hancock

This edits the taskfile setup to more closely match the way that libata
sends the taskfile for other controllers. This avoids putting taskfile writes
into the CPB buffer that are not needed according to the taskfile flags.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-git6edit/drivers/ata/sata_nv.c 2007-02-15 22:36:02.0 
-0600
+++ linux-2.6.20-git6edit/drivers/ata/sata_nv.c.delayandfixes   2007-02-19 
17:00:14.0 -0600
@@ -662,29 +662,30 @@ static unsigned int nv_adma_tf_to_cpb(st
{
unsigned int idx = 0;

-   cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE  8) | tf-device | WNB);
-
-   if ((tf-flags  ATA_TFLAG_LBA48) == 0) {
-   cpb[idx++] = cpu_to_le16(IGN);
-   cpb[idx++] = cpu_to_le16(IGN);
-   cpb[idx++] = cpu_to_le16(IGN);
-   cpb[idx++] = cpu_to_le16(IGN);
-   cpb[idx++] = cpu_to_le16(IGN);
-   }
-   else {
-   cpb[idx++] = cpu_to_le16((ATA_REG_ERR8) | 
tf-hob_feature);
-   cpb[idx++] = cpu_to_le16((ATA_REG_NSECT  8) | tf-hob_nsect);
-   cpb[idx++] = cpu_to_le16((ATA_REG_LBAL   8) | tf-hob_lbal);
-   cpb[idx++] = cpu_to_le16((ATA_REG_LBAM   8) | tf-hob_lbam);
-   cpb[idx++] = cpu_to_le16((ATA_REG_LBAH   8) | tf-hob_lbah);
-   }
-   cpb[idx++] = cpu_to_le16((ATA_REG_ERR 8) | tf-feature);
-   cpb[idx++] = cpu_to_le16((ATA_REG_NSECT   8) | tf-nsect);
-   cpb[idx++] = cpu_to_le16((ATA_REG_LBAL8) | tf-lbal);
-   cpb[idx++] = cpu_to_le16((ATA_REG_LBAM8) | tf-lbam);
-   cpb[idx++] = cpu_to_le16((ATA_REG_LBAH8) | tf-lbah);
+   if(tf-flags  ATA_TFLAG_ISADDR) {
+   if (tf-flags  ATA_TFLAG_LBA48) {
+   cpb[idx++] = cpu_to_le16((ATA_REG_ERR8) | 
tf-hob_feature | WNB);
+   cpb[idx++] = cpu_to_le16((ATA_REG_NSECT  8) | 
tf-hob_nsect);
+   cpb[idx++] = cpu_to_le16((ATA_REG_LBAL   8) | 
tf-hob_lbal);
+   cpb[idx++] = cpu_to_le16((ATA_REG_LBAM   8) | 
tf-hob_lbam);
+   cpb[idx++] = cpu_to_le16((ATA_REG_LBAH   8) | 
tf-hob_lbah);
+   cpb[idx++] = cpu_to_le16((ATA_REG_ERR 8) | 
tf-feature);
+   } else
+   cpb[idx++] = cpu_to_le16((ATA_REG_ERR 8) | 
tf-feature | WNB);
+   
+   cpb[idx++] = cpu_to_le16((ATA_REG_NSECT   8) | tf-nsect);
+   cpb[idx++] = cpu_to_le16((ATA_REG_LBAL8) | tf-lbal);
+   cpb[idx++] = cpu_to_le16((ATA_REG_LBAM8) | tf-lbam);
+   cpb[idx++] = cpu_to_le16((ATA_REG_LBAH8) | tf-lbah);
+   }
+   
+   if(tf-flags  ATA_TFLAG_DEVICE)
+   cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE  8) | tf-device);

cpb[idx++] = cpu_to_le16((ATA_REG_CMD 8) | tf-command | CMDEND);
+   
+   while(idx  12)
+   cpb[idx++] = cpu_to_le16(IGN);

return idx;
}

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/5] sata_nv: Use notifier for completion checks

2007-02-19 Thread Robert Hancock

The hardware provides us a notifier register that indicates what command
tags have completed. Use this to determine which CPBs to check, rather
than blindly checking all active CPBs. This should provide a minor
performance win, since if the controller has touched some of these
incomplete CPBs, accessing them will likely result in a cache miss.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-git6edit/drivers/ata/sata_nv.c 2007-02-15 22:36:02.0 
-0600
+++ linux-2.6.20-git6edit/drivers/ata/sata_nv.c.delayandfixes   2007-02-19 
17:00:14.0 -0600
@@ -853,22 +854,14 @@ static irqreturn_t nv_adma_interrupt(int

if (status  (NV_ADMA_STAT_DONE |
  NV_ADMA_STAT_CPBERR)) {
+   u32 check_commands = notifier | notifier_error;
+   int pos, error = 0;
/** Check CPBs for completed commands */
-
-   if (ata_tag_valid(ap-active_tag)) {
-   /* Non-NCQ command */
-   nv_adma_check_cpb(ap, ap-active_tag,
-   notifier_error  (1  
ap-active_tag));
-   } else {
-   int pos, error = 0;
-   u32 active = ap-sactive;
-
-   while ((pos = ffs(active))  !error) {
-   pos--;
-   error = nv_adma_check_cpb(ap, 
pos,
-   notifier_error  (1  
pos) );
-   active = ~(1  pos );
-   }
+   while ((pos = ffs(check_commands))  !error) {
+   pos--;
+   error = nv_adma_check_cpb(ap, pos,
+   notifier_error  (1  pos) );
+   check_commands = ~(1  pos );
}
}
}

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH RFC] libata: FUA updates

2007-02-19 Thread Robert Hancock

This updates libata FUA support to be more more in line with reality.
FUA support remains off by default.

Add a setting for the fua command-line parameter on libata which enables
FUA only on NCQ-supporting disks.

Update the ata_dev_supports_fua function to remove the blacklisting of
Maxtor BANC1G10 firmware, as there is no conclusive evidence it was ever
needed.

Centralize all of the FUA on/off decisions in this function.

Bypass the checks for FUA command support bit for NCQ disks, since that
bit only applies to non-NCQ FUA, and FUA is part of the spec for NCQ
commands.

When queue depth is set by the user resulting in enabling/disabling
NCQ, trigger a revalidate so that the FUA state will be rechecked,
since disabling/enabling NCQ may also affect FUA support on some disks.

Add a controller flag to indicate it doesn't support FUA commands, and
set this flag for Silicon Image 311x (since that one is known to have
problems) as well as for ITE821x when in smart mode.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

---

Any comments on this version? It's essentially what I posted previously
in libata FUA revisited, except that the default for FUA support remains
off, so this shouldn't break anything for anyone that doesn't explicitly
enable it.

diff -urp linux-2.6.20-git6/drivers/ata/libata-core.c 
linux-2.6.20-git6edit/drivers/ata/libata-core.c
--- linux-2.6.20-git6/drivers/ata/libata-core.c 2007-02-11 17:31:19.0 
-0600
+++ linux-2.6.20-git6edit/drivers/ata/libata-core.c 2007-02-19 
16:55:49.0 -0600
@@ -87,7 +87,7 @@ MODULE_PARM_DESC(atapi_dmadir, Enable A

int libata_fua = 0;
module_param_named(fua, libata_fua, int, 0444);
-MODULE_PARM_DESC(fua, FUA support (0=off, 1=on));
+MODULE_PARM_DESC(fua, FUA support (0=off, 1=on for NCQ drives only, 2=on));

static int ata_probe_timeout = ATA_TMOUT_INTERNAL / HZ;
module_param(ata_probe_timeout, int, 0444);
diff -urp linux-2.6.20-git6/drivers/ata/libata-scsi.c 
linux-2.6.20-git6edit/drivers/ata/libata-scsi.c
--- linux-2.6.20-git6/drivers/ata/libata-scsi.c 2007-02-11 17:31:19.0 
-0600
+++ linux-2.6.20-git6edit/drivers/ata/libata-scsi.c 2007-02-19 
16:47:46.0 -0600
@@ -986,7 +986,7 @@ int ata_scsi_change_queue_depth(struct s
struct ata_port *ap = ata_shost_to_port(sdev-host);
struct ata_device *dev;
unsigned long flags;
-   int max_depth;
+   int max_depth, revalidate;

if (queue_depth  1)
return sdev-queue_depth;
@@ -1003,10 +1003,22 @@ int ata_scsi_change_queue_depth(struct s
scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);

spin_lock_irqsave(ap-lock, flags);
-   if (queue_depth  1)
+   if (queue_depth  1  (dev-flags  ATA_DFLAG_NCQ_OFF)) {
dev-flags = ~ATA_DFLAG_NCQ_OFF;
-   else
+   revalidate = 1;
+   } else if(!(dev-flags  ATA_DFLAG_NCQ_OFF)) {
dev-flags |= ATA_DFLAG_NCQ_OFF;
+   revalidate = 1;
+   }
+   /* Note: NCQ is switched off if queue depth is set to 1.
+  Thus changing the depth may also enable/disable FUA,
+  which the SCSI layer needs to know about, so we trigger
+  a revalidate. */
+   if(revalidate) {
+   ap-eh_info.action |= ATA_EH_REVALIDATE;
+   ata_port_schedule_eh(ap);
+   }
+
spin_unlock_irqrestore(ap-lock, flags);

return queue_depth;
@@ -1990,27 +2002,46 @@ static unsigned int ata_msense_rw_recove
}

/*
- * We can turn this into a real blacklist if it's needed, for now just
- * blacklist any Maxtor BANC1G10 revision firmware
+ * ata_dev_supports_fua - Determine if this device supports FUA.
+ * @dev: Device to check
+ *
+ * Determine if this device supports FUA based on drive and
+ * controller capabilities.
+ *
+ * LOCKING:
+ * None.
 */
-static int ata_dev_supports_fua(u16 *id)
+static int ata_dev_supports_fua(struct ata_device* dev)
{
-   unsigned char model[ATA_ID_PROD_LEN + 1], fw[ATA_ID_FW_REV_LEN + 1];
-
+   /* Is FUA completely disabled? */
if (!libata_fua)
return 0;
-   if (!ata_id_has_fua(id))
+   
+   /* Does the drive support FUA?
+  NCQ-enabled drives always support FUA, otherwise
+  check if the drive indicates support for FUA commands. */
+   if((dev-flags  (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF |
+ ATA_DFLAG_NCQ)) != ATA_DFLAG_NCQ) {
+   if(libata_fua == 1)
+   /* FUA enabled only for NCQ */
+   return 0;
+   
+   /* Does the drive support FUA commands? */
+   if (!(dev-flags  ATA_DFLAG_LBA48) ||
+   !ata_id_has_fua(dev-id))
+   return 0;
+   
+   /* Can't use FUA if we can only use PIO and can't use
+  WRITE MULTIPLE FUA EXT */
+   if((dev-flags  ATA_DFLAG_PIO)  !dev

Re: pata_amd dropping to PIO on resume

2007-02-16 Thread Robert Hancock

Tobias Diedrich wrote:

Possibly a known issue:

After resume pata_amd drops from UDMA/33 to PIO on my system.
Reloading the module puts both attached optical drives (master and
slave) back to UDMA/33.

AFAICS simplex DMA is claimed by other device, disabling DMA seems
to be causing it to drop to PIO (but only after a suspend/resume
cycle, not on boot or module load).

Burning a DVD with 6x speed using PIO makes heavy use of burnproof
and makes the whole system quite sluggish. :)


Yes, the fact that it's going into simplex mode is the problem, it 
wasn't in simplex to start with. It looks like pata_amd does an 
ata_pci_clear_simplex only for certain chip models, maybe this model 
needs it as well?


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: sata_nv ADMA controller lockup investigation

2007-02-15 Thread Robert Hancock

Jeff Garzik wrote:

Robert Hancock wrote:

It's curious that only the post-cache-flush command is having issues,
and normal NCQ operation seems fine. Maybe it's related to that tag 0
being reused repeatedly?



If you take cache flush out of the equation, what happens when NCQ is 
enabled with a queue depth of 1 (to reproduce tag-0-used-repeatedly 
condition)?


Jeff


I was able to reproduce it in my same test case with NCQ depth set to 1.
Of course, there were still some cache flushes going on there, so I'm not
certain that test really told us anything new. I'm rather doutbful that it's
related to reusing the same tag now, though, based on the tests I've been
doing. It may be something to do with switching between NCQ and non-NCQ
commands, maybe the controller isn't able to handle doing that too rapidly.
This patch seems to fix the problem - or at least it hasn't failed the tests 
that
I've run so far. It's not really ideal though, so I'd like to do some more
investigation/testing before proclaiming it as a fix. Experimentally, it
appears that 10 microseconds is not enough delay, but 20 seems to work better.

Hints from the peanut gallery remain welcome.

--- linux-2.6.20-git6edit/drivers/ata/sata_nv.c.before_hacking  2007-02-15 
18:19:13.0 -0600
+++ linux-2.6.20-git6edit/drivers/ata/sata_nv.c 2007-02-15 22:36:02.0 
-0600
@@ -219,6 +219,7 @@
void __iomem *  gen_block;
void __iomem *  notifier_clear_block;
u8  flags;
+   int last_issue_ncq;
};

struct nv_host_priv {
@@ -1260,6 +1261,7 @@
{
struct nv_adma_port_priv *pp = qc-ap-private_data;
void __iomem *mmio = pp-ctl_block;
+   int curr_ncq = (qc-tf.protocol == ATA_PROT_NCQ);

VPRINTK(ENTER\n);

@@ -1274,6 +1276,14 @@
/* write append register, command tag in lower 8 bits
   and (number of cpbs to append -1) in top 8 bits */
wmb();
+
+   if(curr_ncq != pp-last_issue_ncq) {
+   /* Seems to need some delay before switching between NCQ and 
non-NCQ
+  commands, else we get command timeouts and such. */
+   udelay(20);
+   pp-last_issue_ncq = curr_ncq;
+   }
+
writew(qc-tag, mmio + NV_ADMA_APPEND);

DPRINTK(Issued tag %u\n,qc-tag);
-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


sata_nv ADMA controller lockup investigation

2007-02-14 Thread Robert Hancock
 action 0x2 frozen
ata4.00: cmd 61/08:00:e0:a1:64/00:00:0a:00:00/40 tag 0 cdb 0x0 data 4096 out
res 40/00:01:00:4f:c2/00:00:00:00:00/00 Emask 0x4 (timeout)
ata4: soft resetting port
ata4: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
ata4.00: configured for UDMA/133
ata4: EH complete
SCSI device sdb: 312581808 512-byte hdwr sectors (160042 MB)
sdb: Write Protect is off
sdb: Mode Sense: 00 3a 00 00
SCSI device sdb: write cache: enabled, read cache: enabled, doesn't support DPO 
or FUA

The pattern of the hang always seems to be that it's an NCQ command that
immediately follows a cache flush. When that NCQ command is issued, the
IDLE bit clears as we would expect, but then it stays like that
with just the STOPPED bit set. No interrupt is raised and the CPB response
flags are not updated to indicate the command was released (i.e. received
by the drive) or completed. It's like the controller accepted the command
and then stalled before actually doing anything with it.

My guess it's either a bug in the controller that needs to be somehow
worked around, or we're somehow not operating the controller properly.
The latter is very difficult for me to determine since the only
documentation I have other than the original NVIDIA-provided driver for
this controller is the ADMA standard, which this controller only vaguely
follows (for example, not all of the status bits on this controller
are in the ADMA standard and some of the meanings for those that are
there seem to be different).

My only real clue at this point is maybe there's something wrong with
the way we are giving the commands to the controller, using the
APPEND register. That's another thing that's not in the ADMA standard.
It's curious that only the post-cache-flush command is having issues,
and normal NCQ operation seems fine. Maybe it's related to that tag 0
being reused repeatedly?

--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/



-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: libata FUA revisited

2007-02-13 Thread Robert Hancock

Tejun Heo wrote:
On the NCQ side, I think it's pretty safe to assume that all 
controllers will handle it. Obviously I've verified it with sata_nv 
(at least that it doesn't blow up obviously), and the other two NCQ 
drivers we have, ahci and sata_sil24 just feed raw FIS data into the 
controller so there should be no issue with not supporting it.


FWIW, ICH6/7/8 ahci's clear PMP field when transmitting FIS.  The reason 
why I'm hesitant is because there is no way to tell whether the FUA bit 
got honored or ignored.  With extra opcode, it's okay because barrier 
explicitly fails but if NCQ FUA is not supported, it will succeed 
silently as normal write.  Everything will be okay generally but the 
barrier is done incorrectly and on a really bad day it will lead to 
journal corruption.


Well, we should be able to determine that experimentally (at least on 
specific controllers) with a little test program that just writes little 
bits of data and fsyncs repeatedly (assuming that does in fact trigger 
FUAs currently..) If it runs faster than the drive could possibly be 
rewriting the physical disk then obviously the FUA bit is not getting 
through and/or not respected and we can blacklist FUA on that controller.


Also, the FUA bit in the NCQ commands is in the device register, so it's 
not like the PMP fields where it's not used for anything else and so the 
controller messing with it wouldn't be otherwise noticed..




So, actually, I was thinking about *always* using the non-NCQ FUA 
opcode.  As currently implemented, FUA request is always issued by 
itself, so NCQ doesn't make any difference there.  So, I think it would 
be better to turn on FUA on driver-by-driver basis whether the 
controller supports NCQ or not.


Unfortunately not all drives that support NCQ support the non-NCQ FUA 
commands (my Seagates are like this).


There's definitely a potential advantage to FUA with NCQ - if you have 
non-synchronous accesses going on concurrently with synchronous ones, if 
you have to use non-NCQ FUA or flush cache commands, you have to wait 
for all the IOs of both types to drain out before you can issue the 
flush (since those can't be overlapped with the NCQ read/writes). And if 
you can only use flush cache, then you're forcing all the writes to be 
flushed including the non-synchronous ones you didn't care about. 
Whether or not the block layer currently exploits this I don't know, but 
it definitely could.


Well, I might be being too paranoid but silent FUA failure would be 
really hard to diagnose if that ever happens (and I'm fairly certain 
that it will on some firmwares).


Well, there are also probably drives that ignore flush cache commands or 
 fail to do other things that they should. There's only so far we can 
go in coping if the firmware authors are being retarded. If any drive is 
broken like that we should likely just blacklist NCQ on it entirely as 
obviously little thought or testing went into the implementation..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/


-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: libata FUA revisited

2007-02-12 Thread Robert Hancock

Tejun Heo wrote:
-Add a new port flag ATA_FLAG_NO_FUA to indicate that a controller 
can't handle FUA commands, and add that flag to sata_sil. Force FUA 
off on any drive connected to a controller with this bit set.


There was some talk that sata_mv might have this problem, but I 
believe the conclusion was that it didn't. The only controllers that 
would are ones that actually try to interpret the ATA command codes 
and don't know about WRITE DMA FUA.


I think it would be better to add ATA_FLAG_FUA instead of ATA_FLAG_NO_FUA.


I'm not sure about that, it appears that the number of controllers that 
have problems is much lower than the number that don't, so this would 
just need to be added to almost every driver. Especially since the 
non-NCQ FUA which was problematic on SiI in the past isn't being 
switched on by default.


-Change the fua module option to control FUA enable/disable to have a 
third value, enable for NCQ-supporting drives only, which would 
become the new default. That case seems less likely to cause problems 
since FUA on NCQ is just another bit in the command whereas FUA on 
non-NCQ is an entirely different, potentially unsupported command.


Not enabling FUA doesn't result in huge performance hit.  I'm not sure 
whether we should go such far.  Just supporting FUA on known good 
controllers sounds good enough to me.


On the NCQ side, I think it's pretty safe to assume that all controllers 
will handle it. Obviously I've verified it with sata_nv (at least that 
it doesn't blow up obviously), and the other two NCQ drivers we have, 
ahci and sata_sil24 just feed raw FIS data into the controller so there 
should be no issue with not supporting it.


Assuming that we leave FUA off by default for non-NCQ for the 
foreseeable future, is there really much concern here?





Any comments?

As an aside, I came across a comment that the Silicon Image Windows 
drivers for NCQ-supporting controllers have some blacklist entries for 
drives with broken NCQ in their .inf files. We only seem to have one 
in the libata NCQ blacklist, we may want to add some more of these. 
The ones in the current SiI3124 and 3132 drivers' .inf files for 
DisableSataQueueing appear to be:


ModelFirmware
Maxtor 7B250S0BANC1B70
HTS541060G9SA00MB3OC60D
HTS541080G9SA00MB4OC60D
HTS541010G9SA00MBZOC60D

(the latter 3 being Hitachi Travelstar drives)


Yeah, I don't think we need to be too careful about blacklisting NCQ 
considering the sorry state of many early NCQ firmwares.  Please submit 
a patch.  It would be nice if you add a comment why the drives are added 
for documentation.


Will do shortly. Eric, do you have any info on the blacklisting of that 
Maxtor 7B250S0 drive? I would hope that Silicon Image would have a good 
reason for blacklisting that one..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] sata_nv: handle SError status indication

2007-02-11 Thread Robert Hancock

ADMA-capable controllers provide a bit in the status register that appears
to indicate that the controller detected an SError condition. Update sata_nv
to detect this and trigger error handling in order to handle the fault.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- drivers/ata/sata_nv.c.before_serror 2007-02-11 17:49:27.0 -0600
+++ drivers/ata/sata_nv.c   2007-02-11 17:54:39.0 -0600
@@ -827,7 +827,8 @@ static irqreturn_t nv_adma_interrupt(int
/* freeze if hotplugged or controller error */
if (unlikely(status  (NV_ADMA_STAT_HOTPLUG |
   NV_ADMA_STAT_HOTUNPLUG |
-  NV_ADMA_STAT_TIMEOUT))) {
+  NV_ADMA_STAT_TIMEOUT |
+  NV_ADMA_STAT_SERROR))) {
struct ata_eh_info *ehi = ap-eh_info;

ata_ehi_clear_desc(ehi);
@@ -841,6 +842,9 @@ static irqreturn_t nv_adma_interrupt(int
} else if (status  NV_ADMA_STAT_HOTUNPLUG) {
ata_ehi_hotplugged(ehi);
ata_ehi_push_desc(ehi, : hot unplug);
+   } else if (status  NV_ADMA_STAT_SERROR) {
+   /* let libata analyze SError and figure 
out the cause */
+   ata_ehi_push_desc(ehi, : SError);
}
ata_port_freeze(ap);
continue;

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] sata_nv: add back some verbosity into ADMA error_handler

2007-02-11 Thread Robert Hancock

Some debug output in the ADMA error_handler function was removed recently,
but it may be useful in certain cases, like NCQ commands timing out. Add it
back in, but make it a bit more intelligent so that it only prints if
command(s) are active and only prints the CPBs for those commands.
That way it won't spew at inappropriate times like suspend/resume.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-git6/drivers/ata/sata_nv.c 2007-02-11 17:31:19.0 
-0600
+++ linux-2.6.20-git6edit/drivers/ata/sata_nv.c 2007-02-11 17:40:48.0 
-0600
@@ -1442,6 +1442,26 @@ static void nv_adma_error_handler(struct
void __iomem *mmio = pp-ctl_block;
int i;
u16 tmp;
+   
+   if(ata_tag_valid(ap-active_tag) || ap-sactive) {
+   u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
+   u32 notifier_error = readl(mmio + 
NV_ADMA_NOTIFIER_ERROR);
+   u32 gen_ctl = readl(pp-gen_block + NV_ADMA_GEN_CTL);
+   u32 status = readw(mmio + NV_ADMA_STAT);
+
+   ata_port_printk(ap, KERN_ERR, EH in ADMA mode, notifier 
0x%X 
+   notifier_error 0x%X gen_ctl 0x%X status 
0x%X\n,
+   notifier, notifier_error, gen_ctl, status);
+
+   for( i=0;iNV_ADMA_MAX_CPBS;i++) {
+   struct nv_adma_cpb *cpb = pp-cpb[i];
+   if( (ata_tag_valid(ap-active_tag)  i == 
ap-active_tag) ||
+   ap-sactive  (1  i) )
+   ata_port_printk(ap, KERN_ERR,
+   CPB %d: ctl_flags 0x%x, resp_flags 
0x%x\n,
+   i, cpb-ctl_flags, 
cpb-resp_flags);
+   }
+   }

/* Push us back into port register mode for error handling. */
nv_adma_register_mode(ap);

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


libata FUA revisited

2007-02-11 Thread Robert Hancock
I've been looking at some list archives from about a year ago when there 
was a big hoohah about FUA in libata. To summarize what I've gotten from 
that discussion:


Nicolas Mailhot ran into a problem with the first kernels that supported 
libata FUA, using a Silicon Image 3114 controller and a Maxtor 6L300S0 
   drive with BANC1G10 firmware. Essentially it would quickly corrupt 
the filesystem on bootup. After that:


-A blacklist entry was added into libata disabling FUA on Maxtor drives 
with BANC1G10 firmware


-Eric Mudama from Maxtor complained that there was nothing wrong with 
FUA on those drives and the blacklist should be taken out (though it 
never was)


-It was also confirmed by Eric and others that Silicon Image 311x 
controllers go nuts if they're issued WRITE DMA FUA commands, at least 
without some driver improvements which I assume haven't happened.


-Eventually FUA was disabled by default globally in libata.

Given the above, what I'm proposing to do is:

-Remove the blacklisting of Maxtor BANC1G10 firmware for FUA. If we need 
to FUA-blacklist any drives this should likely be added to the existing 
horkage mechanism we now have. However, at this point I don't think 
that's needed, considering that I've seen no conclusive evidence that 
any drive has ever been established to have broken FUA.


-Add a new port flag ATA_FLAG_NO_FUA to indicate that a controller can't 
handle FUA commands, and add that flag to sata_sil. Force FUA off on any 
drive connected to a controller with this bit set.


There was some talk that sata_mv might have this problem, but I believe 
the conclusion was that it didn't. The only controllers that would are 
ones that actually try to interpret the ATA command codes and don't know 
about WRITE DMA FUA.


-Change the fua module option to control FUA enable/disable to have a 
third value, enable for NCQ-supporting drives only, which would become 
the new default. That case seems less likely to cause problems since FUA 
on NCQ is just another bit in the command whereas FUA on non-NCQ is an 
entirely different, potentially unsupported command.


Any comments?

As an aside, I came across a comment that the Silicon Image Windows 
drivers for NCQ-supporting controllers have some blacklist entries for 
drives with broken NCQ in their .inf files. We only seem to have one in 
the libata NCQ blacklist, we may want to add some more of these. The 
ones in the current SiI3124 and 3132 drivers' .inf files for 
DisableSataQueueing appear to be:


Model   Firmware
Maxtor 7B250S0  BANC1B70
HTS541060G9SA00 MB3OC60D
HTS541080G9SA00 MB4OC60D
HTS541010G9SA00 MBZOC60D

(the latter 3 being Hitachi Travelstar drives)

--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/
-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH -mm] sata_nv: wait for response on entering/leaving ADMA mode

2007-02-04 Thread Robert Hancock

Update sata_nv to wait for the controller to indicate via the status register
that it has entered the requested state when switching between ADMA mode and
register mode. This issue came up recently when debugging some problems with
cache flush command timeouts and while it didn't appear to fix that problem,
this is something we should likely be doing in any case.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-rc6-mm3/drivers/ata/sata_nv.c  2007-02-04 21:48:25.0 
-0600
+++ linux-2.6.20-rc6-mm3edit/drivers/ata/sata_nv.c  2007-02-04 
22:13:36.0 -0600
@@ -507,14 +507,38 @@ static void nv_adma_register_mode(struct
{
struct nv_adma_port_priv *pp = ap-private_data;
void __iomem *mmio = pp-ctl_block;
-   u16 tmp;
+   u16 tmp, status;
+   int count = 0;

if (pp-flags  NV_ADMA_PORT_REGISTER_MODE)
return;

+   status = readw(mmio + NV_ADMA_STAT);
+   while(!(status  NV_ADMA_STAT_IDLE)  count  20) {
+   ndelay(50);
+   status = readw(mmio + NV_ADMA_STAT);
+   count++;
+   }
+   if(count == 20)
+   ata_port_printk(ap, KERN_WARNING,
+   timeout waiting for ADMA IDLE, stat=0x%hx\n,
+   status);
+
tmp = readw(mmio + NV_ADMA_CTL);
writew(tmp  ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);

+   count = 0;
+   status = readw(mmio + NV_ADMA_STAT);
+   while(!(status  NV_ADMA_STAT_LEGACY)  count  20) {
+   ndelay(50);
+   status = readw(mmio + NV_ADMA_STAT);
+   count++;
+   }
+   if(count == 20)
+   ata_port_printk(ap, KERN_WARNING,
+timeout waiting for ADMA LEGACY, stat=0x%hx\n,
+status);
+
pp-flags |= NV_ADMA_PORT_REGISTER_MODE;
}

@@ -522,7 +546,8 @@ static void nv_adma_mode(struct ata_port
{
struct nv_adma_port_priv *pp = ap-private_data;
void __iomem *mmio = pp-ctl_block;
-   u16 tmp;
+   u16 tmp, status;
+   int count = 0;

if (!(pp-flags  NV_ADMA_PORT_REGISTER_MODE))
return;
@@ -532,6 +557,18 @@ static void nv_adma_mode(struct ata_port
tmp = readw(mmio + NV_ADMA_CTL);
writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);

+   status = readw(mmio + NV_ADMA_STAT);
+   while(((status  NV_ADMA_STAT_LEGACY) ||
+ !(status  NV_ADMA_STAT_IDLE))  count  20) {
+   ndelay(50);
+   status = readw(mmio + NV_ADMA_STAT);
+   count++;
+   }
+   if(count == 20)
+   ata_port_printk(ap, KERN_WARNING,
+   timeout waiting for ADMA LEGACY clear and IDLE, 
stat=0x%hx\n,
+   status);
+
pp-flags = ~NV_ADMA_PORT_REGISTER_MODE;
}



-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH -mm] sata_nv: propagate ata_pci_device_do_resume return value

2007-02-04 Thread Robert Hancock

ata_pci_device_do_resume can fail if the PCI device couldn't be re-enabled.
Update sata_nv to propagate the return value from this call and to
not try to do any other resume activities if it fails. Fixes a compile
warning.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-rc6-mm3edit/drivers/ata/sata_nv.c.beforeresumechange   
2007-02-04 22:18:49.0 -0600
+++ linux-2.6.20-rc6-mm3edit/drivers/ata/sata_nv.c  2007-02-04 
22:20:06.0 -0600
@@ -1604,8 +1604,11 @@ static int nv_pci_device_resume(struct p
{
struct ata_host *host = dev_get_drvdata(pdev-dev);
struct nv_host_priv *hpriv = host-private_data;
+   int rc;

-   ata_pci_device_do_resume(pdev);
+   rc = ata_pci_device_do_resume(pdev);
+   if(rc)
+   return rc;

if (pdev-dev.power.power_state.event == PM_EVENT_SUSPEND) {
if(hpriv-type = CK804) {

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH RFC] sd: spin down disks on removal or power-down

2007-01-31 Thread Robert Hancock

Stefan Richter wrote:

Robert Hancock wrote:

http://marc.theaimsgroup.com/?t=11692262122

It looks like Tejun's patch essentially does the same thing as mine with
the addition of the control from userspace. There is one exception
though, my patch also does the stop on removal of the SCSI disk (i.e.
writing 1 to its delete file in sysfs, what scsiadd -r does).


Isn't sd_shutdown called at this occasion?


Ah, indeed it is. I was thinking of the way I had written my patch, 
where it only does the spindown if the system state is SYSTEM_POWER_OFF 
so I needed an extra call to force this on removal. Tejun's patch just 
checks for not SYSTEM_RESTART, so it should happen on removal as well.


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] libata: fix translation for START STOP UNIT

2007-01-30 Thread Robert Hancock

Jeff Garzik wrote:
* Include the patch inline rather than as an attachment.  Even a 
text/plain attachment is very difficult to review and quote in popular 
email programs.


Jeff


I'd love to, but unfortunately nobody seems to have come up with a way 
of doing this in Thunderbird that keeps it from mangling whitespace 
without a ton of hassle. I was able to get it to cooperate once (sort 
of, anyway, I think it may have still damaged something on the first 
try), but it required mangling a bunch of settings that made using it 
for normal mail impossible.


The last time I looked, the main how-to page I found had an addendum 
that I gave up on this, it's too hard, I just attach the patches. If 
anyone has gotten any new insight..


--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/


-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH -mm] sata_nv: use ADMA for NODATA commands

2007-01-28 Thread Robert Hancock
Patch is against 2.6.20-rc6-mm1, though will also apply to 2.6.20-rc6 if 
sata_nv-cleanup-adma-error-handling-v2.patch and 
sata_nv-cleanup-adma-error-handling-v2-cleanup.patch from -mm are 
applied first. Testing from those who experienced the previous cache 
flush timeout problem, in particular, would be appreciated.


---

Some problems showed up recently with cache flush commands timing out on 
sata_nv. Previously these commands were always handled by transitioning 
to legacy mode from ADMA mode first. The timeout problem was worked 
around already by a change to the interrupt handling code for legacy 
mode, but for non-data commands like these it appears we can handle them 
in ADMA mode, so the switch to legacy mode is not needed.


This patch changes the behavior so that we use ADMA mode to submit 
interrupt-driven commands with ATA_PROT_NODATA protocol. In addition to 
avoiding the problem mentioned above entirely, this avoids the overhead 
of switching to legacy mode and back to ADMA mode for handling cache 
flushes. When handling non-DMA-mapped commands, we leave the APRD blank 
and clear the NV_CPB_CTL_APRD_VALID field in the CPB so the controller 
does not attempt to read it.


Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/

--- linux-2.6.20-rc6nv/drivers/ata/sata_nv.c2007-01-28 17:05:27.0 
-0600
+++ linux-2.6.20-rc6nvedit/drivers/ata/sata_nv.c2007-01-28 
17:20:11.0 -0600
@@ -1172,16 +1172,31 @@ static void nv_adma_fill_sg(struct ata_q
cpb-next_aprd = cpu_to_le64(((u64)(pp-aprd_dma + 
NV_ADMA_SGTBL_SZ * qc-tag)));
 }
 
+static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
+{
+   struct nv_adma_port_priv *pp = qc-ap-private_data;
+   
+   /* ADMA engine can only be used for non-ATAPI DMA commands,
+  or interrupt-driven no-data commands. */
+   if((pp-flags  NV_ADMA_ATAPI_SETUP_COMPLETE) ||
+  (qc-tf.flags  ATA_TFLAG_POLLING))
+   return 1;
+
+   if((qc-flags  ATA_QCFLAG_DMAMAP) ||
+  (qc-tf.protocol == ATA_PROT_NODATA))
+   return 0;
+   
+   return 1;
+}
+
 static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
 {
struct nv_adma_port_priv *pp = qc-ap-private_data;
struct nv_adma_cpb *cpb = pp-cpb[qc-tag];
u8 ctl_flags = NV_CPB_CTL_CPB_VALID |
-  NV_CPB_CTL_APRD_VALID |
   NV_CPB_CTL_IEN;
 
-   if (!(qc-flags  ATA_QCFLAG_DMAMAP) ||
-(pp-flags  NV_ADMA_ATAPI_SETUP_COMPLETE)) {
+   if (nv_adma_use_reg_mode(qc)) {
nv_adma_register_mode(qc-ap);
ata_qc_prep(qc);
return;
@@ -1200,8 +1215,12 @@ static void nv_adma_qc_prep(struct ata_q
VPRINTK(qc-flags = 0x%lx\n, qc-flags);
 
nv_adma_tf_to_cpb(qc-tf, cpb-tf);
-
-   nv_adma_fill_sg(qc, cpb);
+   
+   if(qc-flags  ATA_QCFLAG_DMAMAP) {
+   nv_adma_fill_sg(qc, cpb);
+   ctl_flags |= NV_CPB_CTL_APRD_VALID;
+   } else
+   memset(cpb-aprd[0], 0, sizeof(struct nv_adma_prd) * 5);
 
/* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until 
we are
   finished filling in all of the contents */
@@ -1216,10 +1235,9 @@ static unsigned int nv_adma_qc_issue(str
 
VPRINTK(ENTER\n);
 
-   if (!(qc-flags  ATA_QCFLAG_DMAMAP) ||
-(pp-flags  NV_ADMA_ATAPI_SETUP_COMPLETE)) {
+   if (nv_adma_use_reg_mode(qc)) {
/* use ATA register mode */
-   VPRINTK(no dmamap or ATAPI, using ATA register mode: 0x%lx\n, 
qc-flags);
+   VPRINTK(using ATA register mode: 0x%lx\n, qc-flags);
nv_adma_register_mode(qc-ap);
return ata_qc_issue_prot(qc);
} else


[PATCH] libata: fix translation for START STOP UNIT

2007-01-28 Thread Robert Hancock

Applies to 2.6.20-rc6.

---

libata's SCSI translation for the SCSI START STOP UNIT command with the 
START bit clear (i.e. stopping the drive) appears to be incorrect. It 
sends an ATA STANDBY command with the time period set to 0, which the 
code comment says means now, but the ATA standard says this means 
disable the standby timer, which effectively does nothing. Change this 
to issue a STANDBY IMMEDIATE command which will actually spin the drive 
down. The SAT (SCSI/ATA Translation) standard revision 9 concurs with 
this choice.


Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/


--- linux-2.6.20-rc6nv/drivers/ata/libata-scsi.c2007-01-28 
16:59:58.0 -0600
+++ linux-2.6.20-rc6nvedit/drivers/ata/libata-scsi.c2007-01-28 
17:30:12.0 -0600
@@ -983,11 +983,10 @@ static unsigned int ata_scsi_start_stop_
}
 
tf-command = ATA_CMD_VERIFY;   /* READ VERIFY */
-   } else {
-   tf-nsect = 0;  /* time period value (0 implies now) */
-   tf-command = ATA_CMD_STANDBY;
-   /* Consider: ATA STANDBY IMMEDIATE command */
-   }
+   } else
+   /* Issue ATA STANDBY IMMEDIATE command */
+   tf-command = ATA_CMD_STANDBYNOW1;
+
/*
 * Standby and Idle condition timers could be implemented but that
 * would require libata to implement the Power condition mode page


[PATCH RFC] sd: spin down disks on removal or power-down

2007-01-28 Thread Robert Hancock

Here's a patch for sd.c I've cooked up which issues a START STOP UNIT
command to stop the drive when the SCSI disk is removed or the machine
is powered down. The rationale behind this is that apparently on many
drives, simply cutting power to the spinning disk forces it to do an
emergency head park/unload which creates more wear on the drive then a
controlled park/unload with power still applied. This change ensures
that the drive will be spun down if the user shuts down the machine or
if they are about to hot-unplug the drive and have done scsiadd -r first.

The main potential concern I have about this implementation is that if
the drive is used in a multi-initiator, iSCSI, etc. environment,
stopping the drive may be undesirable as another initiator may still be
accessing it. I'm not familiar enough with these setups to know if this
problem is likely to come up or not. For this and other reasons we may
want to make this behavior controllable - I'm open to suggestions on how
to do this or whether it's needed.

I've tested that this does work on SATA disks through libata (with my
patch libata: fix translation for START STOP UNIT applied). I also
tested with some external USB-to-IDE drive enclosures. The support for
START STOP UNIT on those seems rather poor though, on one enclosure with
a Genesys bridge chip it returned a check condition with Invalid field
in CDB, and on another with a JMicron chip the request succeeded but it
didn't actually spin the drive down.

--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/




--- linux-2.6.20-rc6nv/drivers/scsi/sd.c2007-01-28 17:00:00.0 
-0600
+++ linux-2.6.20-rc6nvedit/drivers/scsi/sd.c2007-01-28 18:08:53.0 
-0600
@@ -821,6 +821,39 @@ static int sd_sync_cache(struct scsi_dev
return res;
 }
 
+static int sd_stop_unit(struct scsi_device *sdp, struct scsi_disk* sdkp)
+{
+   int res;
+   struct scsi_sense_hdr sshdr;
+   unsigned char cmd[10] = { 0 };
+
+   if (!scsi_device_online(sdp))
+   return -ENODEV;
+
+   cmd[0] = START_STOP;
+   /*
+* Leave the rest of the command zero to indicate
+* transition to stopped power condition and return
+* on completion.
+*/
+   printk(KERN_NOTICE Stopping SCSI disk %s\n,
+   sdkp-disk-disk_name);
+   res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, sshdr,
+  SD_TIMEOUT, SD_MAX_RETRIES);
+
+   if (res) {
+   printk(KERN_WARNING sd stop failed: status = %x, message = 
%02x, 
+   host = %d, driver = %02x\n,
+   status_byte(res), msg_byte(res),
+   host_byte(res), driver_byte(res));
+   if (driver_byte(res)  DRIVER_SENSE)
+   scsi_print_sense_hdr(sd, sshdr);
+   }
+   
+   return res;
+}
+
+
 static int sd_issue_flush(struct device *dev, sector_t *error_sector)
 {
int ret = 0;
@@ -1727,11 +1760,13 @@ static int sd_probe(struct device *dev)
  **/
 static int sd_remove(struct device *dev)
 {
+   struct scsi_device *sdp = to_scsi_device(dev);
struct scsi_disk *sdkp = dev_get_drvdata(dev);
 
class_device_del(sdkp-cdev);
del_gendisk(sdkp-disk);
sd_shutdown(dev);
+   sd_stop_unit(sdp,sdkp);
 
mutex_lock(sd_ref_mutex);
dev_set_drvdata(dev, NULL);
@@ -1784,6 +1819,9 @@ static void sd_shutdown(struct device *d
sdkp-disk-disk_name);
sd_sync_cache(sdp);
}
+   if(system_state == SYSTEM_POWER_OFF)
+   sd_stop_unit(sdp,sdkp);
+   
scsi_disk_put(sdkp);
 }
 




[PATCH -mm] sata_nv: cleanup ADMA error handling v2

2007-01-17 Thread Robert Hancock

Should apply to -mm tree or current libata-dev git tree. This version
leaves out part of a change in the first version which in retrospect
should have been left alone.

---

This cleans up a few issues with the error handling in sata_nv in ADMA
mode to make it more consistent with other NCQ-capable drivers like ahci
and sata_sil24:

-When a command failed, we would effectively set AC_ERR_DEV on the
queued command always. In the case of NCQ commands this prevents libata
from doing a log page query to determine the details of the failed
command, since it thinks we've already analyzed. Just set flags in the
port ehi-err_mask, then freeze or abort and let libata figure out what
went wrong.

-The code handled NV_ADMA_STAT_CPBERR as a really bad error which
caused it to set error flags on every queued command. I don't know
exactly what this flag means (no docs, grr!) but from what I can guess
from the standard ADMA spec, it just means that one or more of the CPBs
had an error, so we just need to go through and do our normal checks in
this case.

-In the error_handler function the code would always dump the state of
all the CPBs. This output seems redundant at this point since libata
already dumps the state of all active commands on errors (and it also
triggers at times when it shouldn't, like when suspending). Take this
out.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.20-rc5/drivers/ata/sata_nv.c  2007-01-12 23:18:08.0 
-0600
+++ linux-2.6.20-rc5edit/drivers/ata/sata_nv.c  2007-01-17 17:22:05.0 
-0600
@@ -646,53 +646,64 @@ static unsigned int nv_adma_tf_to_cpb(st
return idx;
 }
 
-static void nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
+static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
 {
struct nv_adma_port_priv *pp = ap-private_data;
-   int complete = 0, have_err = 0;
u8 flags = pp-cpb[cpb_num].resp_flags;
 
VPRINTK(CPB %d, flags=0x%x\n, cpb_num, flags);
 
-   if (flags  NV_CPB_RESP_DONE) {
-   VPRINTK(CPB flags done, flags=0x%x\n, flags);
-   complete = 1;
-   }
-   if (flags  NV_CPB_RESP_ATA_ERR) {
-   ata_port_printk(ap, KERN_ERR, CPB flags ATA err, 
flags=0x%x\n, flags);
-   have_err = 1;
-   complete = 1;
-   }
-   if (flags  NV_CPB_RESP_CMD_ERR) {
-   ata_port_printk(ap, KERN_ERR, CPB flags CMD err, 
flags=0x%x\n, flags);
-   have_err = 1;
-   complete = 1;
-   }
-   if (flags  NV_CPB_RESP_CPB_ERR) {
-   ata_port_printk(ap, KERN_ERR, CPB flags CPB err, 
flags=0x%x\n, flags);
-   have_err = 1;
-   complete = 1;
+   if(unlikely((force_err ||
+flags  (NV_CPB_RESP_ATA_ERR |
+ NV_CPB_RESP_CMD_ERR |
+ NV_CPB_RESP_CPB_ERR {
+   struct ata_eh_info *ehi = ap-eh_info;
+   int freeze = 0;
+   ata_ehi_clear_desc(ehi);
+   ata_ehi_push_desc(ehi, CPB resp_flags 0x%x, flags );
+   if(flags  NV_CPB_RESP_ATA_ERR) {
+   ata_ehi_push_desc(ehi, : ATA error);
+   ehi-err_mask |= AC_ERR_DEV;
+   }
+   else if(flags  NV_CPB_RESP_CMD_ERR) {
+   ata_ehi_push_desc(ehi, : CMD error);
+   ehi-err_mask |= AC_ERR_DEV;
+   }
+   else if(flags  NV_CPB_RESP_CPB_ERR) {
+   ata_ehi_push_desc(ehi, : CPB error);
+   ehi-err_mask |= AC_ERR_SYSTEM;
+   freeze = 1;
+   }
+   else {
+   /* notifier error, but no error in CPB flags? */
+   ehi-err_mask |= AC_ERR_OTHER;
+   freeze = 1;
+   }
+   /* Kill all commands. EH will determine what actually failed. */
+   if(freeze)
+   ata_port_freeze(ap);
+   else
+   ata_port_abort(ap);
+   return 1;
}
-   if(complete || force_err)
-   {
+   
+   if (flags  NV_CPB_RESP_DONE) {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
+   VPRINTK(CPB flags done, flags=0x%x\n, flags);
if(likely(qc)) {
-   u8 ata_status = 0;
-   /* Only use the ATA port status for non-NCQ commands.
+   /* Grab the ATA port status for non-NCQ commands.
   For NCQ commands the current status may have nothing 
to do with
   the command just completed. */
-   if(qc-tf.protocol != ATA_PROT_NCQ)
-   ata_status = readb(pp-ctl_block + 
(ATA_REG_STATUS * 4));
-
-   if(have_err || force_err

Re: [PATCH -mm] sata_nv: cleanup ADMA error handling

2007-01-15 Thread Robert Hancock

Robert Hancock wrote:
-In the error_handler function the code would always go through and do 
an ADMA channel reset and also dump out the state of all the CPBs. This 
reset seems heinous in this situation since we haven't even decided to 
reset anything yet. The output seems redundant at this point since 
libata already dumps the state of all active commands on errors (and it 
also triggers at times when it shouldn't, like when suspending). Do the 
ADMA reset only on hardreset and remove the output.


Actually, upon further thought some of this stuff really should be done 
in the error_handler method, just maybe not the channel reset. I'll cut 
another patch shortly.

-
To unsubscribe from this list: send the line unsubscribe linux-ide in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] SCSI: Add the SGPIO support for sata_nv.c

2007-01-09 Thread Robert Hancock

Since I've been the one making the most changes in sata_nv lately I
figured I would make some more comments on this patch:


Subject:
RE: [PATCH] SCSI: Add the SGPIO support for sata_nv.c
From:
Peer Chen [EMAIL PROTECTED]
Date:
Tue, 7 Nov 2006 17:55:11 +0800
To:
Christoph Hellwig [EMAIL PROTECTED]

To:
Christoph Hellwig [EMAIL PROTECTED]
CC:
[EMAIL PROTECTED], linux-kernel@vger.kernel.org, 
linux-ide@vger.kernel.org, Kuan Luo [EMAIL PROTECTED]



Modified and resent out the patch as attachment.
Description about the patch:
Add SGPIO support in sata_nv.c.
SGPIO (Serial General Purpose Input Output) is a sideband serial 4-wire
interface that a storage controller uses to communicate with a storage
enclosure management controller, primarily to control activity and
status LEDs that are located within drive bays or on a storage
backplane. SGPIO is defined by [SFF8485].
In this patch,we drive the LEDs to blink when read/write operation
happen on SATA drives connect the corresponding ports on MCP55 board.
==
The patch will be applied to kernel 2.6.19-rc4-git9.

Singed-off-by: Kuan Luo [EMAIL PROTECTED]
Singed-off-by: Peer Chen [EMAIL PROTECTED]


BRs
Peer Chen

  
---
  



--- linux-2.6.19-rc4-git9/drivers/ata/sata_nv.c.orig2006-11-06 
08:47:49.0 +0800
+++ linux-2.6.19-rc4-git9/drivers/ata/sata_nv.c 2006-11-07 08:36:54.0 
+0800


First off, can you rebase against the current libata-dev version of 
sata_nv? There have been

a ton of changes since 2.6.19-rc4-git9.

Also, it would be best to make sure the code passes the checks from the 
Sparse tool

using make C=1. sata_nv now passes this, it would be a shame to break that.


@@ -80,6 +80,176 @@
NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04,
 };
+/* sgpio
+* Sgpio defines
+* SGPIO state defines
+*/
+#define NV_SGPIO_STATE_RESET   0
+#define NV_SGPIO_STATE_OPERATIONAL 1
+#define NV_SGPIO_STATE_ERROR   2
+
+/* SGPIO command opcodes */
+#define NV_SGPIO_CMD_RESET 0
+#define NV_SGPIO_CMD_READ_PARAMS   1
+#define NV_SGPIO_CMD_READ_DATA 2
+#define NV_SGPIO_CMD_WRITE_DATA3
+
+/* SGPIO command status defines */
+#define NV_SGPIO_CMD_OK0
+#define NV_SGPIO_CMD_ACTIVE1
+#define NV_SGPIO_CMD_ERR   2
+
+#define NV_SGPIO_UPDATE_TICK   90
+#define NV_SGPIO_MIN_UPDATE_DELTA  33
+#define NV_CNTRLR_SHARE_INIT   2
+#define NV_SGPIO_MAX_ACTIVITY_ON   20
+#define NV_SGPIO_MIN_FORCE_OFF 5
+#define NV_SGPIO_PCI_CSR_OFFSET0x58
+#define NV_SGPIO_PCI_CB_OFFSET 0x5C
+#define NV_SGPIO_DFLT_CB_SIZE  256
+#define NV_ON 1
+#define NV_OFF 0
+
+
+
+static inline u8 bf_extract(u8 value, u8 offset, u8 bit_count)
+{
+   return u8)(value))  (offset))  ((1  (bit_count)) - 1));
+}
+
+static inline u8 bf_ins(u8 value, u8 ins, u8 offset, u8 bit_count)
+{
+   return  (((value)  ~1  (bit_count)) - 1))  (offset))) |
+   (((u8)(ins))  (offset)));
+}
+
+static inline u32 bf_extract_u32(u32 value, u8 offset, u8 bit_count)
+{
+   return u32)(value))  (offset))  ((1  (bit_count)) - 1));
+
+}
+static inline u32 bf_ins_u32(u32 value, u32 ins, u8 offset, u8 bit_count)
+{
+   return  (((value)  ~1  (bit_count)) - 1))  (offset))) |
+   (((u32)(ins))  (offset)));
+}


Maybe some comment about what these functions do? It's not entirely obvious.


+
+#define GET_SGPIO_STATUS(v)bf_extract(v, 0, 2)
+#define GET_CMD_STATUS(v)  bf_extract(v, 3, 2)
+#define GET_CMD(v) bf_extract(v, 5, 3)
+#define SET_CMD(v, cmd)		bf_ins(v, cmd, 5, 3) 
+

+#define GET_ENABLE(v)  bf_extract(v, 23, 1)
+#define SET_ENABLE(v)  bf_ins_u32(v, 1, 23, 1)
+
+/* Needs to have a u8 bit-field insert. */
+#define GET_ACTIVITY(v)bf_extract(v, 5, 3)
+#define SET_ACTIVITY(v, on_off)bf_ins(v, on_off, 5, 3)
+
+
+
+union nv_sgpio_nvcr 
+{

+   struct {
+   u8  init_cnt;
+   u8  cb_size;
+   u8  cbver;
+   u8  rsvd;
+   } bit;
+   u32 all;
+};
+
+union nv_sgpio_tx 
+{

+   u8  tx_port[4];
+   u32 all;
+};
+
+struct nv_sgpio_cb 
+{

+   u64 scratch_space;
+   union nv_sgpio_nvcr nvcr;
+   u32 cr0;
+   u32 rsvd[4];
+   union nv_sgpio_tx   tx[2];
+};
+
+struct nv_sgpio_host_share
+{
+   spinlock_t  *plock;
+   unsigned long   *ptstamp;
+};
+
+struct nv_sgpio_host_flags
+{
+   u8  sgpio_enabled:1;
+   u8  need_update:1;
+   u8  rsvd:6;
+};
+   
+struct nv_host_sgpio
+{
+   struct nv_sgpio_host_flags  flags;
+   u8  *pcsr;
+   struct 

[PATCH] sata_nv: add suspend/resume support v3

2006-12-12 Thread Robert Hancock
This patch is against 2.6.19-rc6-mm2 and should apply to what is in 
Linus' and Jeff's git trees currently. This includes a later fix to the 
kfree ordering in the nv_remove_one function. Both the original patch 
and the later fix are already in the -mm tree.


---

This patch adds the necessary callbacks to support suspend/resume 
properly in sata_nv. Most of the controllers don't need any specific 
handling but CK804/MCP04 controllers, whether ADMA is enabled or not, 
need some additional setup on resume.


As well as the additional storage of the controller type needed for 
proper resume handling, this also removes the inline helper functions 
for getting ADMA register locations by storing the pointers so we don't 
have to keep calculating them all the time.


This also includes a fix to a bug in the original version of this patch
where the hpriv structure was freed while it could potentially still be
used.

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--- linux-2.6.19-rc6-mm2/drivers/ata/sata_nv.c  2006-12-12 17:49:02.0 
-0600
+++ linux-2.6.19-rc6-mm2admafix/drivers/ata/sata_nv.c   2006-12-11 
22:15:58.0 -0600
@@ -49,7 +49,7 @@
#include linux/libata.h

#define DRV_NAMEsata_nv
-#define DRV_VERSION3.2
+#define DRV_VERSION3.3

#define NV_ADMA_DMA_BOUNDARY0xUL

@@ -213,12 +213,21 @@ struct nv_adma_port_priv {
dma_addr_t  cpb_dma;
struct nv_adma_prd  *aprd;
dma_addr_t  aprd_dma;
+   void __iomem *  ctl_block;
+   void __iomem *  gen_block;
+   void __iomem *  notifier_clear_block;
u8  flags;
};

+struct nv_host_priv {
+   unsigned long   type;
+};
+
#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL)  ( 1  (19 + (12 * (PORT)

static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static void nv_remove_one (struct pci_dev *pdev);
+static int nv_pci_device_resume(struct pci_dev *pdev);
static void nv_ck804_host_stop(struct ata_host *host);
static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
@@ -239,6 +248,8 @@ static irqreturn_t nv_adma_interrupt(int
static void nv_adma_irq_clear(struct ata_port *ap);
static int nv_adma_port_start(struct ata_port *ap);
static void nv_adma_port_stop(struct ata_port *ap);
+static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg);
+static int nv_adma_port_resume(struct ata_port *ap);
static void nv_adma_error_handler(struct ata_port *ap);
static void nv_adma_host_stop(struct ata_host *host);
static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc);
@@ -292,7 +303,9 @@ static struct pci_driver nv_pci_driver =
.name   = DRV_NAME,
.id_table   = nv_pci_tbl,
.probe  = nv_init_one,
-   .remove = ata_pci_remove_one,
+   .suspend= ata_pci_device_suspend,
+   .resume = nv_pci_device_resume,
+   .remove = nv_remove_one,
};

static struct scsi_host_template nv_sht = {
@@ -311,6 +324,8 @@ static struct scsi_host_template nv_sht 
	.slave_configure	= ata_scsi_slave_config,

.slave_destroy  = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
+   .suspend= ata_scsi_device_suspend,
+   .resume = ata_scsi_device_resume,
};

static struct scsi_host_template nv_adma_sht = {
@@ -330,6 +345,8 @@ static struct scsi_host_template nv_adma
.slave_configure= nv_adma_slave_config,
.slave_destroy  = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
+   .suspend= ata_scsi_device_suspend,
+   .resume = ata_scsi_device_resume,
};

static const struct ata_port_operations nv_generic_ops = {
@@ -438,6 +455,8 @@ static const struct ata_port_operations 
	.scr_write		= nv_scr_write,

.port_start = nv_adma_port_start,
.port_stop  = nv_adma_port_stop,
+   .port_suspend   = nv_adma_port_suspend,
+   .port_resume= nv_adma_port_resume,
.host_stop  = nv_adma_host_stop,
};

@@ -476,6 +495,7 @@ static struct ata_port_info nv_port_info
{
.sht= nv_adma_sht,
.flags  = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+  ATA_FLAG_HRST_TO_RESUME | 
  ATA_FLAG_MMIO | ATA_FLAG_NCQ,

.pio_mask   = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK,
@@ -492,32 +512,10 @@ MODULE_VERSION(DRV_VERSION);

static int adma_enabled = 1;

-static inline void __iomem *__nv_adma_ctl_block(void __iomem *mmio,
-   unsigned int port_no)
-{
-   mmio

[PATCH -mm] sata_nv: fix kfree ordering in remove

2006-12-11 Thread Robert Hancock

Jeff Garzik wrote:

It is unwise to free the struct before the ports are even detached.


Right, theoretically something bad could happen here (though not 
likely). Here's a fix. Sorry for attaching with something so trivial, 
but Thunderbird isn't very cooperative..


---

The suspend/resume change for sata_nv introduced a potential bug where 
the hpriv structure could be used after it was freed in nv_remove_one. 
Fix that.


Signed-off-by: Robert Hancock [EMAIL PROTECTED]

---
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/
--- linux-2.6.19-rc6-mm2/drivers/ata/sata_nv.c  2006-12-11 22:13:26.0 
-0600
+++ linux-2.6.19-rc6-mm2admafix/drivers/ata/sata_nv.c   2006-12-11 
22:15:58.0 -0600
@@ -1555,8 +1555,8 @@ static void nv_remove_one (struct pci_de
struct ata_host *host = dev_get_drvdata(pdev-dev);
struct nv_host_priv *hpriv = host-private_data;

-   kfree(hpriv);
ata_pci_remove_one(pdev);
+   kfree(hpriv);
 }  
 
 static int nv_pci_device_resume(struct pci_dev *pdev)


[PATCH -mm] sata_nv: add suspend/resume support

2006-11-29 Thread Robert Hancock
The attached patch is against 2.6.18-rc6-mm1, to be applied on top of 
the patch sata_nv: fix ATAPI in ADMA mode which Andrew and Jeff 
already have in their trees. I've only been able to test this myself by 
doing an aborted suspend and immediate resume and verifying it doesn't 
blow up in that case (suspend-to-RAM is broken on my box and something 
isn't configured properly for suspend-to-disk to work). However, since 
resume will definitely not work on some of these controllers without 
this patch, I think it's an improvement in any case..


---

This patch adds the necessary callbacks to support suspend/resume 
properly in sata_nv. Most of the controllers don't need any specific 
handling but CK804/MCP04 controllers, whether ADMA is enabled or not, 
need some additional setup on resume.


As well as the additional storage of the controller type needed for 
proper resume handling, this also removes the inline helper functions 
for getting ADMA register locations by storing the pointers so we don't 
have to keep calculating them all the time.


Signed-off-by: Robert Hancock [EMAIL PROTECTED]

---
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/


--- linux-2.6.19-rc6-mm1-admafixnoresume/drivers/ata/sata_nv.c  2006-11-26 
00:53:44.0 -0600
+++ linux-2.6.19-rc6-mm1-admafix/drivers/ata/sata_nv.c  2006-11-29 
18:42:17.0 -0600
@@ -49,7 +49,7 @@
 #include linux/libata.h
 
 #define DRV_NAME   sata_nv
-#define DRV_VERSION3.2
+#define DRV_VERSION3.3
 
 #define NV_ADMA_DMA_BOUNDARY   0xUL
 
@@ -213,12 +213,21 @@ struct nv_adma_port_priv {
dma_addr_t  cpb_dma;
struct nv_adma_prd  *aprd;
dma_addr_t  aprd_dma;
+   void __iomem *  ctl_block;
+   void __iomem *  gen_block;
+   void __iomem *  notifier_clear_block;
u8  flags;
 };
 
+struct nv_host_priv {
+   unsigned long   type;
+};
+
 #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL)  ( 1  (19 + (12 * (PORT)
 
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static void nv_remove_one (struct pci_dev *pdev);
+static int nv_pci_device_resume(struct pci_dev *pdev);
 static void nv_ck804_host_stop(struct ata_host *host);
 static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
 static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
@@ -239,6 +248,8 @@ static irqreturn_t nv_adma_interrupt(int
 static void nv_adma_irq_clear(struct ata_port *ap);
 static int nv_adma_port_start(struct ata_port *ap);
 static void nv_adma_port_stop(struct ata_port *ap);
+static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg);
+static int nv_adma_port_resume(struct ata_port *ap);
 static void nv_adma_error_handler(struct ata_port *ap);
 static void nv_adma_host_stop(struct ata_host *host);
 static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc);
@@ -292,7 +303,9 @@ static struct pci_driver nv_pci_driver =
.name   = DRV_NAME,
.id_table   = nv_pci_tbl,
.probe  = nv_init_one,
-   .remove = ata_pci_remove_one,
+   .suspend= ata_pci_device_suspend,
+   .resume = nv_pci_device_resume,
+   .remove = nv_remove_one,
 };
 
 static struct scsi_host_template nv_sht = {
@@ -311,6 +324,8 @@ static struct scsi_host_template nv_sht 
.slave_configure= ata_scsi_slave_config,
.slave_destroy  = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
+   .suspend= ata_scsi_device_suspend,
+   .resume = ata_scsi_device_resume,
 };
 
 static struct scsi_host_template nv_adma_sht = {
@@ -330,6 +345,8 @@ static struct scsi_host_template nv_adma
.slave_configure= nv_adma_slave_config,
.slave_destroy  = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
+   .suspend= ata_scsi_device_suspend,
+   .resume = ata_scsi_device_resume,
 };
 
 static const struct ata_port_operations nv_generic_ops = {
@@ -438,6 +455,8 @@ static const struct ata_port_operations 
.scr_write  = nv_scr_write,
.port_start = nv_adma_port_start,
.port_stop  = nv_adma_port_stop,
+   .port_suspend   = nv_adma_port_suspend,
+   .port_resume= nv_adma_port_resume,
.host_stop  = nv_adma_host_stop,
 };
 
@@ -476,6 +495,7 @@ static struct ata_port_info nv_port_info
{
.sht= nv_adma_sht,
.flags  = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_HRST_TO_RESUME

[PATCH -mm] sata_nv: fix ATAPI in ADMA mode

2006-11-26 Thread Robert Hancock
The attached patch against 2.6.19-rc6-mm1 fixes some problems in sata_nv 
with ATAPI devices on controllers running in ADMA mode. Some of the 
logic in the nv_adma_bmdma_* functions was inverted causing a bunch of 
warnings and caused those functions not to work properly. Also, when an 
ATAPI device is connected, we need to use the legacy DMA engine. The 
code now disables the PCI configuration register bits for ADMA so that 
this works, and ensures that no ATAPI DMA commands go through until this 
is done.


Fixes Bugzilla http://bugzilla.kernel.org/show_bug.cgi?id=7538

Signed-off-by: Robert Hancock [EMAIL PROTECTED]

--
Robert Hancock  Saskatoon, SK, Canada
To email, remove nospam from [EMAIL PROTECTED]
Home Page: http://www.roberthancock.com/
--- linux-2.6.19-rc6-mm1/drivers/ata/sata_nv.c  2006-11-25 10:04:14.0 
-0600
+++ linux-2.6.19-rc6-mm1-admafix/drivers/ata/sata_nv.c  2006-11-25 
21:06:24.0 -0600
@@ -49,7 +49,7 @@
 #include linux/libata.h
 
 #define DRV_NAME   sata_nv
-#define DRV_VERSION3.1
+#define DRV_VERSION3.2
 
 #define NV_ADMA_DMA_BOUNDARY   0xUL
 
@@ -165,6 +165,7 @@ enum {
 
/* port flags */
NV_ADMA_PORT_REGISTER_MODE  = (1  0),
+   NV_ADMA_ATAPI_SETUP_COMPLETE= (1  1),
 
 };
 
@@ -231,6 +232,7 @@ static void nv_ck804_freeze(struct ata_p
 static void nv_ck804_thaw(struct ata_port *ap);
 static void nv_error_handler(struct ata_port *ap);
 static int nv_adma_slave_config(struct scsi_device *sdev);
+static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
 static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc);
 static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance);
@@ -415,6 +417,7 @@ static const struct ata_port_operations 
.port_disable   = ata_port_disable,
.tf_load= ata_tf_load,
.tf_read= ata_tf_read,
+   .check_atapi_dma= nv_adma_check_atapi_dma,
.exec_command   = ata_exec_command,
.check_status   = ata_check_status,
.dev_select = ata_std_dev_select,
@@ -489,13 +492,71 @@ MODULE_VERSION(DRV_VERSION);
 
 static int adma_enabled = 1;
 
+static inline void __iomem *__nv_adma_ctl_block(void __iomem *mmio,
+   unsigned int port_no)
+{
+   mmio += NV_ADMA_PORT + port_no * NV_ADMA_PORT_SIZE;
+   return mmio;
+}
+
+static inline void __iomem *nv_adma_ctl_block(struct ata_port *ap)
+{
+   return __nv_adma_ctl_block(ap-host-mmio_base, ap-port_no);
+}
+
+static inline void __iomem *nv_adma_gen_block(struct ata_port *ap)
+{
+   return (ap-host-mmio_base + NV_ADMA_GEN);
+}
+
+static inline void __iomem *nv_adma_notifier_clear_block(struct ata_port *ap)
+{
+   return (nv_adma_gen_block(ap) + NV_ADMA_NOTIFIER_CLEAR + (4 * 
ap-port_no));
+}
+
+static void nv_adma_register_mode(struct ata_port *ap)
+{
+   void __iomem *mmio = nv_adma_ctl_block(ap);
+   struct nv_adma_port_priv *pp = ap-private_data;
+   u16 tmp;
+
+   if (pp-flags  NV_ADMA_PORT_REGISTER_MODE)
+   return;
+
+   tmp = readw(mmio + NV_ADMA_CTL);
+   writew(tmp  ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
+
+   pp-flags |= NV_ADMA_PORT_REGISTER_MODE;
+}
+
+static void nv_adma_mode(struct ata_port *ap)
+{
+   void __iomem *mmio = nv_adma_ctl_block(ap);
+   struct nv_adma_port_priv *pp = ap-private_data;
+   u16 tmp;
+
+   if (!(pp-flags  NV_ADMA_PORT_REGISTER_MODE))
+   return;
+   
+   WARN_ON(pp-flags  NV_ADMA_ATAPI_SETUP_COMPLETE);
+
+   tmp = readw(mmio + NV_ADMA_CTL);
+   writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
+
+   pp-flags = ~NV_ADMA_PORT_REGISTER_MODE;
+}
+
 static int nv_adma_slave_config(struct scsi_device *sdev)
 {
struct ata_port *ap = ata_shost_to_port(sdev-host);
+   struct nv_adma_port_priv *pp = ap-private_data;
+   struct pci_dev *pdev = to_pci_dev(ap-host-dev);
u64 bounce_limit;
unsigned long segment_boundary;
unsigned short sg_tablesize;
int rc;
+   int adma_enable;
+   u32 current_reg, new_reg, config_mask;
 
rc = ata_scsi_slave_config(sdev);
 
@@ -516,13 +577,40 @@ static int nv_adma_slave_config(struct s
/* Subtract 1 since an extra entry may be needed for padding, 
see
   libata-scsi.c */
sg_tablesize = LIBATA_MAX_PRD - 1;
+   
+   /* Since the legacy DMA engine is in use, we need to disable 
ADMA
+  on the port. */
+   adma_enable = 0;
+   nv_adma_register_mode(ap);
}
else {
bounce_limit = *ap-dev-dma_mask;
segment_boundary = NV_ADMA_DMA_BOUNDARY;
sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN

<    1   2