linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [git patches] 2.6.x libata updates
@ 2006-01-18  2:15 Jeff Garzik
  2006-01-18  2:33 ` Andrew Morton
  0 siblings, 1 reply; 50+ messages in thread
From: Jeff Garzik @ 2006-01-18  2:15 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-ide, linux-kernel


Please pull from 'upstream-linus' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

to receive the following updates:

 drivers/pci/quirks.c        |    5 ++-
 drivers/scsi/ahci.c         |   10 ++++++
 drivers/scsi/ata_piix.c     |    3 +
 drivers/scsi/libata-core.c  |   73 +++++++++++++++++++++++++++++++++++++-------
 drivers/scsi/sata_promise.c |   16 +++++++++
 drivers/scsi/sata_svw.c     |    1 
 include/linux/libata.h      |   11 ++++--
 7 files changed, 105 insertions(+), 14 deletions(-)

Alan Cox:
      libata: Pre UDMA EIDE PIO mode selection
      libata: add a function to decide if we need iordy
      libata: Fix heuristic typos add LBA48PIO flag and support code, add IRQ flag for next diff
      libata: Fix sector lock to apply to both drives not drive 0 twice
      libata: Code for the IRQ mask flag

Jason Gaston:
      ahci: AHCI mode SATA patch for Intel ICH8
      Intel ICH8 SATA: add PCI device IDs

Oliver Weihe:
      [libata] sata_svw: add pci id

Yusuf Iskenderoglu:
      [libata] sata_promise: add pci id

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 605f0df..dda6099 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1142,6 +1142,9 @@ static void __devinit quirk_intel_ide_co
 	case 0x27c4:
 		ich = 7;
 		break;
+	case 0x2828:	/* ICH8M */
+		ich = 8;
+		break;
 	default:
 		/* we do not handle this PCI device */
 		return;
@@ -1161,7 +1164,7 @@ static void __devinit quirk_intel_ide_co
 		else
 			return;			/* not in combined mode */
 	} else {
-		WARN_ON((ich != 6) && (ich != 7));
+		WARN_ON((ich != 6) && (ich != 7) && (ich != 8));
 		tmp &= 0x3;  /* interesting bits 1:0 */
 		if (tmp & (1 << 0))
 			comb = (1 << 2);	/* PATA port 0, SATA port 1 */
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index d113290..19bd346 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -276,6 +276,16 @@ static const struct pci_device_id ahci_p
 	  board_ahci }, /* ESB2 */
 	{ PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ICH7-M DH */
+	{ PCI_VENDOR_ID_INTEL, 0x2821, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH8 */
+	{ PCI_VENDOR_ID_INTEL, 0x2822, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH8 */
+	{ PCI_VENDOR_ID_INTEL, 0x2824, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH8 */
+	{ PCI_VENDOR_ID_INTEL, 0x2829, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH8M */
+	{ PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH8M */
 	{ }	/* terminate list */
 };
 
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 557788e..fc3ca05 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -157,6 +157,9 @@ static const struct pci_device_id piix_p
 	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 
 	{ }	/* terminate list */
 };
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 99bae83..46c4cdb 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -611,6 +611,10 @@ int ata_rwcmd_protocol(struct ata_queued
 	if (dev->flags & ATA_DFLAG_PIO) {
 		tf->protocol = ATA_PROT_PIO;
 		index = dev->multi_count ? 0 : 8;
+	} else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
+		/* Unable to use DMA due to host limitation */
+		tf->protocol = ATA_PROT_PIO;
+		index = dev->multi_count ? 0 : 4;
 	} else {
 		tf->protocol = ATA_PROT_DMA;
 		index = 16;
@@ -1051,18 +1055,22 @@ static unsigned int ata_pio_modes(const 
 {
 	u16 modes;
 
-	/* Usual case. Word 53 indicates word 88 is valid */
-	if (adev->id[ATA_ID_FIELD_VALID] & (1 << 2)) {
+	/* Usual case. Word 53 indicates word 64 is valid */
+	if (adev->id[ATA_ID_FIELD_VALID] & (1 << 1)) {
 		modes = adev->id[ATA_ID_PIO_MODES] & 0x03;
 		modes <<= 3;
 		modes |= 0x7;
 		return modes;
 	}
 
-	/* If word 88 isn't valid then Word 51 holds the PIO timing number
-	   for the maximum. Turn it into a mask and return it */
-	modes = (2 << (adev->id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
+	/* If word 64 isn't valid then Word 51 high byte holds the PIO timing
+	   number for the maximum. Turn it into a mask and return it */
+	modes = (2 << ((adev->id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF)) - 1 ;
 	return modes;
+	/* But wait.. there's more. Design your standards by committee and
+	   you too can get a free iordy field to process. However its the 
+	   speeds not the modes that are supported... Note drivers using the
+	   timing API will get this right anyway */
 }
 
 struct ata_exec_internal_arg {
@@ -1165,6 +1173,39 @@ ata_exec_internal(struct ata_port *ap, s
 }
 
 /**
+ *	ata_pio_need_iordy	-	check if iordy needed
+ *	@adev: ATA device
+ *
+ *	Check if the current speed of the device requires IORDY. Used
+ *	by various controllers for chip configuration.
+ */
+
+unsigned int ata_pio_need_iordy(const struct ata_device *adev)
+{
+	int pio;
+	int speed = adev->pio_mode - XFER_PIO_0;
+
+	if (speed < 2)
+		return 0;
+	if (speed > 2)
+		return 1;
+		
+	/* If we have no drive specific rule, then PIO 2 is non IORDY */
+
+	if (adev->id[ATA_ID_FIELD_VALID] & 2) {	/* EIDE */
+		pio = adev->id[ATA_ID_EIDE_PIO];
+		/* Is the speed faster than the drive allows non IORDY ? */
+		if (pio) {
+			/* This is cycle times not frequency - watch the logic! */
+			if (pio > 240)	/* PIO2 is 240nS per cycle */
+				return 1;
+			return 0;
+		}
+	}
+	return 0;
+}
+
+/**
  *	ata_dev_identify - obtain IDENTIFY x DEVICE page
  *	@ap: port on which device we wish to probe resides
  *	@device: device bus address, starting at zero
@@ -1415,7 +1456,7 @@ void ata_dev_config(struct ata_port *ap,
 		ap->udma_mask &= ATA_UDMA5;
 		ap->host->max_sectors = ATA_MAX_SECTORS;
 		ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
-		ap->device->flags |= ATA_DFLAG_LOCK_SECTORS;
+		ap->device[i].flags |= ATA_DFLAG_LOCK_SECTORS;
 	}
 
 	if (ap->ops->dev_config)
@@ -3056,10 +3097,21 @@ static void ata_pio_data_xfer(struct ata
 static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
 			  unsigned int buflen, int do_write)
 {
-	if (ap->flags & ATA_FLAG_MMIO)
-		ata_mmio_data_xfer(ap, buf, buflen, do_write);
-	else
-		ata_pio_data_xfer(ap, buf, buflen, do_write);
+	/* Make the crap hardware pay the costs not the good stuff */
+	if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) {
+		unsigned long flags;
+		local_irq_save(flags);
+		if (ap->flags & ATA_FLAG_MMIO)
+			ata_mmio_data_xfer(ap, buf, buflen, do_write);
+		else
+			ata_pio_data_xfer(ap, buf, buflen, do_write);
+		local_irq_restore(flags);
+	} else {
+		if (ap->flags & ATA_FLAG_MMIO)
+			ata_mmio_data_xfer(ap, buf, buflen, do_write);
+		else
+			ata_pio_data_xfer(ap, buf, buflen, do_write);
+	}
 }
 
 /**
@@ -5122,6 +5174,7 @@ EXPORT_SYMBOL_GPL(ata_dev_id_string);
 EXPORT_SYMBOL_GPL(ata_dev_config);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
+EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
 EXPORT_SYMBOL_GPL(ata_timing_compute);
 EXPORT_SYMBOL_GPL(ata_timing_merge);
 
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 3d1ea09..b0b0a69 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -66,6 +66,7 @@ enum {
 	board_2037x		= 0,	/* FastTrak S150 TX2plus */
 	board_20319		= 1,	/* FastTrak S150 TX4 */
 	board_20619		= 2,	/* FastTrak TX4000 */
+	board_20771		= 3,	/* FastTrak TX2300 */
 
 	PDC_HAS_PATA		= (1 << 1), /* PDC20375 has PATA */
 
@@ -190,6 +191,16 @@ static const struct ata_port_info pdc_po
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_pata_ops,
 	},
+
+	/* board_20771 */
+	{
+		.sht		= &pdc_ata_sht,
+		.host_flags	= PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.port_ops	= &pdc_sata_ops,
+	},
 };
 
 static const struct pci_device_id pdc_ata_pci_tbl[] = {
@@ -226,6 +237,8 @@ static const struct pci_device_id pdc_at
 	{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20619 },
 
+	{ PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_20771 },
 	{ }	/* terminate list */
 };
 
@@ -706,6 +719,9 @@ static int pdc_ata_init_one (struct pci_
 	case board_2037x:
 		probe_ent->n_ports = 2;
 		break;
+	case board_20771:
+		probe_ent->n_ports = 2;
+		break;
 	case board_20619:
 		probe_ent->n_ports = 4;
 
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 6683735..d847256 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -470,6 +470,7 @@ static const struct pci_device_id k2_sat
 	{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
 	{ 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+	{ 0x1166, 0x024b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ }
 };
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index a43c95f..9e5db29 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -126,16 +126,19 @@ enum {
 
 	ATA_FLAG_SUSPENDED	= (1 << 12), /* port is suspended */
 
+	ATA_FLAG_PIO_LBA48	= (1 << 13), /* Host DMA engine is LBA28 only */
+	ATA_FLAG_IRQ_MASK	= (1 << 14), /* Mask IRQ in PIO xfers */
+
 	ATA_QCFLAG_ACTIVE	= (1 << 1), /* cmd not yet ack'd to scsi lyer */
 	ATA_QCFLAG_SG		= (1 << 3), /* have s/g table? */
 	ATA_QCFLAG_SINGLE	= (1 << 4), /* no s/g, just a single buffer */
 	ATA_QCFLAG_DMAMAP	= ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
 
 	/* various lengths of time */
-	ATA_TMOUT_EDD		= 5 * HZ,	/* hueristic */
+	ATA_TMOUT_EDD		= 5 * HZ,	/* heuristic */
 	ATA_TMOUT_PIO		= 30 * HZ,
-	ATA_TMOUT_BOOT		= 30 * HZ,	/* hueristic */
-	ATA_TMOUT_BOOT_QUICK	= 7 * HZ,	/* hueristic */
+	ATA_TMOUT_BOOT		= 30 * HZ,	/* heuristic */
+	ATA_TMOUT_BOOT_QUICK	= 7 * HZ,	/* heuristic */
 	ATA_TMOUT_CDB		= 30 * HZ,
 	ATA_TMOUT_CDB_QUICK	= 5 * HZ,
 	ATA_TMOUT_INTERNAL	= 30 * HZ,
@@ -499,6 +502,8 @@ extern int ata_scsi_slave_config(struct 
 /*
  * Timing helpers
  */
+
+extern unsigned int ata_pio_need_iordy(const struct ata_device *);
 extern int ata_timing_compute(struct ata_device *, unsigned short,
 			      struct ata_timing *, int, int);
 extern void ata_timing_merge(const struct ata_timing *,

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

* Re: [git patches] 2.6.x libata updates
  2006-01-18  2:15 [git patches] 2.6.x libata updates Jeff Garzik
@ 2006-01-18  2:33 ` Andrew Morton
  2006-01-18  5:18   ` Jeff Garzik
  0 siblings, 1 reply; 50+ messages in thread
From: Andrew Morton @ 2006-01-18  2:33 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, linux-ide, linux-kernel, Reuben Farrelly

Jeff Garzik <jgarzik@pobox.com> wrote:
>
>  Please pull from 'upstream-linus' branch of
>  master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

I worry that whatever it is which has busted Reuben's machine will leak
into mainline.  This patch probably isn't it.

I guess if we can feed libata and acpi into mainline in little bits and
pieces like this, that'll help us work out the cause.

Reuben has spent ages bisecting lots of patches, but the bug is quite
intermittent, which makes the process quite maddeningly error-prone and
slow.

Then again, perhaps merging it up is the best way of fixing it: someone out
there will hit the thing more repeatably and will have a better shot at
finding the cause.



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

* Re: [git patches] 2.6.x libata updates
  2006-01-18  2:33 ` Andrew Morton
@ 2006-01-18  5:18   ` Jeff Garzik
  0 siblings, 0 replies; 50+ messages in thread
From: Jeff Garzik @ 2006-01-18  5:18 UTC (permalink / raw)
  To: Andrew Morton; +Cc: torvalds, linux-ide, linux-kernel, Reuben Farrelly

Andrew Morton wrote:
> Jeff Garzik <jgarzik@pobox.com> wrote:
> 
>> Please pull from 'upstream-linus' branch of
>> master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
> 
> 
> I worry that whatever it is which has busted Reuben's machine will leak
> into mainline.  This patch probably isn't it.

Nothing at all in this push is remotely controversial...


> I guess if we can feed libata and acpi into mainline in little bits and
> pieces like this, that'll help us work out the cause.
> 
> Reuben has spent ages bisecting lots of patches, but the bug is quite
> intermittent, which makes the process quite maddeningly error-prone and
> slow.
> 
> Then again, perhaps merging it up is the best way of fixing it: someone out
> there will hit the thing more repeatably and will have a better shot at
> finding the cause.

Well, I haven't even looked at ACPI yet, and the Jens/Tejun stuff didn't 
get much testing at all.  There's a lot of unfamiliar stuff in the mix.

	Jeff



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

* Re: [git patches] 2.6.x libata updates
  2006-01-03 17:43     ` Jeff Garzik
  2006-01-03 18:35       ` Bartlomiej Zolnierkiewicz
@ 2006-01-04 14:02       ` Alan Cox
  1 sibling, 0 replies; 50+ messages in thread
From: Alan Cox @ 2006-01-04 14:02 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Bartlomiej Zolnierkiewicz, Andrew Morton, Linus Torvalds,
	linux-ide, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1215 bytes --]

On Maw, 2006-01-03 at 12:43 -0500, Jeff Garzik wrote:
> Not really.  If there's no support in mainline, I'm ok with pushing them 
> upstream...  provided that they have been tested and verified to work on 
> at least one machine?  :)

Tested with real hardware and Debian (not enough RAM on MPIIX boxes for
Fedora 8)). The driver mostly duplicates some core code because the
MPIIX isn't quite a PCI IDE controller in the modern sense. That could
be changed to some flags (ALWAYS_LEGACY and DONT_DISABLE) for the core
PCI code but I agree with Bartlomiej sentiment from some time ago that
it is better not to clutter the core libata code with historical
wonders.

Would be slightly cleaner if the core code set adev->pio_mode to PIO0
before doing the identify. Thats something that perhaps should be
handled more specifically by the ATA core since we've no idea how the
BIOS left PATA/SATA controller modes before handing off to us ?


Suggested config entry:

config SCSI_ATA_MPIIX
	tristate "Intel MPIIX PATA support"
	depends on SCSI_SATA && PCI && X86 && !X86_64
	help
	  This option enables support for the Intel MPIIX laptop IDE
	  controller found on some older pentium class laptops.

	  If unsure, say N.



[-- Attachment #2: Driver for MPIIX chipsets --]
[-- Type: text/plain, Size: 9263 bytes --]

/*
 * pata_mpiix.c 	- Intel MPIIX PATA for new ATA layer
 *			  (C) 2005-2006 Red Hat Inc
 *			  Alan Cox <alan@redhat.com>
 *
 * The MPIIX is different enough to the PIIX4 and friends that we give it
 * a separate driver. The old ide/pci code handles this by just not tuning
 * MPIIX at all. 
 *
 * The MPIIX also differs in another important way from the majority of PIIX
 * devices. The chip is a bridge (pardon the pun) between the old world of
 * ISA IDE and PCI IDE. Although the ATA timings are PCI configured the actual
 * IDE controller is not decoded in PCI space and the chip does not claim to
 * be IDE class PCI. This requires slightly non-standard probe logic compared
 * with PCI IDE and also that we do not disable the device when our driver is
 * unloaded (as it has many other functions).
 *
 * The driver conciously keeps this logic internally to avoid pushing quirky
 * PATA history into the clean libata layer.
 *
 * Thinkpad specific note: If you boot an MPIIX using thinkpad with a PCMCIA 
 * hard disk present this driver will not detect it. This is not a bug. In this
 * configuration the secondary port of the MPIIX is disabled and the addresses
 * are decoded by the PCMCIA bridge and therefore are for a generic IDE driver
 * to operate.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>

#define DRV_NAME "pata_mpiix"
#define DRV_VERSION "0.3"

/**
 *	mpiix_phy_reset		-	probe reset
 *	@ap: ATA port
 *
 *	Perform the ATA probe and bus reset sequence plus specific handling
 *	for this hardware. The MPIIX has the enable bits in a different place
 *	to PIIX4 and friends. As a pure PIO device it has no cable detect
 */

static void mpiix_phy_reset(struct ata_port *ap)
{
	struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
	static const struct pci_bits mpiix_enable_bits[] = {
		{ 0x6D, 1, 0x80, 0x80 },
		{ 0x6F, 1, 0x80, 0x80 }
	};

	if (!pci_test_config_bits(pdev, &mpiix_enable_bits[ap->hard_port_no])) {
		ata_port_disable(ap);
		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
		return;
	}
	ap->cbl = ATA_CBL_PATA40;
	ata_port_probe(ap);
	ata_bus_reset(ap);
}

/**
 *	mpiix_set_piomode	-	set initial PIO mode data
 *	@ap: ATA interface
 *	@adev: ATA device
 *
 *	Called to do the PIO mode setup. The MPIIX allows us to program the
 *	IORDY sample point (2-5 clocks), recovery 1-4 clocks and whether
 *	prefetching or iordy are used.
 *
 *	This would get very ugly because we can only program timing for one
 *	device at a time, the other gets PIO0. Fortunately libata calls 
 *	our qc_issue_prot command before a command is issued so we can
 *	flip the timings back and forth to reduce the pain.
 */

static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
	int control = 0;
	int pio = adev->pio_mode - XFER_PIO_0;
	struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
	u16 idetim;
	static const	 /* ISP  RTC */
	u8 timings[][2]	= { { 0, 0 },
			    { 0, 0 },
			    { 1, 0 },
			    { 2, 1 },
			    { 2, 3 }, };

	pci_read_config_word(pdev, 0x6C, &idetim);
	/* Mask the IORDY/TIME/PPE0 bank for this device */
	if (adev->class == ATA_DEV_ATA)
		control |= 4;	/* PPE enable for disk */
	if (ata_pio_need_iordy(adev))
		control |= 2;	/* IORDY */
	if (pio > 0)
		control |= 1;	/* This drive is on the fast timing bank */

	/* Mask out timing and clear both TIME bank selects */
	idetim &= 0xCCEE;
	idetim &= ~(0x07  << (2 * adev->devno));
	idetim |= (control << (2 * adev->devno));
	
	idetim |= (timings[pio][0] << 12) | (timings[pio][1] << 8);
	pci_write_config_word(pdev, 0x6C, idetim);
	
	/* We use ap->private_data as a pointer to the device currently
	   loaded for timing */
	ap->private_data = adev;
}

/**
 *	mpiix_qc_issue_prot	-	command issue
 *	@qc: command pending
 *
 *	Called when the libata layer is about to issue a command. We wrap
 *	this interface so that we can load the correct ATA timings if
 *	neccessary. Our logic also clears TIME0/TIME1 for the other device so
 *	that, even if we get this wrong, cycles to the other device will
 *	be made PIO0.
 */

static int mpiix_qc_issue_prot(struct ata_queued_cmd *qc)
{
	struct ata_port *ap = qc->ap;
	struct ata_device *adev = qc->dev;

	/* If modes have been configured and the channel data is not loaded
	   then load it. We have to check if pio_mode is set as the core code
	   does not set adev->pio_mode to XFER_PIO_0 while probing as would be
	   logical */
	   
	if(adev->pio_mode && adev != ap->private_data)
		mpiix_set_piomode(ap, adev);
		
	return ata_qc_issue_prot(qc);
}

static struct scsi_host_template mpiix_sht = {
	.module			= THIS_MODULE,
	.name			= DRV_NAME,
	.ioctl			= ata_scsi_ioctl,
	.queuecommand		= ata_scsi_queuecmd,
	.eh_strategy_handler	= ata_scsi_error,
	.can_queue		= ATA_DEF_QUEUE,
	.this_id		= ATA_SHT_THIS_ID,
	.sg_tablesize		= LIBATA_MAX_PRD,
	.max_sectors		= ATA_MAX_SECTORS,
	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
	.emulated		= ATA_SHT_EMULATED,
	.use_clustering		= ATA_SHT_USE_CLUSTERING,
	.proc_name		= DRV_NAME,
	.dma_boundary		= ATA_DMA_BOUNDARY,
	.slave_configure	= ata_scsi_slave_config,
	.bios_param		= ata_std_bios_param,
	.ordered_flush		= 1,
};

static struct ata_port_operations mpiix_port_ops = {
	.port_disable	= ata_port_disable,
	.set_piomode	= mpiix_set_piomode,

	.tf_load	= ata_tf_load,
	.tf_read	= ata_tf_read,
	.check_status 	= ata_check_status,
	.exec_command	= ata_exec_command,
	.dev_select 	= ata_std_dev_select,

	.phy_reset	= mpiix_phy_reset,

	.qc_prep 	= ata_qc_prep,
	.qc_issue	= mpiix_qc_issue_prot,
	.eng_timeout	= ata_eng_timeout,

	.irq_handler	= ata_interrupt,
	.irq_clear	= ata_bmdma_irq_clear,

	.port_start	= ata_port_start,
	.port_stop	= ata_port_stop,
	.host_stop	= ata_host_stop
};

static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
	/* Single threaded by the PCI probe logic */
	static struct ata_probe_ent probe[2];
	static int printed_version;
	u16 idetim;
	int ports = 0;
	
	if (!printed_version++)
		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
		
	/* MPIIX has many functions which can be turned on or off according
	   to other devices present. Make sure IDE is enabled before we try
	   and use it */
	   
	pci_read_config_word(dev, 0x6C, &idetim);
	if(!(idetim & 0x8000))
		return -ENODEV;

	/* We do our own plumbing to avoid leaking special cases for whacko
	   ancient hardware into the core code. There are two issues to 
	   worry about.  #1 The chip is a bridge so if in legacy mode and
	   without BARs set fools the setup.  #2 If you pci_disable_device
	   the MPIIX your box goes castors up */

	INIT_LIST_HEAD(&probe[0].node);
	probe[0].dev = pci_dev_to_dev(dev);
	probe[0].port_ops = &mpiix_port_ops;
	probe[0].sht = &mpiix_sht;
	probe[0].pio_mask = 0x1F;
	probe[0].irq = 14;
	probe[0].irq_flags = SA_SHIRQ;
	probe[0].host_flags = ATA_FLAG_SLAVE_POSS;
	probe[0].legacy_mode = 1;
	probe[0].hard_port_no = 0;
	probe[0].n_ports = 1;
	probe[0].port[0].cmd_addr = 0x1F0;
	probe[0].port[0].ctl_addr = 0x3F6;
	probe[0].port[0].altstatus_addr = 0x3F6;
	
	/* The secondary lurks at different addresses but is otherwise
	   the same beastie */
	   
	INIT_LIST_HEAD(&probe[1].node);
	probe[1] = probe[0];
	probe[1].irq = 15;
	probe[1].hard_port_no = 1;
	probe[1].port[0].cmd_addr = 0x170;
	probe[1].port[0].ctl_addr = 0x376;
	probe[1].port[0].altstatus_addr = 0x376;
	
	/* Let libata fill in the port details */
	ata_std_ports(&probe[0].port[0]);
	ata_std_ports(&probe[1].port[0]);
	
	/* Now add the ports that are active */
	ports += ata_device_add(&probe[0]);
	ports += ata_device_add(&probe[1]);
	if(ports)
		return 0;
	return -ENODEV;
}

/**
 *	mpiix_remove_one	-	device unload
 *	@pdev: PCI device being removed
 *
 *	Handle an unplug/unload event for a PCI device. Unload the
 *	PCI driver but do not use the default handler as we *MUST NOT*
 *	disable the device as it has other functions.
 */
 
static void __devexit mpiix_remove_one(struct pci_dev *pdev)
{
	struct device *dev = pci_dev_to_dev(pdev);
	struct ata_host_set *host_set = dev_get_drvdata(dev);

	ata_host_set_remove(host_set);
	dev_set_drvdata(dev, NULL);
}



static const struct pci_device_id mpiix[] = {
	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
	{ 0, },
};

static struct pci_driver mpiix_pci_driver = {
        .name 		= DRV_NAME,
	.id_table	= mpiix,
	.probe 		= mpiix_init_one,
	.remove		= mpiix_remove_one
};

static int __init mpiix_init(void)
{
	return pci_module_init(&mpiix_pci_driver);
}


static void __exit mpiix_exit(void)
{
	pci_unregister_driver(&mpiix_pci_driver);
}


MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("low-level driver for Intel MPIIX");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, mpiix);
MODULE_VERSION(DRV_VERSION);

module_init(mpiix_init);
module_exit(mpiix_exit);

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

* Re: [git patches] 2.6.x libata updates
  2006-01-03 18:35       ` Bartlomiej Zolnierkiewicz
@ 2006-01-03 18:50         ` Alan Cox
  0 siblings, 0 replies; 50+ messages in thread
From: Alan Cox @ 2006-01-03 18:50 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: Jeff Garzik, Andrew Morton, Linus Torvalds, linux-ide, linux-kernel

On Maw, 2006-01-03 at 19:35 +0100, Bartlomiej Zolnierkiewicz wrote:
> > Not really.  If there's no support in mainline, I'm ok with pushing them
> > upstream...  provided that they have been tested and verified to work on
> > at least one machine?  :)
> 
> All chipsets are supported by piix.c driver but:

No they are not. The drivers claim the PCI identifiers but that is not
the same thing as working.

> * we depend on BIOS to program correct PIO timings and set drives
>   (mpiix chipset)

It doesn't work except for PIO0. I've tested it on a thinkpad.

> * PIO tuning code is buggy and needs fixing (oldpiix chipsets)

It crashes. I've tested it.

> I don't think that this alone justify adding new drivers instead of fixing
> old one as both issues can be fixed quite easily by almost cut'n'pasting
> new tuning code from Alan's drivers and adding it to piix.c.

Hardly. The existing PIIX drivers in drivers/ide/pci are *very* buggy.
Some of the bugs are careless but alarming like scribbles to wrong PCI
registers and easily fixed. Others like the mishandling of fifos are
corruptors that thankfully aren't biting writable media. The handling of
pre SITRE capable chipsets in the current driver is broken to the point
it needs a rewrite that quite frankly I don't think can be done without
fixing the locking in the core code.

Please spend your effort improving the ide/pci drivers rather than
trying to block their future replacement with better technology. I've
posted detailed summaries of flaws in several chipsets but no fixes have
appeared.

Alan


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

* Re: [git patches] 2.6.x libata updates
  2006-01-03 17:43     ` Jeff Garzik
@ 2006-01-03 18:35       ` Bartlomiej Zolnierkiewicz
  2006-01-03 18:50         ` Alan Cox
  2006-01-04 14:02       ` Alan Cox
  1 sibling, 1 reply; 50+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2006-01-03 18:35 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Alan Cox, Andrew Morton, Linus Torvalds, linux-ide, linux-kernel

On 1/3/06, Jeff Garzik <jgarzik@pobox.com> wrote:
> Alan Cox wrote:
> > On Maw, 2006-01-03 at 17:51 +0100, Bartlomiej Zolnierkiewicz wrote:
> >
> >>>+ * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
> >>>+ * for the early chip drivers.
> >>
> >>pata_oldpiix and pata_mpiix are not in the mainline
> >
> >
> > They are probably ready for mainline and since Linux currently has no
> > support for either it might be nice to get them in. Anything specific
> > they need polishing for Jeff ?
>
> Not really.  If there's no support in mainline, I'm ok with pushing them
> upstream...  provided that they have been tested and verified to work on
> at least one machine?  :)

All chipsets are supported by piix.c driver but:

* we depend on BIOS to program correct PIO timings and set drives
  (mpiix chipset)

* PIO tuning code is buggy and needs fixing (oldpiix chipsets)

I don't think that this alone justify adding new drivers instead of fixing
old one as both issues can be fixed quite easily by almost cut'n'pasting
new tuning code from Alan's drivers and adding it to piix.c.

Bartlomiej

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

* Re: [git patches] 2.6.x libata updates
  2006-01-03 17:32   ` Alan Cox
@ 2006-01-03 17:43     ` Jeff Garzik
  2006-01-03 18:35       ` Bartlomiej Zolnierkiewicz
  2006-01-04 14:02       ` Alan Cox
  0 siblings, 2 replies; 50+ messages in thread
From: Jeff Garzik @ 2006-01-03 17:43 UTC (permalink / raw)
  To: Alan Cox
  Cc: Bartlomiej Zolnierkiewicz, Andrew Morton, Linus Torvalds,
	linux-ide, linux-kernel

Alan Cox wrote:
> On Maw, 2006-01-03 at 17:51 +0100, Bartlomiej Zolnierkiewicz wrote:
> 
>>>+ * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
>>>+ * for the early chip drivers.
>>
>>pata_oldpiix and pata_mpiix are not in the mainline
> 
> 
> They are probably ready for mainline and since Linux currently has no
> support for either it might be nice to get them in. Anything specific
> they need polishing for Jeff ?

Not really.  If there's no support in mainline, I'm ok with pushing them 
upstream...  provided that they have been tested and verified to work on 
at least one machine?  :)

	Jeff




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

* Re: [git patches] 2.6.x libata updates
  2006-01-03 16:51 ` Bartlomiej Zolnierkiewicz
  2006-01-03 16:56   ` Jeff Garzik
@ 2006-01-03 17:32   ` Alan Cox
  2006-01-03 17:43     ` Jeff Garzik
  1 sibling, 1 reply; 50+ messages in thread
From: Alan Cox @ 2006-01-03 17:32 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: Jeff Garzik, Andrew Morton, Linus Torvalds, linux-ide, linux-kernel

On Maw, 2006-01-03 at 17:51 +0100, Bartlomiej Zolnierkiewicz wrote:
> > + * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
> > + * for the early chip drivers.
> 
> pata_oldpiix and pata_mpiix are not in the mainline

They are probably ready for mainline and since Linux currently has no
support for either it might be nice to get them in. Anything specific
they need polishing for Jeff ?

Alan


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

* Re: [git patches] 2.6.x libata updates
  2006-01-03 16:51 ` Bartlomiej Zolnierkiewicz
@ 2006-01-03 16:56   ` Jeff Garzik
  2006-01-03 17:32   ` Alan Cox
  1 sibling, 0 replies; 50+ messages in thread
From: Jeff Garzik @ 2006-01-03 16:56 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: Andrew Morton, Linus Torvalds, linux-ide, linux-kernel

On Tue, Jan 03, 2006 at 05:51:57PM +0100, Bartlomiej Zolnierkiewicz wrote:
> On 1/3/06, Jeff Garzik <jgarzik@pobox.com> wrote:
> 
> > --- a/drivers/scsi/ata_piix.c
> > +++ b/drivers/scsi/ata_piix.c
> 
> > + * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
> > + * for the early chip drivers.
> 
> pata_oldpiix and pata_mpiix are not in the mainline

Good point.  I'll update to say "in libata-dev#pata-drivers".

	Jeff




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

* Re: [git patches] 2.6.x libata updates
  2006-01-03 16:43 Jeff Garzik
@ 2006-01-03 16:51 ` Bartlomiej Zolnierkiewicz
  2006-01-03 16:56   ` Jeff Garzik
  2006-01-03 17:32   ` Alan Cox
  0 siblings, 2 replies; 50+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2006-01-03 16:51 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Andrew Morton, Linus Torvalds, linux-ide, linux-kernel

On 1/3/06, Jeff Garzik <jgarzik@pobox.com> wrote:

> --- a/drivers/scsi/ata_piix.c
> +++ b/drivers/scsi/ata_piix.c

> + * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
> + * for the early chip drivers.

pata_oldpiix and pata_mpiix are not in the mainline

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

* [git patches] 2.6.x libata updates
@ 2006-01-03 16:43 Jeff Garzik
  2006-01-03 16:51 ` Bartlomiej Zolnierkiewicz
  0 siblings, 1 reply; 50+ messages in thread
From: Jeff Garzik @ 2006-01-03 16:43 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-ide, linux-kernel


Please pull from 'upstream' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

to receive the following updates:

 Documentation/kernel-parameters.txt |    8 
 drivers/pci/quirks.c                |   30 ++
 drivers/scsi/ahci.c                 |   14 -
 drivers/scsi/ata_piix.c             |  127 +++++++++---
 drivers/scsi/libata-core.c          |  364 ++++++++++++++++++++----------------
 drivers/scsi/libata-scsi.c          |   24 +-
 drivers/scsi/libata.h               |    1 
 drivers/scsi/pdc_adma.c             |   11 -
 drivers/scsi/sata_mv.c              |   11 -
 drivers/scsi/sata_promise.c         |   20 +
 drivers/scsi/sata_qstor.c           |    9 
 drivers/scsi/sata_sil.c             |    2 
 drivers/scsi/sata_sil24.c           |   15 -
 drivers/scsi/sata_sx4.c             |   17 +
 include/linux/libata.h              |   13 -
 15 files changed, 413 insertions(+), 253 deletions(-)

Alan Cox:
      libata: add ata_piix notes
      libata: ata_piix 450NX errata

Albert Lee:
      libata: minor patch before moving err_mask
      libata: move err_mask to ata_queued_cmd
      libata: determine the err_mask when the error is found
      libata: determine the err_mask directly in atapi_packet_task()
      libata: err_mask misc fix

Arjan van de Ven:
      mark several libata datastructures const

Jeff Garzik:
      [libata] remove two unused fields from struct ata_port
      [libata ata_piix] cleanup: remove duplicate ata_port_info records
      [libata] Print out SATA speed, if link is up
      [libata sata_promise] minor whitespace cleanup

Jesse Barnes:
      add boot option to control Intel SATA/PATA combined mode

Tejun Heo:
      libata: implement ata_exec_internal()
      libata: use ata_exec_internal()
      libata: remove unused functions
      libata: remove unused qc->waiting

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 5dffcfe..61a56b1 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -633,6 +633,14 @@ running once the system is up.
 	inport.irq=	[HW] Inport (ATI XL and Microsoft) busmouse driver
 			Format: <irq>
 
+	combined_mode=	[HW] control which driver uses IDE ports in combined
+			mode: legacy IDE driver, libata, or both
+			(in the libata case, libata.atapi_enabled=1 may be
+			useful as well).  Note that using the ide or libata
+			options may affect your device naming (e.g. by
+			changing hdc to sdb).
+			Format: combined (default), ide, or libata
+
 	inttest=	[IA64]
 
 	io7=		[HW] IO7 for Marvel based alpha systems
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 3a4f49f..f28ebdd 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1098,6 +1098,23 @@ static void __init quirk_alder_ioapic(st
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic );
 #endif
 
+enum ide_combined_type { COMBINED = 0, IDE = 1, LIBATA = 2 };
+/* Defaults to combined */
+static enum ide_combined_type combined_mode;
+
+static int __init combined_setup(char *str)
+{
+	if (!strncmp(str, "ide", 3))
+		combined_mode = IDE;
+	else if (!strncmp(str, "libata", 6))
+		combined_mode = LIBATA;
+	else /* "combined" or anything else defaults to old behavior */
+		combined_mode = COMBINED;
+
+	return 1;
+}
+__setup("combined_mode=", combined_setup);
+
 #ifdef CONFIG_SCSI_SATA_INTEL_COMBINED
 static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
 {
@@ -1164,6 +1181,19 @@ static void __devinit quirk_intel_ide_co
 	if (prog & comb)
 		return;
 
+	/* Don't reserve any so the IDE driver can get them (but only if
+	 * combined_mode=ide).
+	 */
+	if (combined_mode == IDE)
+		return;
+
+	/* Grab them both for libata if combined_mode=libata. */
+	if (combined_mode == LIBATA) {
+		request_region(0x1f0, 8, "libata");	/* port 0 */
+		request_region(0x170, 8, "libata");	/* port 1 */
+		return;
+	}
+
 	/* SATA port is in legacy mode.  Reserve port so that
 	 * IDE driver does not attempt to use it.  If request_region
 	 * fails, it will be obvious at boot time, so we don't bother
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 83467a0..887eaa2 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -243,7 +243,7 @@ static const struct ata_port_operations 
 	.port_stop		= ahci_port_stop,
 };
 
-static struct ata_port_info ahci_port_info[] = {
+static const struct ata_port_info ahci_port_info[] = {
 	/* board_ahci */
 	{
 		.sht		= &ahci_sht,
@@ -643,7 +643,8 @@ static void ahci_eng_timeout(struct ata_
 	 	 * not being called from the SCSI EH.
 	 	 */
 		qc->scsidone = scsi_finish_command;
-		ata_qc_complete(qc, AC_ERR_OTHER);
+		qc->err_mask |= AC_ERR_OTHER;
+		ata_qc_complete(qc);
 	}
 
 	spin_unlock_irqrestore(&host_set->lock, flags);
@@ -664,7 +665,8 @@ static inline int ahci_host_intr(struct 
 	ci = readl(port_mmio + PORT_CMD_ISSUE);
 	if (likely((ci & 0x1) == 0)) {
 		if (qc) {
-			ata_qc_complete(qc, 0);
+			assert(qc->err_mask == 0);
+			ata_qc_complete(qc);
 			qc = NULL;
 		}
 	}
@@ -681,8 +683,10 @@ static inline int ahci_host_intr(struct 
 		/* command processing has stopped due to error; restart */
 		ahci_restart_port(ap, status);
 
-		if (qc)
-			ata_qc_complete(qc, err_mask);
+		if (qc) {
+			qc->err_mask |= AC_ERR_OTHER;
+			ata_qc_complete(qc);
+		}
 	}
 
 	return 1;
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 333d69d..0ea2787 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -37,6 +37,49 @@
  *
  *  Hardware documentation available at http://developer.intel.com/
  *
+ * Documentation
+ *	Publically available from Intel web site. Errata documentation
+ * is also publically available. As an aide to anyone hacking on this
+ * driver the list of errata that are relevant is below.going back to
+ * PIIX4. Older device documentation is now a bit tricky to find.
+ *
+ * The chipsets all follow very much the same design. The orginal Triton
+ * series chipsets do _not_ support independant device timings, but this
+ * is fixed in Triton II. With the odd mobile exception the chips then
+ * change little except in gaining more modes until SATA arrives. This
+ * driver supports only the chips with independant timing (that is those
+ * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
+ * for the early chip drivers.
+ *
+ * Errata of note:
+ *
+ * Unfixable
+ *	PIIX4    errata #9	- Only on ultra obscure hw
+ *	ICH3	 errata #13     - Not observed to affect real hw
+ *				  by Intel
+ *
+ * Things we must deal with
+ *	PIIX4	errata #10	- BM IDE hang with non UDMA
+ *				  (must stop/start dma to recover)
+ *	440MX   errata #15	- As PIIX4 errata #10
+ *	PIIX4	errata #15	- Must not read control registers
+ * 				  during a PIO transfer
+ *	440MX   errata #13	- As PIIX4 errata #15
+ *	ICH2	errata #21	- DMA mode 0 doesn't work right
+ *	ICH0/1  errata #55	- As ICH2 errata #21
+ *	ICH2	spec c #9	- Extra operations needed to handle
+ *				  drive hotswap [NOT YET SUPPORTED]
+ *	ICH2    spec c #20	- IDE PRD must not cross a 64K boundary
+ *				  and must be dword aligned
+ *	ICH2    spec c #24	- UDMA mode 4,5 t85/86 should be 6ns not 3.3
+ *
+ * Should have been BIOS fixed:
+ *	450NX:	errata #19	- DMA hangs on old 450NX
+ *	450NX:  errata #20	- DMA hangs on old 450NX
+ *	450NX:  errata #25	- Corruption with DMA on old 450NX
+ *	ICH3    errata #15      - IDE deadlock under high load
+ *				  (BIOS must set dev 31 fn 0 bit 23)
+ *	ICH3	errata #18	- Don't use native mode
  */
 
 #include <linux/kernel.h>
@@ -78,9 +121,7 @@ enum {
 	ich5_sata		= 1,
 	piix4_pata		= 2,
 	ich6_sata		= 3,
-	ich6_sata_rm		= 4,
-	ich7_sata		= 5,
-	esb2_sata		= 6,
+	ich6_sata_ahci		= 4,
 
 	PIIX_AHCI_DEVICE	= 6,
 };
@@ -111,11 +152,11 @@ static const struct pci_device_id piix_p
 	{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
-	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
-	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
-	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata },
-	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata },
-	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb2_sata },
+	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 
 	{ }	/* terminate list */
 };
@@ -258,31 +299,7 @@ static struct ata_port_info piix_port_in
 		.port_ops	= &piix_sata_ops,
 	},
 
-	/* ich6_sata_rm */
-	{
-		.sht		= &piix_sht,
-		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
-				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
-				  ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
-		.port_ops	= &piix_sata_ops,
-	},
-
-	/* ich7_sata */
-	{
-		.sht		= &piix_sht,
-		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
-				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
-				  ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
-		.port_ops	= &piix_sata_ops,
-	},
-
-	/* esb2_sata */
+	/* ich6_sata_ahci */
 	{
 		.sht		= &piix_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
@@ -603,6 +620,40 @@ static int piix_disable_ahci(struct pci_
 }
 
 /**
+ *	piix_check_450nx_errata	-	Check for problem 450NX setup
+ *	
+ *	Check for the present of 450NX errata #19 and errata #25. If
+ *	they are found return an error code so we can turn off DMA
+ */
+
+static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
+{
+	struct pci_dev *pdev = NULL;
+	u16 cfg;
+	u8 rev;
+	int no_piix_dma = 0;
+	
+	while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
+	{
+		/* Look for 450NX PXB. Check for problem configurations
+		   A PCI quirk checks bit 6 already */
+		pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+		pci_read_config_word(pdev, 0x41, &cfg);
+		/* Only on the original revision: IDE DMA can hang */
+		if(rev == 0x00)
+			no_piix_dma = 1;
+		/* On all revisions below 5 PXB bus lock must be disabled for IDE */
+		else if(cfg & (1<<14) && rev < 5)
+			no_piix_dma = 2;
+	}
+	if(no_piix_dma)
+		dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n");
+	if(no_piix_dma == 2)
+		dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n");
+	return no_piix_dma;
+}		
+
+/**
  *	piix_init_one - Register PIIX ATA PCI device with kernel services
  *	@pdev: PCI device to register
  *	@ent: Entry in piix_pci_tbl matching with @pdev
@@ -676,7 +727,15 @@ static int piix_init_one (struct pci_dev
 			   "combined mode detected (p=%u, s=%u)\n",
 			   pata_chan, sata_chan);
 	}
-
+	if (piix_check_450nx_errata(pdev)) {
+		/* This writes into the master table but it does not
+		   really matter for this errata as we will apply it to
+		   all the PIIX devices on the board */
+		port_info[0]->mwdma_mask = 0;
+		port_info[0]->udma_mask = 0;
+		port_info[1]->mwdma_mask = 0;
+		port_info[1]->udma_mask = 0;
+	}
 	return ata_pci_init_one(pdev, port_info, 2);
 }
 
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index d0a0fdb..9ea1025 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -605,7 +605,7 @@ void ata_rwcmd_protocol(struct ata_queue
 	tf->command = ata_rw_cmds[index + lba48 + write];
 }
 
-static const char * xfer_mode_str[] = {
+static const char * const xfer_mode_str[] = {
 	"UDMA/16",
 	"UDMA/25",
 	"UDMA/33",
@@ -1046,28 +1046,103 @@ static unsigned int ata_pio_modes(const 
 	return modes;
 }
 
-static int ata_qc_wait_err(struct ata_queued_cmd *qc,
-			   struct completion *wait)
+struct ata_exec_internal_arg {
+	unsigned int err_mask;
+	struct ata_taskfile *tf;
+	struct completion *waiting;
+};
+
+int ata_qc_complete_internal(struct ata_queued_cmd *qc)
 {
-	int rc = 0;
+	struct ata_exec_internal_arg *arg = qc->private_data;
+	struct completion *waiting = arg->waiting;
 
-	if (wait_for_completion_timeout(wait, 30 * HZ) < 1) {
-		/* timeout handling */
-		unsigned int err_mask = ac_err_mask(ata_chk_status(qc->ap));
-
-		if (!err_mask) {
-			printk(KERN_WARNING "ata%u: slow completion (cmd %x)\n",
-			       qc->ap->id, qc->tf.command);
-		} else {
-			printk(KERN_WARNING "ata%u: qc timeout (cmd %x)\n",
-			       qc->ap->id, qc->tf.command);
-			rc = -EIO;
+	if (!(qc->err_mask & ~AC_ERR_DEV))
+		qc->ap->ops->tf_read(qc->ap, arg->tf);
+	arg->err_mask = qc->err_mask;
+	arg->waiting = NULL;
+	complete(waiting);
+
+	return 0;
+}
+
+/**
+ *	ata_exec_internal - execute libata internal command
+ *	@ap: Port to which the command is sent
+ *	@dev: Device to which the command is sent
+ *	@tf: Taskfile registers for the command and the result
+ *	@dma_dir: Data tranfer direction of the command
+ *	@buf: Data buffer of the command
+ *	@buflen: Length of data buffer
+ *
+ *	Executes libata internal command with timeout.  @tf contains
+ *	command on entry and result on return.  Timeout and error
+ *	conditions are reported via return value.  No recovery action
+ *	is taken after a command times out.  It's caller's duty to
+ *	clean up after timeout.
+ *
+ *	LOCKING:
+ *	None.  Should be called with kernel context, might sleep.
+ */
+
+static unsigned
+ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
+		  struct ata_taskfile *tf,
+		  int dma_dir, void *buf, unsigned int buflen)
+{
+	u8 command = tf->command;
+	struct ata_queued_cmd *qc;
+	DECLARE_COMPLETION(wait);
+	unsigned long flags;
+	struct ata_exec_internal_arg arg;
+
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
+
+	qc->tf = *tf;
+	qc->dma_dir = dma_dir;
+	if (dma_dir != DMA_NONE) {
+		ata_sg_init_one(qc, buf, buflen);
+		qc->nsect = buflen / ATA_SECT_SIZE;
+	}
+
+	arg.waiting = &wait;
+	arg.tf = tf;
+	qc->private_data = &arg;
+	qc->complete_fn = ata_qc_complete_internal;
+
+	if (ata_qc_issue(qc))
+		goto issue_fail;
+
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+	if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) {
+		spin_lock_irqsave(&ap->host_set->lock, flags);
+
+		/* We're racing with irq here.  If we lose, the
+		 * following test prevents us from completing the qc
+		 * again.  If completion irq occurs after here but
+		 * before the caller cleans up, it will result in a
+		 * spurious interrupt.  We can live with that.
+		 */
+		if (arg.waiting) {
+			qc->err_mask = AC_ERR_OTHER;
+			ata_qc_complete(qc);
+			printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n",
+			       ap->id, command);
 		}
 
-		ata_qc_complete(qc, err_mask);
+		spin_unlock_irqrestore(&ap->host_set->lock, flags);
 	}
 
-	return rc;
+	return arg.err_mask;
+
+ issue_fail:
+	ata_qc_free(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	return AC_ERR_OTHER;
 }
 
 /**
@@ -1099,9 +1174,8 @@ static void ata_dev_identify(struct ata_
 	u16 tmp;
 	unsigned long xfer_modes;
 	unsigned int using_edd;
-	DECLARE_COMPLETION(wait);
-	struct ata_queued_cmd *qc;
-	unsigned long flags;
+	struct ata_taskfile tf;
+	unsigned int err_mask;
 	int rc;
 
 	if (!ata_dev_present(dev)) {
@@ -1122,40 +1196,26 @@ static void ata_dev_identify(struct ata_
 
 	ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
 
-	qc = ata_qc_new_init(ap, dev);
-	BUG_ON(qc == NULL);
-
-	ata_sg_init_one(qc, dev->id, sizeof(dev->id));
-	qc->dma_dir = DMA_FROM_DEVICE;
-	qc->tf.protocol = ATA_PROT_PIO;
-	qc->nsect = 1;
-
 retry:
+	ata_tf_init(ap, &tf, device);
+
 	if (dev->class == ATA_DEV_ATA) {
-		qc->tf.command = ATA_CMD_ID_ATA;
+		tf.command = ATA_CMD_ID_ATA;
 		DPRINTK("do ATA identify\n");
 	} else {
-		qc->tf.command = ATA_CMD_ID_ATAPI;
+		tf.command = ATA_CMD_ID_ATAPI;
 		DPRINTK("do ATAPI identify\n");
 	}
 
-	qc->waiting = &wait;
-	qc->complete_fn = ata_qc_complete_noop;
+	tf.protocol = ATA_PROT_PIO;
 
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	rc = ata_qc_issue(qc);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+				     dev->id, sizeof(dev->id));
 
-	if (rc)
-		goto err_out;
-	else
-		ata_qc_wait_err(qc, &wait);
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	ap->ops->tf_read(ap, &qc->tf);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	if (err_mask) {
+		if (err_mask & ~AC_ERR_DEV)
+			goto err_out;
 
-	if (qc->tf.command & ATA_ERR) {
 		/*
 		 * arg!  EDD works for all test cases, but seems to return
 		 * the ATA signature for some ATAPI devices.  Until the
@@ -1168,13 +1228,9 @@ retry:
 		 * to have this problem.
 		 */
 		if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
-			u8 err = qc->tf.feature;
+			u8 err = tf.feature;
 			if (err & ATA_ABORTED) {
 				dev->class = ATA_DEV_ATAPI;
-				qc->cursg = 0;
-				qc->cursg_ofs = 0;
-				qc->cursect = 0;
-				qc->nsect = 1;
 				goto retry;
 			}
 		}
@@ -1444,11 +1500,23 @@ void __sata_phy_reset(struct ata_port *a
 	} while (time_before(jiffies, timeout));
 
 	/* TODO: phy layer with polling, timeouts, etc. */
-	if (sata_dev_present(ap))
+	sstatus = scr_read(ap, SCR_STATUS);
+	if (sata_dev_present(ap)) {
+		const char *speed;
+		u32 tmp;
+
+		tmp = (sstatus >> 4) & 0xf;
+		if (tmp & (1 << 0))
+			speed = "1.5";
+		else if (tmp & (1 << 1))
+			speed = "3.0";
+		else
+			speed = "<unknown>";
+		printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
+		       ap->id, speed, sstatus);
 		ata_port_probe(ap);
-	else {
-		sstatus = scr_read(ap, SCR_STATUS);
-		printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
+	} else {
+		printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n",
 		       ap->id, sstatus);
 		ata_port_disable(ap);
 	}
@@ -2071,7 +2139,7 @@ static void ata_pr_blacklisted(const str
 		ap->id, dev->devno);
 }
 
-static const char * ata_dma_blacklist [] = {
+static const char * const ata_dma_blacklist [] = {
 	"WDC AC11000H",
 	"WDC AC22100H",
 	"WDC AC32500H",
@@ -2266,34 +2334,23 @@ static int ata_choose_xfer_mode(const st
 
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 {
-	DECLARE_COMPLETION(wait);
-	struct ata_queued_cmd *qc;
-	int rc;
-	unsigned long flags;
+	struct ata_taskfile tf;
 
 	/* set up set-features taskfile */
 	DPRINTK("set features - xfer mode\n");
 
-	qc = ata_qc_new_init(ap, dev);
-	BUG_ON(qc == NULL);
-
-	qc->tf.command = ATA_CMD_SET_FEATURES;
-	qc->tf.feature = SETFEATURES_XFER;
-	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	qc->tf.protocol = ATA_PROT_NODATA;
-	qc->tf.nsect = dev->xfer_mode;
-
-	qc->waiting = &wait;
-	qc->complete_fn = ata_qc_complete_noop;
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	rc = ata_qc_issue(qc);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	ata_tf_init(ap, &tf, dev->devno);
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = SETFEATURES_XFER;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = dev->xfer_mode;
 
-	if (rc)
+	if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+		printk(KERN_ERR "ata%u: failed to set xfermode, disabled\n",
+		       ap->id);
 		ata_port_disable(ap);
-	else
-		ata_qc_wait_err(qc, &wait);
+	}
 
 	DPRINTK("EXIT\n");
 }
@@ -2308,41 +2365,25 @@ static void ata_dev_set_xfermode(struct 
 
 static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
 {
-	DECLARE_COMPLETION(wait);
-	struct ata_queued_cmd *qc;
-	unsigned long flags;
-	int rc;
-
-	qc = ata_qc_new_init(ap, dev);
-	BUG_ON(qc == NULL);
+	struct ata_taskfile tf;
 
-	ata_sg_init_one(qc, dev->id, sizeof(dev->id));
-	qc->dma_dir = DMA_FROM_DEVICE;
+	ata_tf_init(ap, &tf, dev->devno);
 
 	if (dev->class == ATA_DEV_ATA) {
-		qc->tf.command = ATA_CMD_ID_ATA;
+		tf.command = ATA_CMD_ID_ATA;
 		DPRINTK("do ATA identify\n");
 	} else {
-		qc->tf.command = ATA_CMD_ID_ATAPI;
+		tf.command = ATA_CMD_ID_ATAPI;
 		DPRINTK("do ATAPI identify\n");
 	}
 
-	qc->tf.flags |= ATA_TFLAG_DEVICE;
-	qc->tf.protocol = ATA_PROT_PIO;
-	qc->nsect = 1;
-
-	qc->waiting = &wait;
-	qc->complete_fn = ata_qc_complete_noop;
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	rc = ata_qc_issue(qc);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	tf.flags |= ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_PIO;
 
-	if (rc)
+	if (ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+			      dev->id, sizeof(dev->id)))
 		goto err_out;
 
-	ata_qc_wait_err(qc, &wait);
-
 	swap_buf_le16(dev->id, ATA_ID_WORDS);
 
 	ata_dump_id(dev);
@@ -2351,6 +2392,7 @@ static void ata_dev_reread_id(struct ata
 
 	return;
 err_out:
+	printk(KERN_ERR "ata%u: failed to reread ID, disabled\n", ap->id);
 	ata_port_disable(ap);
 }
 
@@ -2364,10 +2406,7 @@ err_out:
 
 static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
 {
-	DECLARE_COMPLETION(wait);
-	struct ata_queued_cmd *qc;
-	int rc;
-	unsigned long flags;
+	struct ata_taskfile tf;
 	u16 sectors = dev->id[6];
 	u16 heads   = dev->id[3];
 
@@ -2378,26 +2417,18 @@ static void ata_dev_init_params(struct a
 	/* set up init dev params taskfile */
 	DPRINTK("init dev params \n");
 
-	qc = ata_qc_new_init(ap, dev);
-	BUG_ON(qc == NULL);
-
-	qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
-	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	qc->tf.protocol = ATA_PROT_NODATA;
-	qc->tf.nsect = sectors;
-	qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
-
-	qc->waiting = &wait;
-	qc->complete_fn = ata_qc_complete_noop;
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	rc = ata_qc_issue(qc);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	ata_tf_init(ap, &tf, dev->devno);
+	tf.command = ATA_CMD_INIT_DEV_PARAMS;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = sectors;
+	tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
 
-	if (rc)
+	if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+		printk(KERN_ERR "ata%u: failed to init parameters, disabled\n",
+		       ap->id);
 		ata_port_disable(ap);
-	else
-		ata_qc_wait_err(qc, &wait);
+	}
 
 	DPRINTK("EXIT\n");
 }
@@ -2765,7 +2796,7 @@ skip_map:
  *	None.  (grabs host lock)
  */
 
-void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+void ata_poll_qc_complete(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned long flags;
@@ -2773,7 +2804,7 @@ void ata_poll_qc_complete(struct ata_que
 	spin_lock_irqsave(&ap->host_set->lock, flags);
 	ap->flags &= ~ATA_FLAG_NOINTR;
 	ata_irq_on(ap);
-	ata_qc_complete(qc, err_mask);
+	ata_qc_complete(qc);
 	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 }
 
@@ -2790,10 +2821,14 @@ void ata_poll_qc_complete(struct ata_que
 
 static unsigned long ata_pio_poll(struct ata_port *ap)
 {
+	struct ata_queued_cmd *qc;
 	u8 status;
 	unsigned int poll_state = HSM_ST_UNKNOWN;
 	unsigned int reg_state = HSM_ST_UNKNOWN;
 
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	assert(qc != NULL);
+
 	switch (ap->hsm_task_state) {
 	case HSM_ST:
 	case HSM_ST_POLL:
@@ -2813,6 +2848,7 @@ static unsigned long ata_pio_poll(struct
 	status = ata_chk_status(ap);
 	if (status & ATA_BUSY) {
 		if (time_after(jiffies, ap->pio_task_timeout)) {
+			qc->err_mask |= AC_ERR_ATA_BUS;
 			ap->hsm_task_state = HSM_ST_TMOUT;
 			return 0;
 		}
@@ -2847,29 +2883,31 @@ static int ata_pio_complete (struct ata_
 	 * msecs, then chk-status again.  If still busy, fall back to
 	 * HSM_ST_POLL state.
 	 */
-	drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
-	if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+	drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
+	if (drv_stat & ATA_BUSY) {
 		msleep(2);
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
-		if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+		drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
+		if (drv_stat & ATA_BUSY) {
 			ap->hsm_task_state = HSM_ST_LAST_POLL;
 			ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
 			return 0;
 		}
 	}
 
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	assert(qc != NULL);
+
 	drv_stat = ata_wait_idle(ap);
 	if (!ata_ok(drv_stat)) {
+		qc->err_mask |= __ac_err_mask(drv_stat);
 		ap->hsm_task_state = HSM_ST_ERR;
 		return 0;
 	}
 
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-	assert(qc != NULL);
-
 	ap->hsm_task_state = HSM_ST_IDLE;
 
-	ata_poll_qc_complete(qc, 0);
+	assert(qc->err_mask == 0);
+	ata_poll_qc_complete(qc);
 
 	/* another command may start at this point */
 
@@ -3177,6 +3215,7 @@ static void atapi_pio_bytes(struct ata_q
 err_out:
 	printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
 	      ap->id, dev->devno);
+	qc->err_mask |= AC_ERR_ATA_BUS;
 	ap->hsm_task_state = HSM_ST_ERR;
 }
 
@@ -3215,8 +3254,16 @@ static void ata_pio_block(struct ata_por
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 
+	/* check error */
+	if (status & (ATA_ERR | ATA_DF)) {
+		qc->err_mask |= AC_ERR_DEV;
+		ap->hsm_task_state = HSM_ST_ERR;
+		return;
+	}
+
+	/* transfer data if any */
 	if (is_atapi_taskfile(&qc->tf)) {
-		/* no more data to transfer or unsupported ATAPI command */
+		/* DRQ=0 means no more data to transfer */
 		if ((status & ATA_DRQ) == 0) {
 			ap->hsm_task_state = HSM_ST_LAST;
 			return;
@@ -3226,6 +3273,7 @@ static void ata_pio_block(struct ata_por
 	} else {
 		/* handle BSY=0, DRQ=0 as error */
 		if ((status & ATA_DRQ) == 0) {
+			qc->err_mask |= AC_ERR_ATA_BUS;
 			ap->hsm_task_state = HSM_ST_ERR;
 			return;
 		}
@@ -3243,9 +3291,14 @@ static void ata_pio_error(struct ata_por
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 
+	/* make sure qc->err_mask is available to 
+	 * know what's wrong and recover
+	 */
+	assert(qc->err_mask);
+
 	ap->hsm_task_state = HSM_ST_IDLE;
 
-	ata_poll_qc_complete(qc, AC_ERR_ATA_BUS);
+	ata_poll_qc_complete(qc);
 }
 
 static void ata_pio_task(void *_data)
@@ -3347,7 +3400,8 @@ static void ata_qc_timeout(struct ata_qu
 		       ap->id, qc->tf.command, drv_stat, host_stat);
 
 		/* complete taskfile transaction */
-		ata_qc_complete(qc, ac_err_mask(drv_stat));
+		qc->err_mask |= ac_err_mask(drv_stat);
+		ata_qc_complete(qc);
 		break;
 	}
 
@@ -3446,15 +3500,10 @@ struct ata_queued_cmd *ata_qc_new_init(s
 	return qc;
 }
 
-int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask)
-{
-	return 0;
-}
-
 static void __ata_qc_complete(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	unsigned int tag, do_clear = 0;
+	unsigned int tag;
 
 	qc->flags = 0;
 	tag = qc->tag;
@@ -3462,17 +3511,8 @@ static void __ata_qc_complete(struct ata
 		if (tag == ap->active_tag)
 			ap->active_tag = ATA_TAG_POISON;
 		qc->tag = ATA_TAG_POISON;
-		do_clear = 1;
-	}
-
-	if (qc->waiting) {
-		struct completion *waiting = qc->waiting;
-		qc->waiting = NULL;
-		complete(waiting);
-	}
-
-	if (likely(do_clear))
 		clear_bit(tag, &ap->qactive);
+	}
 }
 
 /**
@@ -3488,7 +3528,6 @@ static void __ata_qc_complete(struct ata
 void ata_qc_free(struct ata_queued_cmd *qc)
 {
 	assert(qc != NULL);	/* ata_qc_from_tag _might_ return NULL */
-	assert(qc->waiting == NULL);	/* nothing should be waiting */
 
 	__ata_qc_complete(qc);
 }
@@ -3505,7 +3544,7 @@ void ata_qc_free(struct ata_queued_cmd *
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+void ata_qc_complete(struct ata_queued_cmd *qc)
 {
 	int rc;
 
@@ -3522,7 +3561,7 @@ void ata_qc_complete(struct ata_queued_c
 	qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
 	/* call completion callback */
-	rc = qc->complete_fn(qc, err_mask);
+	rc = qc->complete_fn(qc);
 
 	/* if callback indicates not to complete command (non-zero),
 	 * return immediately
@@ -3960,7 +3999,8 @@ inline unsigned int ata_host_intr (struc
 		ap->ops->irq_clear(ap);
 
 		/* complete taskfile transaction */
-		ata_qc_complete(qc, ac_err_mask(status));
+		qc->err_mask |= ac_err_mask(status);
+		ata_qc_complete(qc);
 		break;
 
 	default:
@@ -4054,13 +4094,17 @@ static void atapi_packet_task(void *_dat
 
 	/* sleep-wait for BSY to clear */
 	DPRINTK("busy wait\n");
-	if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
-		goto err_out_status;
+	if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
+		qc->err_mask |= AC_ERR_ATA_BUS;
+		goto err_out;
+	}
 
 	/* make sure DRQ is set */
 	status = ata_chk_status(ap);
-	if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)
+	if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
+		qc->err_mask |= AC_ERR_ATA_BUS;
 		goto err_out;
+	}
 
 	/* send SCSI cdb */
 	DPRINTK("send cdb\n");
@@ -4092,10 +4136,8 @@ static void atapi_packet_task(void *_dat
 
 	return;
 
-err_out_status:
-	status = ata_chk_status(ap);
 err_out:
-	ata_poll_qc_complete(qc, __ac_err_mask(status));
+	ata_poll_qc_complete(qc);
 }
 
 
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 2282c04..e0439be 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -418,7 +418,7 @@ void ata_to_sense_error(unsigned id, u8 
 	int i;
 
 	/* Based on the 3ware driver translation table */
-	static unsigned char sense_table[][4] = {
+	static const unsigned char sense_table[][4] = {
 		/* BBD|ECC|ID|MAR */
 		{0xd1, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
 		/* BBD|ECC|ID */
@@ -449,7 +449,7 @@ void ata_to_sense_error(unsigned id, u8 
 		{0x80, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Block marked bad		  Medium error, unrecovered read error
 		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
 	};
-	static unsigned char stat_table[][4] = {
+	static const unsigned char stat_table[][4] = {
 		/* Must be first because BUSY means no other bits valid */
 		{0x80, 		ABORTED_COMMAND, 0x47, 0x00},	// Busy, fake parity for now
 		{0x20, 		HARDWARE_ERROR,  0x00, 0x00}, 	// Device fault
@@ -1203,12 +1203,11 @@ nothing_to_do:
 	return 1;
 }
 
-static int ata_scsi_qc_complete(struct ata_queued_cmd *qc,
-				unsigned int err_mask)
+static int ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	u8 *cdb = cmd->cmnd;
- 	int need_sense = (err_mask != 0);
+ 	int need_sense = (qc->err_mask != 0);
 
 	/* For ATA pass thru (SAT) commands, generate a sense block if
 	 * user mandated it or if there's an error.  Note that if we
@@ -1532,7 +1531,7 @@ unsigned int ata_scsiop_inq_80(struct at
 	return 0;
 }
 
-static const char *inq_83_str = "Linux ATA-SCSI simulator";
+static const char * const inq_83_str = "Linux ATA-SCSI simulator";
 
 /**
  *	ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity
@@ -1955,9 +1954,9 @@ void ata_scsi_badcmd(struct scsi_cmnd *c
 	done(cmd);
 }
 
-static int atapi_sense_complete(struct ata_queued_cmd *qc,unsigned int err_mask)
+static int atapi_sense_complete(struct ata_queued_cmd *qc)
 {
-	if (err_mask && ((err_mask & AC_ERR_DEV) == 0))
+	if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0))
 		/* FIXME: not quite right; we don't want the
 		 * translation of taskfile registers into
 		 * a sense descriptors, since that's only
@@ -2015,15 +2014,18 @@ static void atapi_request_sense(struct a
 
 	qc->complete_fn = atapi_sense_complete;
 
-	if (ata_qc_issue(qc))
-		ata_qc_complete(qc, AC_ERR_OTHER);
+	if (ata_qc_issue(qc)) {
+		qc->err_mask |= AC_ERR_OTHER;
+		ata_qc_complete(qc);
+	}
 
 	DPRINTK("EXIT\n");
 }
 
-static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+static int atapi_qc_complete(struct ata_queued_cmd *qc)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
+	unsigned int err_mask = qc->err_mask;
 
 	VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
 
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 8ebaa69..251e53b 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -39,7 +39,6 @@ struct ata_scsi_args {
 
 /* libata-core.c */
 extern int atapi_enabled;
-extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask);
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 				      struct ata_device *dev);
 extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index f557f17..e8df0c9 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -464,14 +464,12 @@ static inline unsigned int adma_intr_pkt
 			continue;
 		qc = ata_qc_from_tag(ap, ap->active_tag);
 		if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
-			unsigned int err_mask = 0;
-
 			if ((status & (aPERR | aPSD | aUIRQ)))
-				err_mask = AC_ERR_OTHER;
+				qc->err_mask |= AC_ERR_OTHER;
 			else if (pp->pkt[0] != cDONE)
-				err_mask = AC_ERR_OTHER;
+				qc->err_mask |= AC_ERR_OTHER;
 
-			ata_qc_complete(qc, err_mask);
+			ata_qc_complete(qc);
 		}
 	}
 	return handled;
@@ -501,7 +499,8 @@ static inline unsigned int adma_intr_mmi
 		
 				/* complete taskfile transaction */
 				pp->state = adma_state_idle;
-				ata_qc_complete(qc, ac_err_mask(status));
+				qc->err_mask |= ac_err_mask(status);
+				ata_qc_complete(qc);
 				handled = 1;
 			}
 		}
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 9321cdf..b2bf16a 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -431,7 +431,7 @@ static const struct ata_port_operations 
 	.host_stop		= mv_host_stop,
 };
 
-static struct ata_port_info mv_port_info[] = {
+static const struct ata_port_info mv_port_info[] = {
 	{  /* chip_504x */
 		.sht		= &mv_sht,
 		.host_flags	= MV_COMMON_FLAGS,
@@ -1243,8 +1243,10 @@ static void mv_host_intr(struct ata_host
 				VPRINTK("port %u IRQ found for qc, "
 					"ata_status 0x%x\n", port,ata_status);
 				/* mark qc status appropriately */
-				if (!(qc->tf.ctl & ATA_NIEN))
-					ata_qc_complete(qc, err_mask);
+				if (!(qc->tf.ctl & ATA_NIEN)) {
+					qc->err_mask |= err_mask;
+					ata_qc_complete(qc);
+				}
 			}
 		}
 	}
@@ -1865,7 +1867,8 @@ static void mv_eng_timeout(struct ata_po
 	 	 */
 		spin_lock_irqsave(&ap->host_set->lock, flags);
 		qc->scsidone = scsi_finish_command;
-		ata_qc_complete(qc, AC_ERR_OTHER);
+		qc->err_mask |= AC_ERR_OTHER;
+		ata_qc_complete(qc);
 		spin_unlock_irqrestore(&ap->host_set->lock, flags);
 	}
 }
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 2691625..da7fa04 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -161,7 +161,7 @@ static const struct ata_port_operations 
 	.host_stop		= ata_pci_host_stop,
 };
 
-static struct ata_port_info pdc_port_info[] = {
+static const struct ata_port_info pdc_port_info[] = {
 	/* board_2037x */
 	{
 		.sht		= &pdc_ata_sht,
@@ -401,7 +401,8 @@ static void pdc_eng_timeout(struct ata_p
 	case ATA_PROT_NODATA:
 		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
 		drv_stat = ata_wait_idle(ap);
-		ata_qc_complete(qc, __ac_err_mask(drv_stat));
+		qc->err_mask |= __ac_err_mask(drv_stat);
+		ata_qc_complete(qc);
 		break;
 
 	default:
@@ -410,7 +411,8 @@ static void pdc_eng_timeout(struct ata_p
 		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
 		       ap->id, qc->tf.command, drv_stat);
 
-		ata_qc_complete(qc, ac_err_mask(drv_stat));
+		qc->err_mask |= ac_err_mask(drv_stat);
+		ata_qc_complete(qc);
 		break;
 	}
 
@@ -422,21 +424,21 @@ out:
 static inline unsigned int pdc_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc)
 {
-	unsigned int handled = 0, err_mask = 0;
+	unsigned int handled = 0;
 	u32 tmp;
 	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
 
 	tmp = readl(mmio);
 	if (tmp & PDC_ERR_MASK) {
-		err_mask = AC_ERR_DEV;
+		qc->err_mask |= AC_ERR_DEV;
 		pdc_reset_port(ap);
 	}
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
-		err_mask |= ac_err_mask(ata_wait_idle(ap));
-		ata_qc_complete(qc, err_mask);
+		qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+		ata_qc_complete(qc);
 		handled = 1;
 		break;
 
@@ -703,7 +705,7 @@ static int pdc_ata_init_one (struct pci_
 		probe_ent->port[3].scr_addr = base + 0x700;
 		break;
 	case board_2037x:
-       		probe_ent->n_ports = 2;
+		probe_ent->n_ports = 2;
 		break;
 	case board_20619:
 		probe_ent->n_ports = 4;
@@ -713,7 +715,7 @@ static int pdc_ata_init_one (struct pci_
 
 		probe_ent->port[2].scr_addr = base + 0x600;
 		probe_ent->port[3].scr_addr = base + 0x700;
-                break;
+		break;
 	default:
 		BUG();
 		break;
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index a8987f5..de05e28 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -170,7 +170,7 @@ static const struct ata_port_operations 
 	.bmdma_status		= qs_bmdma_status,
 };
 
-static struct ata_port_info qs_port_info[] = {
+static const struct ata_port_info qs_port_info[] = {
 	/* board_2068_idx */
 	{
 		.sht		= &qs_ata_sht,
@@ -409,8 +409,8 @@ static inline unsigned int qs_intr_pkt(s
 					case 3: /* device error */
 						pp->state = qs_state_idle;
 						qs_enter_reg_mode(qc->ap);
-						ata_qc_complete(qc,
-							ac_err_mask(sDST));
+						qc->err_mask |= ac_err_mask(sDST);
+						ata_qc_complete(qc);
 						break;
 					default:
 						break;
@@ -447,7 +447,8 @@ static inline unsigned int qs_intr_mmio(
 
 				/* complete taskfile transaction */
 				pp->state = qs_state_idle;
-				ata_qc_complete(qc, ac_err_mask(status));
+				qc->err_mask |= ac_err_mask(status);
+				ata_qc_complete(qc);
 				handled = 1;
 			}
 		}
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 3609186..d205348 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -176,7 +176,7 @@ static const struct ata_port_operations 
 	.host_stop		= ata_pci_host_stop,
 };
 
-static struct ata_port_info sil_port_info[] = {
+static const struct ata_port_info sil_port_info[] = {
 	/* sil_3112 */
 	{
 		.sht		= &sil_sht,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index e0d6f19..a0ad3ed 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -654,7 +654,8 @@ static void sil24_eng_timeout(struct ata
 	 */
 	printk(KERN_ERR "ata%u: command timeout\n", ap->id);
 	qc->scsidone = scsi_finish_command;
-	ata_qc_complete(qc, AC_ERR_OTHER);
+	qc->err_mask |= AC_ERR_OTHER;
+	ata_qc_complete(qc);
 
 	sil24_reset_controller(ap);
 }
@@ -711,8 +712,10 @@ static void sil24_error_intr(struct ata_
 		sil24_reset_controller(ap);
 	}
 
-	if (qc)
-		ata_qc_complete(qc, err_mask);
+	if (qc) {
+		qc->err_mask |= err_mask;
+		ata_qc_complete(qc);
+	}
 }
 
 static inline void sil24_host_intr(struct ata_port *ap)
@@ -734,8 +737,10 @@ static inline void sil24_host_intr(struc
 		 */
 		sil24_update_tf(ap);
 
-		if (qc)
-			ata_qc_complete(qc, ac_err_mask(pp->tf.command));
+		if (qc) {
+			qc->err_mask |= ac_err_mask(pp->tf.command);
+			ata_qc_complete(qc);
+		}
 	} else
 		sil24_error_intr(ap, slot_stat);
 }
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index ac7b0d8..94b253b 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -215,7 +215,7 @@ static const struct ata_port_operations 
 	.host_stop		= pdc20621_host_stop,
 };
 
-static struct ata_port_info pdc_port_info[] = {
+static const struct ata_port_info pdc_port_info[] = {
 	/* board_20621 */
 	{
 		.sht		= &pdc_sata_sht,
@@ -719,7 +719,8 @@ static inline unsigned int pdc20621_host
 			VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 			/* get drive status; clear intr; complete txn */
-			ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
+			qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+			ata_qc_complete(qc);
 			pdc20621_pop_hdma(qc);
 		}
 
@@ -757,7 +758,8 @@ static inline unsigned int pdc20621_host
 			VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 			/* get drive status; clear intr; complete txn */
-			ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
+			qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+			ata_qc_complete(qc);
 			pdc20621_pop_hdma(qc);
 		}
 		handled = 1;
@@ -767,7 +769,8 @@ static inline unsigned int pdc20621_host
 
 		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
 		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
-		ata_qc_complete(qc, ac_err_mask(status));
+		qc->err_mask |= ac_err_mask(status);
+		ata_qc_complete(qc);
 		handled = 1;
 
 	} else {
@@ -882,7 +885,8 @@ static void pdc_eng_timeout(struct ata_p
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
 		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
-		ata_qc_complete(qc, __ac_err_mask(ata_wait_idle(ap)));
+		qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
+		ata_qc_complete(qc);
 		break;
 
 	default:
@@ -891,7 +895,8 @@ static void pdc_eng_timeout(struct ata_p
 		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
 		       ap->id, qc->tf.command, drv_stat);
 
-		ata_qc_complete(qc, ac_err_mask(drv_stat));
+		qc->err_mask |= ac_err_mask(drv_stat);
+		ata_qc_complete(qc);
 		break;
 	}
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 41ea7db..e828e17 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -136,6 +136,8 @@ enum {
 	ATA_TMOUT_BOOT_QUICK	= 7 * HZ,	/* hueristic */
 	ATA_TMOUT_CDB		= 30 * HZ,
 	ATA_TMOUT_CDB_QUICK	= 5 * HZ,
+	ATA_TMOUT_INTERNAL	= 30 * HZ,
+	ATA_TMOUT_INTERNAL_QUICK = 5 * HZ,
 
 	/* ATA bus states */
 	BUS_UNKNOWN		= 0,
@@ -195,7 +197,7 @@ struct ata_port;
 struct ata_queued_cmd;
 
 /* typedefs */
-typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, unsigned int err_mask);
+typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
 
 struct ata_ioports {
 	unsigned long		cmd_addr;
@@ -280,9 +282,9 @@ struct ata_queued_cmd {
 	/* DO NOT iterate over __sg manually, use ata_for_each_sg() */
 	struct scatterlist	*__sg;
 
-	ata_qc_cb_t		complete_fn;
+	unsigned int		err_mask;
 
-	struct completion	*waiting;
+	ata_qc_cb_t		complete_fn;
 
 	void			*private_data;
 };
@@ -331,8 +333,6 @@ struct ata_port {
 
 	u8			ctl;	/* cache of ATA control register */
 	u8			last_ctl;	/* Cache last written value */
-	unsigned int		bus_state;
-	unsigned int		port_state;
 	unsigned int		pio_mask;
 	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
@@ -478,7 +478,7 @@ extern void ata_bmdma_start (struct ata_
 extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
 extern u8   ata_bmdma_status(struct ata_port *ap);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
-extern void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask);
+extern void ata_qc_complete(struct ata_queued_cmd *qc);
 extern void ata_eng_timeout(struct ata_port *ap);
 extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd,
 			      void (*done)(struct scsi_cmnd *));
@@ -670,6 +670,7 @@ static inline void ata_qc_reinit(struct 
 	qc->cursect = qc->cursg = qc->cursg_ofs = 0;
 	qc->nsect = 0;
 	qc->nbytes = qc->curbytes = 0;
+	qc->err_mask = 0;
 
 	ata_tf_init(qc->ap, &qc->tf, qc->dev->devno);
 }

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

* [git patches] 2.6.x libata updates
@ 2005-11-11 16:23 Jeff Garzik
  0 siblings, 0 replies; 50+ messages in thread
From: Jeff Garzik @ 2005-11-11 16:23 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-ide, linux-kernel


Please pull from 'upstream-linus' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

to receive the following updates:

 drivers/scsi/ahci.c         |    2 +-
 drivers/scsi/ata_piix.c     |    2 +-
 drivers/scsi/libata-core.c  |    2 ++
 drivers/scsi/libata-scsi.c  |    2 ++
 drivers/scsi/pdc_adma.c     |    2 +-
 drivers/scsi/sata_mv.c      |    4 +++-
 drivers/scsi/sata_nv.c      |    2 +-
 drivers/scsi/sata_promise.c |    2 +-
 drivers/scsi/sata_qstor.c   |    2 +-
 drivers/scsi/sata_sil.c     |    2 +-
 drivers/scsi/sata_sil24.c   |    2 +-
 drivers/scsi/sata_sis.c     |    2 +-
 drivers/scsi/sata_svw.c     |    2 +-
 drivers/scsi/sata_sx4.c     |    2 +-
 drivers/scsi/sata_uli.c     |    2 +-
 drivers/scsi/sata_via.c     |    2 +-
 drivers/scsi/sata_vsc.c     |    2 +-
 include/linux/libata.h      |    2 ++
 18 files changed, 23 insertions(+), 15 deletions(-)

Alan Cox:
      libata: Note a nasty ATA quirk
      libata: propogate host private data from probe function

Andrew Morton:
      libata.h needs dma-mapping.h

Jeff Garzik:
      [libata] constify PCI ID table in several drivers
      [libata sata_mv] add Adaptec 1420SA PCI ID

diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 10c470e..57ef7ae 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -255,7 +255,7 @@ static struct ata_port_info ahci_port_in
 	},
 };
 
-static struct pci_device_id ahci_pci_tbl[] = {
+static const struct pci_device_id ahci_pci_tbl[] = {
 	{ PCI_VENDOR_ID_INTEL, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ICH6 */
 	{ PCI_VENDOR_ID_INTEL, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index a1bd8d9..855428f 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -95,7 +95,7 @@ static void piix_set_dmamode (struct ata
 
 static unsigned int in_module_init = 1;
 
-static struct pci_device_id piix_pci_tbl[] = {
+static const struct pci_device_id piix_pci_tbl[] = {
 #ifdef ATA_ENABLE_PATA
 	{ 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata },
 	{ 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index a74b407..e51d9a8 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -4563,6 +4563,7 @@ ata_pci_init_native_mode(struct pci_dev 
 
 	probe_ent->irq = pdev->irq;
 	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->private_data = port[0]->private_data;
 
 	if (ports & ATA_PORT_PRIMARY) {
 		probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
@@ -4599,6 +4600,7 @@ static struct ata_probe_ent *ata_pci_ini
 	probe_ent->legacy_mode = 1;
 	probe_ent->n_ports = 1;
 	probe_ent->hard_port_no = port_num;
+	probe_ent->private_data = port->private_data;
 
 	switch(port_num)
 	{
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index bb30fcd..7e37f48 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -1129,6 +1129,8 @@ static unsigned int ata_scsi_rw_xlat(str
 		 * length 0 means transfer 0 block of data.
 		 * However, for ATA R/W commands, sector count 0 means
 		 * 256 or 65536 sectors, not 0 sectors as in SCSI.
+		 *
+		 * WARNING: one or two older ATA drives treat 0 as 0...
 		 */
 		goto nothing_to_do;
 
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index 78b4ff1..f557f17 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -190,7 +190,7 @@ static struct ata_port_info adma_port_in
 	},
 };
 
-static struct pci_device_id adma_ata_pci_tbl[] = {
+static const struct pci_device_id adma_ata_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PDC, 0x1841, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_1841_idx },
 
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 93d5523..257c128 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -349,7 +349,7 @@ static struct ata_port_info mv_port_info
 	},
 };
 
-static struct pci_device_id mv_pci_tbl[] = {
+static const struct pci_device_id mv_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x},
 	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x},
 	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_508x},
@@ -359,6 +359,8 @@ static struct pci_device_id mv_pci_tbl[]
 	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x},
 	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x},
 	{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x},
+
+	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x0241), 0, 0, chip_604x},
 	{}			/* terminate list */
 };
 
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 37a4fae..4954896 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -137,7 +137,7 @@ enum nv_host_type
 	CK804
 };
 
-static struct pci_device_id nv_pci_tbl[] = {
+static const struct pci_device_id nv_pci_tbl[] = {
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE2 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 9edc9d9..242d906 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -193,7 +193,7 @@ static struct ata_port_info pdc_port_inf
 	},
 };
 
-static struct pci_device_id pdc_ata_pci_tbl[] = {
+static const struct pci_device_id pdc_ata_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_2037x },
 	{ PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index d274ab2..b2f6324 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -184,7 +184,7 @@ static struct ata_port_info qs_port_info
 	},
 };
 
-static struct pci_device_id qs_ata_pci_tbl[] = {
+static const struct pci_device_id qs_ata_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PDC, 0x2068, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_2068_idx },
 
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index d0e3c3c..3609186 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -87,7 +87,7 @@ static void sil_scr_write (struct ata_po
 static void sil_post_set_mode (struct ata_port *ap);
 
 
-static struct pci_device_id sil_pci_tbl[] = {
+static const struct pci_device_id sil_pci_tbl[] = {
 	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
 	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
 	{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 4682a50..d3198d9 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -240,7 +240,7 @@ static void sil24_port_stop(struct ata_p
 static void sil24_host_stop(struct ata_host_set *host_set);
 static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 
-static struct pci_device_id sil24_pci_tbl[] = {
+static const struct pci_device_id sil24_pci_tbl[] = {
 	{ 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
 	{ 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 },
 	{ 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index 42d7c4e..32e1262 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -67,7 +67,7 @@ static int sis_init_one (struct pci_dev 
 static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 
-static struct pci_device_id sis_pci_tbl[] = {
+static const struct pci_device_id sis_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
 	{ PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
 	{ PCI_VENDOR_ID_SI, 0x182, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 9895d1c..57e5a9d 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -466,7 +466,7 @@ err_out:
  * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA
  * controller
  * */
-static struct pci_device_id k2_sata_pci_tbl[] = {
+static const struct pci_device_id k2_sata_pci_tbl[] = {
 	{ 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index d5a3878..b4bbe48 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -229,7 +229,7 @@ static struct ata_port_info pdc_port_inf
 
 };
 
-static struct pci_device_id pdc_sata_pci_tbl[] = {
+static const struct pci_device_id pdc_sata_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PROMISE, 0x6622, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20621 },
 	{ }	/* terminate list */
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index cf0baaa..b2422a0 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -55,7 +55,7 @@ static int uli_init_one (struct pci_dev 
 static u32 uli_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 
-static struct pci_device_id uli_pci_tbl[] = {
+static const struct pci_device_id uli_pci_tbl[] = {
 	{ PCI_VENDOR_ID_AL, 0x5289, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5289 },
 	{ PCI_VENDOR_ID_AL, 0x5287, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5287 },
 	{ PCI_VENDOR_ID_AL, 0x5281, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5281 },
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index ab19d2b..c762156 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -75,7 +75,7 @@ static int svia_init_one (struct pci_dev
 static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 
-static struct pci_device_id svia_pci_tbl[] = {
+static const struct pci_device_id svia_pci_tbl[] = {
 	{ 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
 	{ 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 },
 
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index ce8a2fd..77a6e4b 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -400,7 +400,7 @@ err_out:
  * 0x8086/0x3200 is the Intel 31244, which is supposed to be identical
  * compatibility is untested as of yet
  */
-static struct pci_device_id vsc_sata_pci_tbl[] = {
+static const struct pci_device_id vsc_sata_pci_tbl[] = {
 	{ 0x1725, 0x7174, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
 	{ 0x8086, 0x3200, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
 	{ }
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 6f07522..1464a75 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <asm/io.h>
 #include <linux/ata.h>
 #include <linux/workqueue.h>
@@ -404,6 +405,7 @@ struct ata_port_info {
 	unsigned long		mwdma_mask;
 	unsigned long		udma_mask;
 	const struct ata_port_operations *port_ops;
+	void 			*private_data;
 };
 
 struct ata_timing {

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

* Re: [git patches] 2.6.x libata updates
  2005-10-31  0:58             ` Linus Torvalds
  2005-10-31  2:35               ` Rob Landley
  2005-10-31  2:52               ` Rob Landley
@ 2005-11-10  0:36               ` Matthias Urlichs
  2 siblings, 0 replies; 50+ messages in thread
From: Matthias Urlichs @ 2005-11-10  0:36 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ide

Hi, Linus Torvalds wrote:

> I have to say that the bk->cvs gateway is actually a very impressive 
> linearization, and I don't even know how it did it.

That's easy -- it found the longest path from A to B and generated patches
between each step.

Looking at the latest tree with gitk, I'd guess that the previous rate
of roughly 50% is no longer achievable; linearizing would aggregate
some large chunks of patch-series and subtree merges (no surprise there).

-- 
Matthias Urlichs   |   {M:U} IT Design @ m-u-it.de   |  smurf@smurf.noris.de
Disclaimer: The quote was selected randomly. Really. | http://smurf.noris.de
 - -
Automobile, n.:
	A four-wheeled vehicle that runs up hills and down pedestrians.



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

* [git patches] 2.6.x libata updates
@ 2005-11-09  6:54 Jeff Garzik
  0 siblings, 0 replies; 50+ messages in thread
From: Jeff Garzik @ 2005-11-09  6:54 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-ide, linux-kernel


Please pull from 'upstream-linus' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

to receive the following minor updates, and a fix:

 drivers/scsi/ahci.c         |    4 ++--
 drivers/scsi/ata_piix.c     |    3 +--
 drivers/scsi/libata-core.c  |   11 +++++------
 drivers/scsi/libata-scsi.c  |    9 +++++----
 drivers/scsi/pdc_adma.c     |    3 +--
 drivers/scsi/sata_mv.c      |    4 ++--
 drivers/scsi/sata_nv.c      |    3 +--
 drivers/scsi/sata_promise.c |    4 ++--
 drivers/scsi/sata_qstor.c   |    3 +--
 drivers/scsi/sata_sil.c     |    3 +--
 drivers/scsi/sata_sil24.c   |    4 ++--
 drivers/scsi/sata_sis.c     |    3 +--
 drivers/scsi/sata_svw.c     |    3 +--
 drivers/scsi/sata_sx4.c     |    4 ++--
 drivers/scsi/sata_uli.c     |    3 +--
 drivers/scsi/sata_via.c     |    3 +--
 drivers/scsi/sata_vsc.c     |    3 +--
 include/linux/libata.h      |    6 +++---
 18 files changed, 33 insertions(+), 43 deletions(-)

Albert Lee:
      libata: if condition fix for ata_dev_identify()

Jeff Garzik:
      [libata] eliminate use of drivers/scsi/scsi.h compatibility header/defines
      Merge branch 'master'

Randy Dunlap:
      libata kernel-doc fixes

diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 4612312..10c470e 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -42,8 +42,8 @@
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
 #include <asm/io.h>
 
@@ -196,7 +196,7 @@ static u8 ahci_check_status(struct ata_p
 static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
 static void ahci_remove_one (struct pci_dev *pdev);
 
-static Scsi_Host_Template ahci_sht = {
+static struct scsi_host_template ahci_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 7f8aa1b..a1bd8d9 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -46,7 +46,6 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
@@ -128,7 +127,7 @@ static struct pci_driver piix_pci_driver
 	.remove			= ata_pci_remove_one,
 };
 
-static Scsi_Host_Template piix_sht = {
+static struct scsi_host_template piix_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 1c1a7ca..a74b407 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -51,8 +51,8 @@
 #include <linux/jiffies.h>
 #include <linux/scatterlist.h>
 #include <scsi/scsi.h>
-#include "scsi.h"
 #include "scsi_priv.h"
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 #include <asm/io.h>
@@ -1144,7 +1144,7 @@ retry:
 		 * ATA software reset (SRST, the default) does not appear
 		 * to have this problem.
 		 */
-		if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) {
+		if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
 			u8 err = qc->tf.feature;
 			if (err & ATA_ABORTED) {
 				dev->class = ATA_DEV_ATAPI;
@@ -2713,7 +2713,7 @@ static int ata_sg_setup(struct ata_queue
 /**
  *	ata_poll_qc_complete - turn irq back on and finish qc
  *	@qc: Command to complete
- *	@drv_stat: ATA status register content
+ *	@err_mask: ATA status register content
  *
  *	LOCKING:
  *	None.  (grabs host lock)
@@ -2747,7 +2747,6 @@ static unsigned long ata_pio_poll(struct
 	u8 status;
 	unsigned int poll_state = HSM_ST_UNKNOWN;
 	unsigned int reg_state = HSM_ST_UNKNOWN;
-	const unsigned int tmout_state = HSM_ST_TMOUT;
 
 	switch (ap->hsm_task_state) {
 	case HSM_ST:
@@ -2768,7 +2767,7 @@ static unsigned long ata_pio_poll(struct
 	status = ata_chk_status(ap);
 	if (status & ATA_BUSY) {
 		if (time_after(jiffies, ap->pio_task_timeout)) {
-			ap->hsm_task_state = tmout_state;
+			ap->hsm_task_state = HSM_ST_TMOUT;
 			return 0;
 		}
 		ap->hsm_task_state = poll_state;
@@ -3478,7 +3477,7 @@ void ata_qc_free(struct ata_queued_cmd *
 /**
  *	ata_qc_complete - Complete an active ATA command
  *	@qc: Command to complete
- *	@drv_stat: ATA Status register contents
+ *	@err_mask: ATA Status register contents
  *
  *	Indicate to the mid and upper layers that an ATA
  *	command has completed, with either an ok or not-ok status.
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index eb604b0..bb30fcd 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -37,9 +37,9 @@
 #include <linux/blkdev.h>
 #include <linux/spinlock.h>
 #include <scsi/scsi.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
+#include <scsi/scsi_request.h>
 #include <linux/libata.h>
 #include <linux/hdreg.h>
 #include <asm/uaccess.h>
@@ -131,7 +131,7 @@ int ata_std_bios_param(struct scsi_devic
 
 /**
  *	ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl
- *	@dev: Device to whom we are issuing command
+ *	@scsidev: Device to which we are issuing command
  *	@arg: User provided data for issuing command
  *
  *	LOCKING:
@@ -217,7 +217,7 @@ error:
 
 /**
  *	ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl
- *	@dev: Device to whom we are issuing command
+ *	@scsidev: Device to which we are issuing command
  *	@arg: User provided data for issuing command
  *
  *	LOCKING:
@@ -416,6 +416,7 @@ void ata_dump_status(unsigned id, struct
 
 /**
  *	ata_to_sense_error - convert ATA error to SCSI error
+ *	@id: ATA device number
  *	@drv_stat: value contained in ATA status register
  *	@drv_err: value contained in ATA error register
  *	@sk: the sense key we'll fill out
@@ -2231,7 +2232,7 @@ ata_scsi_map_proto(u8 byte1)
 /**
  *	ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
  *	@qc: command structure to be initialized
- *	@cmd: SCSI command to convert
+ *	@scsicmd: SCSI command to convert
  *
  *	Handles either 12 or 16-byte versions of the CDB.
  *
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index a50588c..78b4ff1 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -41,7 +41,6 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <asm/io.h>
 #include <linux/libata.h>
@@ -139,7 +138,7 @@ static u8 adma_bmdma_status(struct ata_p
 static void adma_irq_clear(struct ata_port *ap);
 static void adma_eng_timeout(struct ata_port *ap);
 
-static Scsi_Host_Template adma_ata_sht = {
+static struct scsi_host_template adma_ata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 0f469e3..93d5523 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -30,8 +30,8 @@
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
 #include <asm/io.h>
 
@@ -270,7 +270,7 @@ static irqreturn_t mv_interrupt(int irq,
 static void mv_eng_timeout(struct ata_port *ap);
 static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 
-static Scsi_Host_Template mv_sht = {
+static struct scsi_host_template mv_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index d573888..37a4fae 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -62,7 +62,6 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
@@ -219,7 +218,7 @@ static struct pci_driver nv_pci_driver =
 	.remove			= ata_pci_remove_one,
 };
 
-static Scsi_Host_Template nv_sht = {
+static struct scsi_host_template nv_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index b41c977..9edc9d9 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -39,8 +39,8 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
 #include <asm/io.h>
 #include "sata_promise.h"
@@ -94,7 +94,7 @@ static void pdc_irq_clear(struct ata_por
 static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
 
 
-static Scsi_Host_Template pdc_ata_sht = {
+static struct scsi_host_template pdc_ata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index 65502c1..d274ab2 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -36,7 +36,6 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <asm/io.h>
 #include <linux/libata.h>
@@ -128,7 +127,7 @@ static u8 qs_bmdma_status(struct ata_por
 static void qs_irq_clear(struct ata_port *ap);
 static void qs_eng_timeout(struct ata_port *ap);
 
-static Scsi_Host_Template qs_ata_sht = {
+static struct scsi_host_template qs_ata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 435f7e0..d0e3c3c 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -42,7 +42,6 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
@@ -131,7 +130,7 @@ static struct pci_driver sil_pci_driver 
 	.remove			= ata_pci_remove_one,
 };
 
-static Scsi_Host_Template sil_sht = {
+static struct scsi_host_template sil_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index e6c8e89..4682a50 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -37,7 +37,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
 #include <scsi/scsi_host.h>
-#include "scsi.h"
+#include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
 #include <asm/io.h>
 
@@ -255,7 +255,7 @@ static struct pci_driver sil24_pci_drive
 	.remove			= ata_pci_remove_one, /* safe? */
 };
 
-static Scsi_Host_Template sil24_sht = {
+static struct scsi_host_template sil24_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index 42288be..42d7c4e 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -39,7 +39,6 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
@@ -83,7 +82,7 @@ static struct pci_driver sis_pci_driver 
 	.remove			= ata_pci_remove_one,
 };
 
-static Scsi_Host_Template sis_sht = {
+static struct scsi_host_template sis_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index db615ff..9895d1c 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -45,7 +45,6 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
@@ -284,7 +283,7 @@ static int k2_sata_proc_info(struct Scsi
 #endif /* CONFIG_PPC_OF */
 
 
-static Scsi_Host_Template k2_sata_sht = {
+static struct scsi_host_template k2_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index f859bbd..d5a3878 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -39,8 +39,8 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
 #include <asm/io.h>
 #include "sata_promise.h"
@@ -177,7 +177,7 @@ static void pdc20621_irq_clear(struct at
 static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
 
 
-static Scsi_Host_Template pdc_sata_sht = {
+static struct scsi_host_template pdc_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index a5e245c..cf0baaa 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -33,7 +33,6 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
@@ -71,7 +70,7 @@ static struct pci_driver uli_pci_driver 
 	.remove			= ata_pci_remove_one,
 };
 
-static Scsi_Host_Template uli_sht = {
+static struct scsi_host_template uli_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index b3ecdbe..ab19d2b 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -42,7 +42,6 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 #include <asm/io.h>
@@ -90,7 +89,7 @@ static struct pci_driver svia_pci_driver
 	.remove			= ata_pci_remove_one,
 };
 
-static Scsi_Host_Template svia_sht = {
+static struct scsi_host_template svia_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index bb84ba0..ce8a2fd 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -43,7 +43,6 @@
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
@@ -219,7 +218,7 @@ static irqreturn_t vsc_sata_interrupt (i
 }
 
 
-static Scsi_Host_Template vsc_sata_sht = {
+static struct scsi_host_template vsc_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index dcd17e7..6f07522 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -214,7 +214,7 @@ struct ata_probe_ent {
 	struct list_head	node;
 	struct device 		*dev;
 	const struct ata_port_operations *port_ops;
-	Scsi_Host_Template	*sht;
+	struct scsi_host_template *sht;
 	struct ata_ioports	port[ATA_MAX_PORTS];
 	unsigned int		n_ports;
 	unsigned int		hard_port_no;
@@ -398,7 +398,7 @@ struct ata_port_operations {
 };
 
 struct ata_port_info {
-	Scsi_Host_Template	*sht;
+	struct scsi_host_template *sht;
 	unsigned long		host_flags;
 	unsigned long		pio_mask;
 	unsigned long		mwdma_mask;
@@ -433,7 +433,7 @@ extern void ata_pci_remove_one (struct p
 #endif /* CONFIG_PCI */
 extern int ata_device_add(const struct ata_probe_ent *ent);
 extern void ata_host_set_remove(struct ata_host_set *host_set);
-extern int ata_scsi_detect(Scsi_Host_Template *sht);
+extern int ata_scsi_detect(struct scsi_host_template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
 extern int ata_scsi_error(struct Scsi_Host *host);

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

* Re: [git patches] 2.6.x libata updates
  2005-10-31 17:49                             ` David Lang
@ 2005-10-31 18:06                               ` Giuseppe Bilotta
  0 siblings, 0 replies; 50+ messages in thread
From: Giuseppe Bilotta @ 2005-10-31 18:06 UTC (permalink / raw)
  To: linux-kernel

On Mon, 31 Oct 2005 09:49:28 -0800 (PST), David Lang wrote:

> On Mon, 31 Oct 2005, Giuseppe Bilotta wrote:
> 
>> Trac has a 'Session ID' key that stores something like a cookie,
>> except that it's serverside. Something halfway a cookie and an actual
>> login. The user can write down the session ID or just assign its own,
>> and the re-enter the session ID and all things are restored to the
>> settings he had chosen. Something like this, maybe?
> 
> saving the state on the server means that you have to deal with (or 
> somehow eliminate) collisions between different users, it means that you 
> need to have the server-side data time out and get garbage collected, and 
> in general adds significant complexity to the project.

Well, I honestly don't have the slightest idea about this is handled
internally by Trac, but it seemed to be that something like this would
fit the needs, more or less. Of course it may need to be tuned for the
specific purpose ...

-- 
Giuseppe "Oblomov" Bilotta

"E la storia dell'umanità, babbo?"
"Ma niente: prima si fanno delle cazzate,
 poi si studia che cazzate si sono fatte"
(Altan)
("And what about the history of the human race, dad?"
 "Oh, nothing special: first they make some foolish things,
  then you study what foolish things have been made")


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

* Re: [git patches] 2.6.x libata updates
  2005-10-31 11:45                           ` Giuseppe Bilotta
@ 2005-10-31 17:49                             ` David Lang
  2005-10-31 18:06                               ` Giuseppe Bilotta
  0 siblings, 1 reply; 50+ messages in thread
From: David Lang @ 2005-10-31 17:49 UTC (permalink / raw)
  To: Giuseppe Bilotta; +Cc: linux-kernel

On Mon, 31 Oct 2005, Giuseppe Bilotta wrote:

> On Mon, 31 Oct 2005 03:34:34 -0600, Rob Landley wrote:
>
>> On Monday 31 October 2005 03:13, David Lang wrote:
>>>> I was thinking about doing thatn in hidden input fields and
>>>> passing form back and forth.  After all what real git bisect
>>>> keeps locally are one bad commit ID and bunch of good commit
>>>> IDs.
>>>
>>> if it's kept in a file or cookie then it can survive a reboot and other
>>> distractions (remember that this process can take days if the problem
>>> doesn't show up at boot). a cookie can hold a couple K worth of data, a
>>> file has no size limit.
>>
>> Actually, lots of Linux browsers these days treats all cookies as session
>> cookies for security reasons.  So surviving a reboot still isn't guaranteed.
>> But it's possible.

I haven't seen a browser that does this (it would break a lot of sites), I 
have seen the option when you go to accept a cookie to accept it for this 
session only, so a note to the user to allow the cookie to persist may be 
enough, or we can just go the tarball route and the file that gets saved 
and uploaded would be enough.

what browser have you seen this default bahavior on?

>> You can also have 'em bookmark a URL...
>
> Trac has a 'Session ID' key that stores something like a cookie,
> except that it's serverside. Something halfway a cookie and an actual
> login. The user can write down the session ID or just assign its own,
> and the re-enter the session ID and all things are restored to the
> settings he had chosen. Something like this, maybe?

saving the state on the server means that you have to deal with (or 
somehow eliminate) collisions between different users, it means that you 
need to have the server-side data time out and get garbage collected, and 
in general adds significant complexity to the project.

David Lang

-- 
There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.
  -- C.A.R. Hoare

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

* Re: [git patches] 2.6.x libata updates
  2005-10-31  9:34                         ` Rob Landley
@ 2005-10-31 11:45                           ` Giuseppe Bilotta
  2005-10-31 17:49                             ` David Lang
  0 siblings, 1 reply; 50+ messages in thread
From: Giuseppe Bilotta @ 2005-10-31 11:45 UTC (permalink / raw)
  To: linux-kernel

On Mon, 31 Oct 2005 03:34:34 -0600, Rob Landley wrote:

> On Monday 31 October 2005 03:13, David Lang wrote:
>>> I was thinking about doing thatn in hidden input fields and
>>> passing form back and forth.  After all what real git bisect
>>> keeps locally are one bad commit ID and bunch of good commit
>>> IDs.
>>
>> if it's kept in a file or cookie then it can survive a reboot and other
>> distractions (remember that this process can take days if the problem
>> doesn't show up at boot). a cookie can hold a couple K worth of data, a
>> file has no size limit.
> 
> Actually, lots of Linux browsers these days treats all cookies as session 
> cookies for security reasons.  So surviving a reboot still isn't guaranteed.  
> But it's possible.
> 
> You can also have 'em bookmark a URL...

Trac has a 'Session ID' key that stores something like a cookie,
except that it's serverside. Something halfway a cookie and an actual
login. The user can write down the session ID or just assign its own,
and the re-enter the session ID and all things are restored to the
settings he had chosen. Something like this, maybe?

-- 
Giuseppe "Oblomov" Bilotta

"I'm never quite so stupid
 as when I'm being smart" --Linus van Pelt


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

* Re: [git patches] 2.6.x libata updates
  2005-10-31  9:13                       ` David Lang
@ 2005-10-31  9:34                         ` Rob Landley
  2005-10-31 11:45                           ` Giuseppe Bilotta
  0 siblings, 1 reply; 50+ messages in thread
From: Rob Landley @ 2005-10-31  9:34 UTC (permalink / raw)
  To: David Lang; +Cc: Junio C Hamano, linux-kernel

On Monday 31 October 2005 03:13, David Lang wrote:
> > I was thinking about doing thatn in hidden input fields and
> > passing form back and forth.  After all what real git bisect
> > keeps locally are one bad commit ID and bunch of good commit
> > IDs.
>
> if it's kept in a file or cookie then it can survive a reboot and other
> distractions (remember that this process can take days if the problem
> doesn't show up at boot). a cookie can hold a couple K worth of data, a
> file has no size limit.

Actually, lots of Linux browsers these days treats all cookies as session 
cookies for security reasons.  So surviving a reboot still isn't guaranteed.  
But it's possible.

You can also have 'em bookmark a URL...

> it would also be a good idea if the web page could give an estimate
> estimate of how many additional tests may end up being required.

Bisect already says how many commits are left in the pool, so roughly log(2) 
of that...

> David Lang

Rob

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

* Re: [git patches] 2.6.x libata updates
  2005-10-31  9:00                     ` Junio C Hamano
@ 2005-10-31  9:13                       ` David Lang
  2005-10-31  9:34                         ` Rob Landley
  0 siblings, 1 reply; 50+ messages in thread
From: David Lang @ 2005-10-31  9:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: linux-kernel, Rob Landley

On Mon, 31 Oct 2005, Junio C Hamano wrote:

> David Lang <david.lang@digitalinsight.com> writes:
>
>> given the time required to compile a kernel and reboot you can't plan to
>> keep the info server side (browser connections will time out well before
>> this finishes)
>>
>> instead this will require saving something on the client and passing it
>> back to the server.
>
> I was thinking about doing thatn in hidden input fields and
> passing form back and forth.  After all what real git bisect
> keeps locally are one bad commit ID and bunch of good commit
> IDs.

if it's kept in a file or cookie then it can survive a reboot and other 
distractions (remember that this process can take days if the problem 
doesn't show up at boot). a cookie can hold a couple K worth of data, a 
file has no size limit.

it would also be a good idea if the web page could give an estimate 
estimate of how many additional tests may end up being required.

David Lang
-- 
There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.
  -- C.A.R. Hoare

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

* Re: [git patches] 2.6.x libata updates
  2005-10-31  8:10                   ` David Lang
  2005-10-31  8:28                     ` David Lang
@ 2005-10-31  9:00                     ` Junio C Hamano
  2005-10-31  9:13                       ` David Lang
  1 sibling, 1 reply; 50+ messages in thread
From: Junio C Hamano @ 2005-10-31  9:00 UTC (permalink / raw)
  To: David Lang; +Cc: linux-kernel, Rob Landley

David Lang <david.lang@digitalinsight.com> writes:

> given the time required to compile a kernel and reboot you can't plan to 
> keep the info server side (browser connections will time out well before 
> this finishes)
>
> instead this will require saving something on the client and passing it 
> back to the server.

I was thinking about doing thatn in hidden input fields and
passing form back and forth.  After all what real git bisect
keeps locally are one bad commit ID and bunch of good commit
IDs.


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

* Re: [git patches] 2.6.x libata updates
  2005-10-31  8:10                   ` David Lang
@ 2005-10-31  8:28                     ` David Lang
  2005-10-31  9:00                     ` Junio C Hamano
  1 sibling, 0 replies; 50+ messages in thread
From: David Lang @ 2005-10-31  8:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: linux-kernel, Rob Landley

On Mon, 31 Oct 2005, David Lang wrote:

> On Sun, 30 Oct 2005, Junio C Hamano wrote:
>
>> Rob Landley <rob@landley.net> writes:
>> 
>>> grep -n MARKER bisect.patch | less
>>> (pick a line number)
>>> head -n linenumber bisect.patch > test.patch
>>> 
>>> If that's not it, revert test.patch and then try again.  Tell us the first
>>> line number that failed, which is the end of the patch we want...
>>> 
>>> Hmmm...  The logical place to put the URL to gitweb is at the _end_ of the
>>> patch, attached to the marker.  So that's what they see in the grep, and 
>>> the
>>> last thing they test when they cut at that line with head -n...
>> 
>> Well, do people realize that 'git bisect' is *not* a textual
>> half-way between, but rather is computed every time you feed
>> new "the patch you told me to test last time was good/bad"
>> information?  I do not think statically generating a huge text
>> and telling the user to apply up to halfway and bisect by hand
>> would not work -- it would be quite different from what git
>> bisect would give you.
>> 
>> I think public webserver based bisect service David Lang
>> suggests might work.  The interaction with it would start by the
>> end user somehow giving it the last known-working commit ID (A)
>> (pick from gitweb shortlog, perhaps) and a commit ID newer than
>> that that broke things (B) (again, pick from gitweb shortlog).
>> Then the service runs bisect on the server side, spit out a diff
>> against (A).  The end user applies the patch, try it, and then
>> come back and tell if it worked or not,...  Since we are talking
>> about the kernel development, I think the cycle might involve
>> rebooting the machine; so you would probably need two machines
>> (one guinea-pig machine to reboot, another to keep the browser
>> open so that your state can be kept somehow).
>
> given the time required to compile a kernel and reboot you can't plan to keep 
> the info server side (browser connections will time out well before this 
> finishes)
>
> instead this will require saving something on the client and passing it back 
> to the server.
>
> offhand I'd say that it would end up working something like this.
>
> 1. go to the website and pick starting good/bad points
> 2. the server will give you a tgz (bzip is significantly more load on the 
> server) that contains the patch and a status file.
> 3. apply the patch to the starting tree (in theory it may be a smaller patch 
> to either tree, but it's easier to explain if one is picked all the time so 
> initially it should be the working tree). compile the tree and test
> 4. go back to the website, upload the status file and indicate sucess or 
> failure
> 5. goto 2
>
> the file would basicly save and report what git bisect would normally store 
> in environment variables.
>
> the server will have to do some sanity checking on the good and bad points 
> it's given (for security reasons if nothing else)
>
> potentially it should suggest checking an officially tagged release that's 
> between the good and bad points. this may actually slow testing slightly (if 
> you know it worked on 2.6.7 and failed on 2.6.12 you would probably be the 
> most efficiant if you start bisecting directly, but it's far easier for 
> others to understand things if you test 2.6.10 and other tagged releases 
> first)
>
> I also suspect that a log of what people are testing would be intereating to 
> people as well (if you see a bunch of people bisecting in the same area it's 
> an indication that more attention needs to be paied to that area)
>
> David Lang

an alternate approach that would be a little cleaner would be to use a 
cookie to store the bisect state info so that it is just a patch that's 
downloaded (although this does limit someone to bisecting one thing at a 
time, I think that's not an unreasonable limitation)

David Lang
-- 
There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.
  -- C.A.R. Hoare

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

* Re: [git patches] 2.6.x libata updates
  2005-10-31  7:46                 ` Junio C Hamano
@ 2005-10-31  8:10                   ` David Lang
  2005-10-31  8:28                     ` David Lang
  2005-10-31  9:00                     ` Junio C Hamano
  0 siblings, 2 replies; 50+ messages in thread
From: David Lang @ 2005-10-31  8:10 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: linux-kernel, Rob Landley

On Sun, 30 Oct 2005, Junio C Hamano wrote:

> Rob Landley <rob@landley.net> writes:
>
>> grep -n MARKER bisect.patch | less
>> (pick a line number)
>> head -n linenumber bisect.patch > test.patch
>>
>> If that's not it, revert test.patch and then try again.  Tell us the first
>> line number that failed, which is the end of the patch we want...
>>
>> Hmmm...  The logical place to put the URL to gitweb is at the _end_ of the
>> patch, attached to the marker.  So that's what they see in the grep, and the
>> last thing they test when they cut at that line with head -n...
>
> Well, do people realize that 'git bisect' is *not* a textual
> half-way between, but rather is computed every time you feed
> new "the patch you told me to test last time was good/bad"
> information?  I do not think statically generating a huge text
> and telling the user to apply up to halfway and bisect by hand
> would not work -- it would be quite different from what git
> bisect would give you.
>
> I think public webserver based bisect service David Lang
> suggests might work.  The interaction with it would start by the
> end user somehow giving it the last known-working commit ID (A)
> (pick from gitweb shortlog, perhaps) and a commit ID newer than
> that that broke things (B) (again, pick from gitweb shortlog).
> Then the service runs bisect on the server side, spit out a diff
> against (A).  The end user applies the patch, try it, and then
> come back and tell if it worked or not,...  Since we are talking
> about the kernel development, I think the cycle might involve
> rebooting the machine; so you would probably need two machines
> (one guinea-pig machine to reboot, another to keep the browser
> open so that your state can be kept somehow).

given the time required to compile a kernel and reboot you can't plan to 
keep the info server side (browser connections will time out well before 
this finishes)

instead this will require saving something on the client and passing it 
back to the server.

offhand I'd say that it would end up working something like this.

1. go to the website and pick starting good/bad points
2. the server will give you a tgz (bzip is significantly more load on the 
server) that contains the patch and a status file.
3. apply the patch to the starting tree (in theory it may be a smaller 
patch to either tree, but it's easier to explain if one is picked all the 
time so initially it should be the working tree). compile the tree and 
test
4. go back to the website, upload the status file and indicate sucess or 
failure
5. goto 2

the file would basicly save and report what git bisect would normally 
store in environment variables.

the server will have to do some sanity checking on the good and bad points 
it's given (for security reasons if nothing else)

potentially it should suggest checking an officially tagged release 
that's between the good and bad points. this may actually slow testing 
slightly (if you know it worked on 2.6.7 and failed on 2.6.12 you would 
probably be the most efficiant if you start bisecting directly, but it's 
far easier for others to understand things if you test 2.6.10 and other 
tagged releases first)

I also suspect that a log of what people are testing would be intereating 
to people as well (if you see a bunch of people bisecting in the same area 
it's an indication that more attention needs to be paied to that area)

David Lang

-- 
There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.
  -- C.A.R. Hoare

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

* Re: [git patches] 2.6.x libata updates
  2005-10-31  2:35               ` Rob Landley
@ 2005-10-31  7:46                 ` Junio C Hamano
  2005-10-31  8:10                   ` David Lang
  0 siblings, 1 reply; 50+ messages in thread
From: Junio C Hamano @ 2005-10-31  7:46 UTC (permalink / raw)
  To: linux-kernel; +Cc: Rob Landley

Rob Landley <rob@landley.net> writes:

> grep -n MARKER bisect.patch | less
> (pick a line number)
> head -n linenumber bisect.patch > test.patch
>
> If that's not it, revert test.patch and then try again.  Tell us the first 
> line number that failed, which is the end of the patch we want...
>
> Hmmm...  The logical place to put the URL to gitweb is at the _end_ of the 
> patch, attached to the marker.  So that's what they see in the grep, and the 
> last thing they test when they cut at that line with head -n...

Well, do people realize that 'git bisect' is *not* a textual
half-way between, but rather is computed every time you feed
new "the patch you told me to test last time was good/bad"
information?  I do not think statically generating a huge text
and telling the user to apply up to halfway and bisect by hand
would not work -- it would be quite different from what git
bisect would give you.

I think public webserver based bisect service David Lang
suggests might work.  The interaction with it would start by the
end user somehow giving it the last known-working commit ID (A)
(pick from gitweb shortlog, perhaps) and a commit ID newer than
that that broke things (B) (again, pick from gitweb shortlog).
Then the service runs bisect on the server side, spit out a diff
against (A).  The end user applies the patch, try it, and then
come back and tell if it worked or not,...  Since we are talking
about the kernel development, I think the cycle might involve
rebooting the machine; so you would probably need two machines
(one guinea-pig machine to reboot, another to keep the browser
open so that your state can be kept somehow).


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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 19:37     ` Linus Torvalds
                         ` (6 preceding siblings ...)
  2005-10-30 13:11       ` Pavel Machek
@ 2005-10-31  3:55       ` David Lang
  7 siblings, 0 replies; 50+ messages in thread
From: David Lang @ 2005-10-31  3:55 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Jeff Garzik, Andrew Morton, linux-ide, linux-kernel

On Sat, 29 Oct 2005, Linus Torvalds wrote:

> On Sat, 29 Oct 2005, Jeff Garzik wrote:
>>
>> Even so, it's easy, to I'll ask him to test 2.6.14, 2.6.14-git1, and
>> (tonight's upcoming) 2.6.14-git2 (with my latest pull included) to see if
>> anything breaks.
>
> Side note: one of the downsides of the new "merge lots of stuff early in
> the development series" approach is that the first few daily snapshots end
> up being _huge_.
>
> So the -git1 and -git2 patches are/will be very big indeed.
>
> For example, patch-2.6.14-git1 literally ended up being a megabyte
> compressed. Right now my diff to 2.6.14 (after just two days) is 1.6MB
> compressed.
>
> Admittedly, some of it is due to things like the MIPS merge, but the point
> I'm trying to make is that it makes the daily snapshot diffs a lot less
> useful to people who try to figure out where something broke.
>
> Now, I've gotten several positive comments on how easy "git bisect" is to
> use, and I've used it myself, but this is the first time that patch users
> _really_ become very much second-class citizens, and you can't necessarily
> always do useful things with just the tar-trees and patches. That's sad,
> and possibly a really big downside.
>
> Don't get me wrong - I personally think that the new merge policy is a
> clear improvement, but it does have this downside.
>
> 			Linus

how about setting up something on a webserver (ideally kernel.org) to do 
the git bisect and output patches against the daily snapshots.

if a lot of people used it the load would be an issue, but if it's only 
used by a relativly few people tracking down bugs it's probably worth it.

David Lang

-- 
There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.
  -- C.A.R. Hoare

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

* Re: [git patches] 2.6.x libata updates
  2005-10-31  0:58             ` Linus Torvalds
  2005-10-31  2:35               ` Rob Landley
@ 2005-10-31  2:52               ` Rob Landley
  2005-11-10  0:36               ` Matthias Urlichs
  2 siblings, 0 replies; 50+ messages in thread
From: Rob Landley @ 2005-10-31  2:52 UTC (permalink / raw)
  Cc: linux-kernel

On Sunday 30 October 2005 18:58, Linus Torvalds wrote:
> Using "git bisect" to generate successive bisections (and then building up
> a linearization patch from that) would work,

I don't suppose I could make puppy eyes at somebody _else_ to bang on git a 
bit and try to come up with a proof-of-concept patch?  (Say 
2.6.14-rc5-bisect.patch?)

I just downloaded the git source snapshot to find out it won't compile without 
openssl headers.  (Thanks, ubuntu, for stripping out every darn development 
header and making them separate things you have to hunt down and install 
individually, even though the box actually _has_ whatever darn library it's 
complaining about and really couldn't _function_ without it.  Sigh.)

Rob

(kynaptic 
--install-the-development-headers-for-all-installed-packages-already)

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

* Re: [git patches] 2.6.x libata updates
  2005-10-31  0:58             ` Linus Torvalds
@ 2005-10-31  2:35               ` Rob Landley
  2005-10-31  7:46                 ` Junio C Hamano
  2005-10-31  2:52               ` Rob Landley
  2005-11-10  0:36               ` Matthias Urlichs
  2 siblings, 1 reply; 50+ messages in thread
From: Rob Landley @ 2005-10-31  2:35 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Jeff Garzik, Andrew Morton, linux-ide, linux-kernel

On Sunday 30 October 2005 18:58, Linus Torvalds wrote:

> Using "git bisect" to generate successive bisections (and then building up
> a linearization patch from that) would work, but it would result in some
> _really_ strange things:

Which is fine for a debugging tool.

It sounds like any git user could make one of these patches now, and put them 
up each time you cut a release.  (Hmmm, is this likely to be scriptable, or 
does it require poking at the git source?  Coming up to speed on git is a 
to-do item for me.  It has its own _vocabulary_, not exactly a trivial time 
expenditure to understand what's going on for those of us who never got 
around to using bitkeeper...)

> it would basically have one patch do one thing, 
> then the next patch might _undo_ that, and do another, and then the third
> patch would re-do it and do them both together.
>
> And that's really sometimes the best linearization you can do. But that's
> just too strange and confusing, I think. And the patches would be horribly
> inefficient.

"Horribly inefficient" seems pretty standard for a debugging tool.  Dwarf2 
bloats executables by a factor of 10 or more.  If it's a big issue, perhaps 
kernel.org could offer both "rc1-rc2.patch" (the "simple diff between trees" 
version) and "rc1-rc2-bisect.patch" (the "ugly granular debugging" version).

Also, the patch description in the bisect version could easily include a URL 
to an online git diff viewer (can http://www.kernel.org/git do this?) in case 
people want to see what it did, since the patch for artificially linearized 
changes can easily be unintelligible, ala:

The human readable version of this patch is at:
http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=3e6716e748609a3a899e8d670e42832921bd45bc

> At that point I'd rather teach people to use "git bisect" natively. It
> wouldn't be any less confusing than the patches ;)

The problem with teaching people to use "git bisect" is you have people who 
aren't kernel developers who have a bug, and want to help track down the bug, 
and you're telling them "Ok, to debug this you need to install git, use it to 
check out the linux-kernel repository, then..."

I suspect even the best-intentioned dilettantes seldom make it to "then".  
Telling them to binary search through a downloadable text file on the marker 
"===newpatch===" or some such sounds like a much easier sell.  It doesn't 
even need a shell script:

grep -n MARKER bisect.patch | less
(pick a line number)
head -n linenumber bisect.patch > test.patch

If that's not it, revert test.patch and then try again.  Tell us the first 
line number that failed, which is the end of the patch we want...

Hmmm...  The logical place to put the URL to gitweb is at the _end_ of the 
patch, attached to the marker.  So that's what they see in the grep, and the 
last thing they test when they cut at that line with head -n...

>   Linus

Rob

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

* Re: [git patches] 2.6.x libata updates
  2005-10-30 23:31           ` Rob Landley
@ 2005-10-31  0:58             ` Linus Torvalds
  2005-10-31  2:35               ` Rob Landley
                                 ` (2 more replies)
  0 siblings, 3 replies; 50+ messages in thread
From: Linus Torvalds @ 2005-10-31  0:58 UTC (permalink / raw)
  To: Rob Landley; +Cc: Jeff Garzik, Andrew Morton, linux-ide, linux-kernel



On Sun, 30 Oct 2005, Rob Landley wrote:
> 
> I know there isn't an absolute or stable ordering, but can't a temporary 
> ordering be exported?

Not generally, no. And definitely not easily.

> I was under the impression that the bk->cvs gateway squashed changes into a 
> sort of order, way back when.

I have to say that the bk->cvs gateway is actually a very impressive 
linearization, and I don't even know how it did it. But even that one 
wasn't perfect - occasionally it ended up with big patches for merges.

Using "git bisect" to generate successive bisections (and then building up 
a linearization patch from that) would work, but it would result in some 
_really_ strange things: it would basically have one patch do one thing, 
then the next patch might _undo_ that, and do another, and then the third 
patch would re-do it and do them both together.

And that's really sometimes the best linearization you can do. But that's 
just too strange and confusing, I think. And the patches would be horribly 
inefficient.

At that point I'd rather teach people to use "git bisect" natively. It 
wouldn't be any less confusing than the patches ;)

		Linus

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

* Re: [git patches] 2.6.x libata updates
  2005-10-30 23:59           ` Rob Landley
@ 2005-10-31  0:16             ` Randy.Dunlap
  0 siblings, 0 replies; 50+ messages in thread
From: Randy.Dunlap @ 2005-10-31  0:16 UTC (permalink / raw)
  To: Rob Landley; +Cc: torvalds, jgarzik, akpm, linux-ide, linux-kernel

On Sun, 30 Oct 2005 17:59:39 -0600 Rob Landley wrote:

> On Sunday 30 October 2005 16:36, Linus Torvalds wrote:
> 
> > > Is this a viable option?
> >
> > No.
> >
> > There is no "ordering" in a distributed environment. We have things
> > happening in parallel, adn you can't really linearize the patches.
> 
> To clarify my thinking:
> 
> It doesn't matter what the ordering is, as long as A) the patches are 
> separated somehow, B) the resulting kernel from applying any initial subset 
> (patches 1-X in the series) has some reasonable chance to build and work.
> 
> Any arbitrary order is theoretically fine for (A).  Alphabetical by msgid or 
> sha1sum.  Or the order they appear in the changelog.
> 
> It's (B) that's the tricky bit, but not an insoluble problem.  "The order 
> Linux imported them into his tree" might give that.
> 
> > The closest you can get is "git bisect", which does the right thing.
> 
> Ok, so we've already got an order, whatever order git bisect puts them in.  
> (It doesn't have to be stable between releases, just a snapshot in time of a 
> set of individual patches which, cumulatively applied,would have the same 
> effect as the big rc1->rc2 diffs we've been getting.)
> 
> It doesn't sound like it would be _too_ hard to abuse the "git bisect" 
> mechanism to work out each possible bisection point between -rc1 and -rc1, 
> and if that can be done why can't it spit out the individual patches (with 
> descriptions) and cat them together?
> 
> Why wouldn't this work?

Why isn't there a linus.git ordering?  that can be made to work.

---
~Randy

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

* Re: [git patches] 2.6.x libata updates
  2005-10-30 22:36         ` Linus Torvalds
  2005-10-30 23:31           ` Rob Landley
@ 2005-10-30 23:59           ` Rob Landley
  2005-10-31  0:16             ` Randy.Dunlap
  1 sibling, 1 reply; 50+ messages in thread
From: Rob Landley @ 2005-10-30 23:59 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Jeff Garzik, Andrew Morton, linux-ide, linux-kernel

On Sunday 30 October 2005 16:36, Linus Torvalds wrote:

> > Is this a viable option?
>
> No.
>
> There is no "ordering" in a distributed environment. We have things
> happening in parallel, adn you can't really linearize the patches.

To clarify my thinking:

It doesn't matter what the ordering is, as long as A) the patches are 
separated somehow, B) the resulting kernel from applying any initial subset 
(patches 1-X in the series) has some reasonable chance to build and work.

Any arbitrary order is theoretically fine for (A).  Alphabetical by msgid or 
sha1sum.  Or the order they appear in the changelog.

It's (B) that's the tricky bit, but not an insoluble problem.  "The order 
Linux imported them into his tree" might give that.

> The closest you can get is "git bisect", which does the right thing.

Ok, so we've already got an order, whatever order git bisect puts them in.  
(It doesn't have to be stable between releases, just a snapshot in time of a 
set of individual patches which, cumulatively applied,would have the same 
effect as the big rc1->rc2 diffs we've been getting.)

It doesn't sound like it would be _too_ hard to abuse the "git bisect" 
mechanism to work out each possible bisection point between -rc1 and -rc1, 
and if that can be done why can't it spit out the individual patches (with 
descriptions) and cat them together?

Why wouldn't this work?

>   Linus

Rob

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

* Re: [git patches] 2.6.x libata updates
  2005-10-30 22:36         ` Linus Torvalds
@ 2005-10-30 23:31           ` Rob Landley
  2005-10-31  0:58             ` Linus Torvalds
  2005-10-30 23:59           ` Rob Landley
  1 sibling, 1 reply; 50+ messages in thread
From: Rob Landley @ 2005-10-30 23:31 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Jeff Garzik, Andrew Morton, linux-ide, linux-kernel

On Sunday 30 October 2005 16:36, Linus Torvalds wrote:
> > Is this a viable option?
>
> No.
>
> There is no "ordering" in a distributed environment. We have things
> happening in parallel, adn you can't really linearize the patches.
>
> The closest you can get is "git bisect", which does the right thing.
>
>   Linus

I know there isn't an absolute or stable ordering, but can't a temporary 
ordering be exported?

I was under the impression that the bk->cvs gateway squashed changes into a 
sort of order, way back when.  Admittedly this order wasn't stable, and new 
changes perturbed the whole list.  But just for debugging purposes with a 
"patch vs last -rc"?

Rob

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

* Re: [git patches] 2.6.x libata updates
  2005-10-30 12:44       ` Rob Landley
@ 2005-10-30 22:36         ` Linus Torvalds
  2005-10-30 23:31           ` Rob Landley
  2005-10-30 23:59           ` Rob Landley
  0 siblings, 2 replies; 50+ messages in thread
From: Linus Torvalds @ 2005-10-30 22:36 UTC (permalink / raw)
  To: Rob Landley; +Cc: Jeff Garzik, Andrew Morton, linux-ide, linux-kernel



On Sun, 30 Oct 2005, Rob Landley wrote:
> 
> Rather than making the patch a simple diff of the trees, make the patch a cat 
> of the individual patches/commits (preferably with descriptions) that got 
> applied, in the order they got applied.
> 
> This makes the patch bigger, but it also means that bisect can be done with 
> vi, simply by truncating the file at the last interesting patch and applying 
> the truncated version to a clean tree.  Since patch applies hunks in order 
> and sifts out hunks from description already...
> 
> Is this a viable option?

No.

There is no "ordering" in a distributed environment. We have things 
happening in parallel, adn you can't really linearize the patches.

The closest you can get is "git bisect", which does the right thing.

		Linus

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 21:01         ` Linus Torvalds
@ 2005-10-30 15:46           ` Nicolas Pitre
  0 siblings, 0 replies; 50+ messages in thread
From: Nicolas Pitre @ 2005-10-30 15:46 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: lkml

On Sat, 29 Oct 2005, Linus Torvalds wrote:

> On Sat, 29 Oct 2005, Nicolas Pitre wrote:
> > 
> > Since GIT is real free software that even purists may use without fear, 
> > this downside is certainly not as critical as it was in the BK days.
> 
> I don't think that's the problem.
> 
> It's the learning curve. I don't think git is that hard to use (certainly 
> not if you just follow somebody elses tree and occasionally do a "git 
> bisect"), but git _is_ different. And if you're not a developer, or even 
> if you are, and you're just somebody who has alway sjust used CVS, then 
> something like "patch" is simply to understand what it's doing, with 
> basically no abstractions anywhere. 

Agreed.

> Compared to tar-files + patches, git has a _lot_ of abstract things going 
> on that you have to get used to before you aren't intimidated by it.

Maybe gitweb could be extended to provide any arbitrary patch with a 
front-end to git-bisect...


Nicolas

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 19:37     ` Linus Torvalds
                         ` (5 preceding siblings ...)
  2005-10-30 12:44       ` Rob Landley
@ 2005-10-30 13:11       ` Pavel Machek
  2005-10-31  3:55       ` David Lang
  7 siblings, 0 replies; 50+ messages in thread
From: Pavel Machek @ 2005-10-30 13:11 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Jeff Garzik, Andrew Morton, linux-ide, linux-kernel

Hi!

> > Even so, it's easy, to I'll ask him to test 2.6.14, 2.6.14-git1, and
> > (tonight's upcoming) 2.6.14-git2 (with my latest pull included) to see if
> > anything breaks.
> 
> Side note: one of the downsides of the new "merge lots of stuff early in 
> the development series" approach is that the first few daily snapshots end 
> up being _huge_. 
> 
> So the -git1 and -git2 patches are/will be very big indeed.
> 
> For example, patch-2.6.14-git1 literally ended up being a megabyte 
> compressed. Right now my diff to 2.6.14 (after just two days) is 1.6MB 
> compressed.
...
> Now, I've gotten several positive comments on how easy "git bisect" is to 
> use, and I've used it myself, but this is the first time that patch users 
> _really_ become very much second-class citizens, and you can't necessarily 
> always do useful things with just the tar-trees and patches. That's sad, 
> and possibly a really big downside.
> 
> Don't get me wrong - I personally think that the new merge policy is a 
> clear improvement, but it does have this downside.

Well, git bisect helps a bit, but does not really cut it. If changes are
merged slowly enough, you usually don't need to go through history;
you know it is broken, you know it worked yesterday, and diff is small enough...

				Pavel
-- 
64 bytes from 195.113.31.123: icmp_seq=28 ttl=51 time=448769.1 ms         


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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 19:37     ` Linus Torvalds
                         ` (4 preceding siblings ...)
  2005-10-30  2:28       ` Horst von Brand
@ 2005-10-30 12:44       ` Rob Landley
  2005-10-30 22:36         ` Linus Torvalds
  2005-10-30 13:11       ` Pavel Machek
  2005-10-31  3:55       ` David Lang
  7 siblings, 1 reply; 50+ messages in thread
From: Rob Landley @ 2005-10-30 12:44 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Jeff Garzik, Andrew Morton, linux-ide, linux-kernel

On Saturday 29 October 2005 14:37, Linus Torvalds wrote:
> Now, I've gotten several positive comments on how easy "git bisect" is to
> use, and I've used it myself, but this is the first time that patch users
> _really_ become very much second-class citizens, and you can't necessarily
> always do useful things with just the tar-trees and patches. That's sad,
> and possibly a really big downside.
>
> Don't get me wrong - I personally think that the new merge policy is a
> clear improvement, but it does have this downside.

One possible solution:

Rather than making the patch a simple diff of the trees, make the patch a cat 
of the individual patches/commits (preferably with descriptions) that got 
applied, in the order they got applied.

This makes the patch bigger, but it also means that bisect can be done with 
vi, simply by truncating the file at the last interesting patch and applying 
the truncated version to a clean tree.  Since patch applies hunks in order 
and sifts out hunks from description already...

Is this a viable option?

Rob

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 19:37     ` Linus Torvalds
                         ` (3 preceding siblings ...)
  2005-10-29 22:21       ` Andrew Morton
@ 2005-10-30  2:28       ` Horst von Brand
  2005-10-30 12:44       ` Rob Landley
                         ` (2 subsequent siblings)
  7 siblings, 0 replies; 50+ messages in thread
From: Horst von Brand @ 2005-10-30  2:28 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Jeff Garzik, Andrew Morton, linux-ide, linux-kernel

Linus Torvalds <torvalds@osdl.org> wrote:
> On Sat, 29 Oct 2005, Jeff Garzik wrote:
> > 
> > Even so, it's easy, to I'll ask him to test 2.6.14, 2.6.14-git1, and
> > (tonight's upcoming) 2.6.14-git2 (with my latest pull included) to see if
> > anything breaks.
> 
> Side note: one of the downsides of the new "merge lots of stuff early in 
> the development series" approach is that the first few daily snapshots end 
> up being _huge_. 

How about doing it in several stages at the beginning? I.e., have -git1
after one set of patches (pulling in from somebody, etc), and so on?
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                     Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria              +56 32 654239
Casilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 22:30         ` Linus Torvalds
@ 2005-10-30  0:55           ` Tony Luck
  0 siblings, 0 replies; 50+ messages in thread
From: Tony Luck @ 2005-10-30  0:55 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, jgarzik, linux-ide, linux-kernel

Perhaps the script that creates the -git1 etc. nightly snapshots
could peek at how many commits were included since the
previous snapshot ... if it is above some threshhold, then it
could run "git bisect" to create a -git0.5 (recursing if needed
to make -git0.25 etc.)

-Tony

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 22:21       ` Andrew Morton
@ 2005-10-29 22:30         ` Linus Torvalds
  2005-10-30  0:55           ` Tony Luck
  0 siblings, 1 reply; 50+ messages in thread
From: Linus Torvalds @ 2005-10-29 22:30 UTC (permalink / raw)
  To: Andrew Morton; +Cc: jgarzik, linux-ide, linux-kernel



On Sat, 29 Oct 2005, Andrew Morton wrote:
> 
> However there's usually little overlap between the subsystems trees - with
> a net update, a USB update, a SCSI update and an ia64 update it's usually
> pretty obvious which one caused a particular regression.

Yes, that's true, but the subsystem trees themselves now tend to have more 
time to grow, and tend to be merged more int one go.

Which is all intentional, of course - the whole _point_ of the new thing 
is that they should be in your tree and tested and then merged into my 
tree during a short "merge window" for further testing.

But it means that updates that used to "tricke in" to my kernel now tend 
to be more of a "big merge", making the daily snapshot less effective.

So when we get a "uhhuh, networking failed between daily snapshot X and 
X+1" we now more often have a single biger merge of networking stuff that 
was just waiting for the merge window to open..

> The individual -mm-only patches tend to be more scattered around the tree,
> which is why I send them as batches of 100-200 every couple of days: to get
> a bit of separation in the -git snapshots.  This hasn't actually proven to
> be very useful, though.

One issue is of course that a lot of people doing reports don't actually
even test the daily snapshots.

Some bug reporters do, and I'm very grateful, and they are wonderful 
people. Others do after some prodding, and yet others will never bother to 
try a couple of different kernels at all ;/

So the snapshot separation doesn't always necessarily help, even when it's 
there.

		Linus

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 19:37     ` Linus Torvalds
                         ` (2 preceding siblings ...)
  2005-10-29 20:18       ` Nicolas Pitre
@ 2005-10-29 22:21       ` Andrew Morton
  2005-10-29 22:30         ` Linus Torvalds
  2005-10-30  2:28       ` Horst von Brand
                         ` (3 subsequent siblings)
  7 siblings, 1 reply; 50+ messages in thread
From: Andrew Morton @ 2005-10-29 22:21 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: jgarzik, linux-ide, linux-kernel

Linus Torvalds <torvalds@osdl.org> wrote:
>
> 
> 
> On Sat, 29 Oct 2005, Jeff Garzik wrote:
> > 
> > Even so, it's easy, to I'll ask him to test 2.6.14, 2.6.14-git1, and
> > (tonight's upcoming) 2.6.14-git2 (with my latest pull included) to see if
> > anything breaks.
> 
> Side note: one of the downsides of the new "merge lots of stuff early in 
> the development series" approach is that the first few daily snapshots end 
> up being _huge_. 
> 
> So the -git1 and -git2 patches are/will be very big indeed.
> 
> For example, patch-2.6.14-git1 literally ended up being a megabyte 
> compressed. Right now my diff to 2.6.14 (after just two days) is 1.6MB 
> compressed.
> 

However there's usually little overlap between the subsystems trees - with
a net update, a USB update, a SCSI update and an ia64 update it's usually
pretty obvious which one caused a particular regression.

And given that the size of each individual subsystem update is unaltered,
it doesn't really matter whether or not they all came on the same day.

The individual -mm-only patches tend to be more scattered around the tree,
which is why I send them as batches of 100-200 every couple of days: to get
a bit of separation in the -git snapshots.  This hasn't actually proven to
be very useful, though.

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 20:18       ` Nicolas Pitre
@ 2005-10-29 21:01         ` Linus Torvalds
  2005-10-30 15:46           ` Nicolas Pitre
  0 siblings, 1 reply; 50+ messages in thread
From: Linus Torvalds @ 2005-10-29 21:01 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: lkml



On Sat, 29 Oct 2005, Nicolas Pitre wrote:
> 
> Since GIT is real free software that even purists may use without fear, 
> this downside is certainly not as critical as it was in the BK days.

I don't think that's the problem.

It's the learning curve. I don't think git is that hard to use (certainly 
not if you just follow somebody elses tree and occasionally do a "git 
bisect"), but git _is_ different. And if you're not a developer, or even 
if you are, and you're just somebody who has alway sjust used CVS, then 
something like "patch" is simply to understand what it's doing, with 
basically no abstractions anywhere. 

Compared to tar-files + patches, git has a _lot_ of abstract things going 
on that you have to get used to before you aren't intimidated by it.

And the thing is, the most important bug-reports often come from people 
who aren't necessarily developers - because they are the ones that see a 
bug that none of the developers saw.. So making it easy for people like 
that to test a few different versions is probably important.

		Linus

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 19:37     ` Linus Torvalds
  2005-10-29 20:09       ` Al Viro
  2005-10-29 20:16       ` Jeff Garzik
@ 2005-10-29 20:18       ` Nicolas Pitre
  2005-10-29 21:01         ` Linus Torvalds
  2005-10-29 22:21       ` Andrew Morton
                         ` (4 subsequent siblings)
  7 siblings, 1 reply; 50+ messages in thread
From: Nicolas Pitre @ 2005-10-29 20:18 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: lkml

On Sat, 29 Oct 2005, Linus Torvalds wrote:

> Now, I've gotten several positive comments on how easy "git bisect" is to 
> use, and I've used it myself, but this is the first time that patch users 
> _really_ become very much second-class citizens, and you can't necessarily 
> always do useful things with just the tar-trees and patches. That's sad, 
> and possibly a really big downside.

Since GIT is real free software that even purists may use without fear, 
this downside is certainly not as critical as it was in the BK days.

The fact is: tar and patches simply do not scale anymore.


Nicolas

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 19:37     ` Linus Torvalds
  2005-10-29 20:09       ` Al Viro
@ 2005-10-29 20:16       ` Jeff Garzik
  2005-10-29 20:18       ` Nicolas Pitre
                         ` (5 subsequent siblings)
  7 siblings, 0 replies; 50+ messages in thread
From: Jeff Garzik @ 2005-10-29 20:16 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, linux-ide, linux-kernel

Linus Torvalds wrote:
> Side note: one of the downsides of the new "merge lots of stuff early in 
> the development series" approach is that the first few daily snapshots end 
> up being _huge_. 

Yeah.  Back when I did the BK snapshots, I would occasionally do a 
middle-of-the-day snapshot if there were a ton of incoming merges in a 
24-hour span.

If this "huge -git1" becomes a real problem, we could always

* give you a manual "do snapshot" button

* ask the maintainers to spread out their submits across multiple days, 
as I am doing now

* sell you on capping the daily push-to-kernel.org limit.  merge stuff 
into "day1", "day2", etc. branches when the main branch "fills up" for 
the day.

None of these are terribly painful, but none are terribly appealing either.

	Jeff



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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 19:37     ` Linus Torvalds
@ 2005-10-29 20:09       ` Al Viro
  2005-10-29 20:16       ` Jeff Garzik
                         ` (6 subsequent siblings)
  7 siblings, 0 replies; 50+ messages in thread
From: Al Viro @ 2005-10-29 20:09 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Jeff Garzik, Andrew Morton, linux-ide, linux-kernel

On Sat, Oct 29, 2005 at 12:37:58PM -0700, Linus Torvalds wrote:
> Now, I've gotten several positive comments on how easy "git bisect" is to 
> use, and I've used it myself, but this is the first time that patch users 
> _really_ become very much second-class citizens, and you can't necessarily 
> always do useful things with just the tar-trees and patches. That's sad, 
> and possibly a really big downside.
> 
> Don't get me wrong - I personally think that the new merge policy is a 
> clear improvement, but it does have this downside.

Well...  All it takes is extra patches when incremental gets too large;
e.g. have a script pick idle interval close to splitting the thing in
half until parts get less than <size>.  The question is, how much extra
load would that create?  Another problem is that a lot of intermediates
will not build, but that is just as true for -git<n> snapshots ;-/

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 19:20   ` Jeff Garzik
@ 2005-10-29 19:37     ` Linus Torvalds
  2005-10-29 20:09       ` Al Viro
                         ` (7 more replies)
  0 siblings, 8 replies; 50+ messages in thread
From: Linus Torvalds @ 2005-10-29 19:37 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Andrew Morton, linux-ide, linux-kernel



On Sat, 29 Oct 2005, Jeff Garzik wrote:
> 
> Even so, it's easy, to I'll ask him to test 2.6.14, 2.6.14-git1, and
> (tonight's upcoming) 2.6.14-git2 (with my latest pull included) to see if
> anything breaks.

Side note: one of the downsides of the new "merge lots of stuff early in 
the development series" approach is that the first few daily snapshots end 
up being _huge_. 

So the -git1 and -git2 patches are/will be very big indeed.

For example, patch-2.6.14-git1 literally ended up being a megabyte 
compressed. Right now my diff to 2.6.14 (after just two days) is 1.6MB 
compressed.

Admittedly, some of it is due to things like the MIPS merge, but the point 
I'm trying to make is that it makes the daily snapshot diffs a lot less 
useful to people who try to figure out where something broke.

Now, I've gotten several positive comments on how easy "git bisect" is to 
use, and I've used it myself, but this is the first time that patch users 
_really_ become very much second-class citizens, and you can't necessarily 
always do useful things with just the tar-trees and patches. That's sad, 
and possibly a really big downside.

Don't get me wrong - I personally think that the new merge policy is a 
clear improvement, but it does have this downside.

			Linus

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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 19:14 ` Andrew Morton
@ 2005-10-29 19:20   ` Jeff Garzik
  2005-10-29 19:37     ` Linus Torvalds
  0 siblings, 1 reply; 50+ messages in thread
From: Jeff Garzik @ 2005-10-29 19:20 UTC (permalink / raw)
  To: Andrew Morton; +Cc: torvalds, linux-ide, linux-kernel

Andrew Morton wrote:
> Jeff Garzik <jgarzik@pobox.com> wrote:
> 
>>Please pull from 'upstream-linus' branch of
>> master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
>>
>> to obtain misc fixes and cleanups, and to merge
>> the ATA passthru (SMART support) feature.
> 
> 
> Are you sure this doesn't propagate Max Kellermann's "2.6.14-rc4-mm1 and
> later: second ata_piix controller is invisible" regression?
> 
> He did confirm that git-libata-all.patch caused it.

Highly doubtful.

Even so, it's easy, to I'll ask him to test 2.6.14, 2.6.14-git1, and 
(tonight's upcoming) 2.6.14-git2 (with my latest pull included) to see 
if anything breaks.

I think it's some of Alan's changes that aren't yet merged upstream, 
though I could be wrong.

	Jeff




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

* Re: [git patches] 2.6.x libata updates
  2005-10-29 18:22 Jeff Garzik
@ 2005-10-29 19:14 ` Andrew Morton
  2005-10-29 19:20   ` Jeff Garzik
  0 siblings, 1 reply; 50+ messages in thread
From: Andrew Morton @ 2005-10-29 19:14 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, linux-ide, linux-kernel

Jeff Garzik <jgarzik@pobox.com> wrote:
>
> Please pull from 'upstream-linus' branch of
>  master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
> 
>  to obtain misc fixes and cleanups, and to merge
>  the ATA passthru (SMART support) feature.

Are you sure this doesn't propagate Max Kellermann's "2.6.14-rc4-mm1 and
later: second ata_piix controller is invisible" regression?

He did confirm that git-libata-all.patch caused it.

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

* [git patches] 2.6.x libata updates
@ 2005-10-29 18:22 Jeff Garzik
  2005-10-29 19:14 ` Andrew Morton
  0 siblings, 1 reply; 50+ messages in thread
From: Jeff Garzik @ 2005-10-29 18:22 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-ide, linux-kernel


Please pull from 'upstream-linus' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

to obtain misc fixes and cleanups, and to merge
the ATA passthru (SMART support) feature.

 drivers/scsi/libata-core.c  |   18 -
 drivers/scsi/libata-scsi.c  |  790 ++++++++++++++++++++++++++++++++++++--------
 drivers/scsi/libata.h       |    3 
 drivers/scsi/pdc_adma.c     |   28 -
 drivers/scsi/sata_promise.c |    4 
 drivers/scsi/sata_qstor.c   |    2 
 drivers/scsi/sata_sil24.c   |   35 +
 drivers/scsi/sata_svw.c     |   22 -
 drivers/scsi/sata_vsc.c     |   20 -
 include/scsi/scsi.h         |    3 
 10 files changed, 740 insertions(+), 185 deletions(-)

Al Viro:
      sata_sil24 iomem annotations and fixes

Douglas Gilbert:
      [libata scsi] MODE SELECT, strengthen mode sense

Ed Kear:
      libata: add support for Promise SATA 300 TX2plus PDC40775

Jeff Garzik:
      [libata] ATA passthru (arbitrary ATA command execution)
      libata: Update 'passthru' branch for latest libata
      [libata passthru] add (DRIVER_SENSE << 24) to all check-conditions
      [libata passthru] update ATAPI completion for new error handling
      [libata pdc_adma] minor fixes and cleanups
      [libata sata_promise] add pci id
      [libata] ensure ->tf_read() hook reads Status and Error registers

Jeff Raubitschek:
      [libata passthru] fix leak on error

Randy Dunlap:
      libata-core cleanups (updated)

diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index f53d7b8..b1b1c6f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -370,6 +370,8 @@ static void ata_tf_read_pio(struct ata_p
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
+	tf->command = ata_check_status(ap);
+	tf->feature = ata_chk_err(ap);
 	tf->nsect = inb(ioaddr->nsect_addr);
 	tf->lbal = inb(ioaddr->lbal_addr);
 	tf->lbam = inb(ioaddr->lbam_addr);
@@ -402,6 +404,8 @@ static void ata_tf_read_mmio(struct ata_
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
+	tf->command = ata_check_status(ap);
+	tf->feature = ata_chk_err(ap);
 	tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
 	tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
 	tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
@@ -4254,11 +4258,10 @@ int ata_device_add(const struct ata_prob
 
 	DPRINTK("ENTER\n");
 	/* alloc a container for our list of ATA ports (buses) */
-	host_set = kmalloc(sizeof(struct ata_host_set) +
+	host_set = kzalloc(sizeof(struct ata_host_set) +
 			   (ent->n_ports * sizeof(void *)), GFP_KERNEL);
 	if (!host_set)
 		return 0;
-	memset(host_set, 0, sizeof(struct ata_host_set) + (ent->n_ports * sizeof(void *)));
 	spin_lock_init(&host_set->lock);
 
 	host_set->dev = dev;
@@ -4298,10 +4301,8 @@ int ata_device_add(const struct ata_prob
 		count++;
 	}
 
-	if (!count) {
-		kfree(host_set);
-		return 0;
-	}
+	if (!count)
+		goto err_free_ret;
 
 	/* obtain irq, that is shared between channels */
 	if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
@@ -4359,6 +4360,7 @@ err_out:
 		ata_host_remove(host_set->ports[i], 1);
 		scsi_host_put(host_set->ports[i]->host);
 	}
+err_free_ret:
 	kfree(host_set);
 	VPRINTK("EXIT, returning 0\n");
 	return 0;
@@ -4468,15 +4470,13 @@ ata_probe_ent_alloc(struct device *dev, 
 {
 	struct ata_probe_ent *probe_ent;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
 	if (!probe_ent) {
 		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
 		       kobject_name(&(dev->kobj)));
 		return NULL;
 	}
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
-
 	INIT_LIST_HEAD(&probe_ent->node);
 	probe_ent->dev = dev;
 
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 5885888..89a04b1 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -40,14 +40,56 @@
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
+#include <linux/hdreg.h>
 #include <asm/uaccess.h>
 
 #include "libata.h"
 
+#define SECTOR_SIZE	512
+
 typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
 static struct ata_device *
 ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
 
+#define RW_RECOVERY_MPAGE 0x1
+#define RW_RECOVERY_MPAGE_LEN 12
+#define CACHE_MPAGE 0x8
+#define CACHE_MPAGE_LEN 20
+#define CONTROL_MPAGE 0xa
+#define CONTROL_MPAGE_LEN 12
+#define ALL_MPAGES 0x3f
+#define ALL_SUB_MPAGES 0xff
+
+
+static const u8 def_rw_recovery_mpage[] = {
+	RW_RECOVERY_MPAGE,
+	RW_RECOVERY_MPAGE_LEN - 2,
+	(1 << 7) |	/* AWRE, sat-r06 say it shall be 0 */
+	    (1 << 6),	/* ARRE (auto read reallocation) */
+	0,		/* read retry count */
+	0, 0, 0, 0,
+	0,		/* write retry count */
+	0, 0, 0
+};
+
+static const u8 def_cache_mpage[CACHE_MPAGE_LEN] = {
+	CACHE_MPAGE,
+	CACHE_MPAGE_LEN - 2,
+	0,		/* contains WCE, needs to be 0 for logic */
+	0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0,		/* contains DRA, needs to be 0 for logic */
+	0, 0, 0, 0, 0, 0, 0
+};
+
+static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
+	CONTROL_MPAGE,
+	CONTROL_MPAGE_LEN - 2,
+	2,	/* DSENSE=0, GLTSD=1 */
+	0,	/* [QAM+QERR may be 1, see 05-359r1] */
+	0, 0, 0, 0, 0xff, 0xff,
+	0, 30	/* extended self test time, see 05-359r1 */
+};
+
 
 static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
 				   void (*done)(struct scsi_cmnd *))
@@ -86,6 +128,150 @@ int ata_std_bios_param(struct scsi_devic
 	return 0;
 }
 
+/**
+ *	ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl
+ *	@dev: Device to whom we are issuing command
+ *	@arg: User provided data for issuing command
+ *
+ *	LOCKING:
+ *	Defined by the SCSI layer.  We don't really care.
+ *
+ *	RETURNS:
+ *	Zero on success, negative errno on error.
+ */
+
+int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
+{
+	int rc = 0;
+	u8 scsi_cmd[MAX_COMMAND_SIZE];
+	u8 args[4], *argbuf = NULL;
+	int argsize = 0;
+	struct scsi_request *sreq;
+
+	if (NULL == (void *)arg)
+		return -EINVAL;
+
+	if (copy_from_user(args, arg, sizeof(args)))
+		return -EFAULT;
+
+	sreq = scsi_allocate_request(scsidev, GFP_KERNEL);
+	if (!sreq)
+		return -EINTR;
+
+	memset(scsi_cmd, 0, sizeof(scsi_cmd));
+
+	if (args[3]) {
+		argsize = SECTOR_SIZE * args[3];
+		argbuf = kmalloc(argsize, GFP_KERNEL);
+		if (argbuf == NULL) {
+			rc = -ENOMEM;
+			goto error;
+		}
+
+		scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
+		scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
+		                            block count in sector count field */
+		sreq->sr_data_direction = DMA_FROM_DEVICE;
+	} else {
+		scsi_cmd[1]  = (3 << 1); /* Non-data */
+		/* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+		sreq->sr_data_direction = DMA_NONE;
+	}
+
+	scsi_cmd[0] = ATA_16;
+
+	scsi_cmd[4] = args[2];
+	if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */
+		scsi_cmd[6]  = args[3];
+		scsi_cmd[8]  = args[1];
+		scsi_cmd[10] = 0x4f;
+		scsi_cmd[12] = 0xc2;
+	} else {
+		scsi_cmd[6]  = args[1];
+	}
+	scsi_cmd[14] = args[0];
+
+	/* Good values for timeout and retries?  Values below
+	   from scsi_ioctl_send_command() for default case... */
+	scsi_wait_req(sreq, scsi_cmd, argbuf, argsize, (10*HZ), 5);
+
+	if (sreq->sr_result) {
+		rc = -EIO;
+		goto error;
+	}
+
+	/* Need code to retrieve data from check condition? */
+
+	if ((argbuf)
+	 && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize))
+		rc = -EFAULT;
+error:
+	scsi_release_request(sreq);
+
+	if (argbuf)
+		kfree(argbuf);
+
+	return rc;
+}
+
+/**
+ *	ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl
+ *	@dev: Device to whom we are issuing command
+ *	@arg: User provided data for issuing command
+ *
+ *	LOCKING:
+ *	Defined by the SCSI layer.  We don't really care.
+ *
+ *	RETURNS:
+ *	Zero on success, negative errno on error.
+ */
+int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
+{
+	int rc = 0;
+	u8 scsi_cmd[MAX_COMMAND_SIZE];
+	u8 args[7];
+	struct scsi_request *sreq;
+
+	if (NULL == (void *)arg)
+		return -EINVAL;
+
+	if (copy_from_user(args, arg, sizeof(args)))
+		return -EFAULT;
+
+	memset(scsi_cmd, 0, sizeof(scsi_cmd));
+	scsi_cmd[0]  = ATA_16;
+	scsi_cmd[1]  = (3 << 1); /* Non-data */
+	/* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+	scsi_cmd[4]  = args[1];
+	scsi_cmd[6]  = args[2];
+	scsi_cmd[8]  = args[3];
+	scsi_cmd[10] = args[4];
+	scsi_cmd[12] = args[5];
+	scsi_cmd[14] = args[0];
+
+	sreq = scsi_allocate_request(scsidev, GFP_KERNEL);
+	if (!sreq) {
+		rc = -EINTR;
+		goto error;
+	}
+
+	sreq->sr_data_direction = DMA_NONE;
+	/* Good values for timeout and retries?  Values below
+	   from scsi_ioctl_send_command() for default case... */
+	scsi_wait_req(sreq, scsi_cmd, NULL, 0, (10*HZ), 5);
+
+	if (sreq->sr_result) {
+		rc = -EIO;
+		goto error;
+	}
+
+	/* Need code to retrieve data from check condition? */
+
+error:
+	scsi_release_request(sreq);
+	return rc;
+}
+
 int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
 {
 	struct ata_port *ap;
@@ -115,6 +301,16 @@ int ata_scsi_ioctl(struct scsi_device *s
 			return -EINVAL;
 		return 0;
 
+	case HDIO_DRIVE_CMD:
+		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+			return -EACCES;
+		return ata_cmd_ioctl(scsidev, arg);
+
+	case HDIO_DRIVE_TASK:
+		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+			return -EACCES;
+		return ata_task_ioctl(scsidev, arg);
+
 	default:
 		rc = -ENOTTY;
 		break;
@@ -173,23 +369,70 @@ struct ata_queued_cmd *ata_scsi_qc_new(s
 }
 
 /**
+ *	ata_dump_status - user friendly display of error info
+ *	@id: id of the port in question
+ *	@tf: ptr to filled out taskfile
+ *
+ *	Decode and dump the ATA error/status registers for the user so
+ *	that they have some idea what really happened at the non
+ *	make-believe layer.
+ *
+ *	LOCKING:
+ *	inherited from caller
+ */
+void ata_dump_status(unsigned id, struct ata_taskfile *tf)
+{
+	u8 stat = tf->command, err = tf->feature;
+
+	printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat);
+	if (stat & ATA_BUSY) {
+		printk("Busy }\n");	/* Data is not valid in this case */
+	} else {
+		if (stat & 0x40)	printk("DriveReady ");
+		if (stat & 0x20)	printk("DeviceFault ");
+		if (stat & 0x10)	printk("SeekComplete ");
+		if (stat & 0x08)	printk("DataRequest ");
+		if (stat & 0x04)	printk("CorrectedError ");
+		if (stat & 0x02)	printk("Index ");
+		if (stat & 0x01)	printk("Error ");
+		printk("}\n");
+
+		if (err) {
+			printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err);
+			if (err & 0x04)		printk("DriveStatusError ");
+			if (err & 0x80) {
+				if (err & 0x04)	printk("BadCRC ");
+				else		printk("Sector ");
+			}
+			if (err & 0x40)		printk("UncorrectableError ");
+			if (err & 0x10)		printk("SectorIdNotFound ");
+			if (err & 0x02)		printk("TrackZeroNotFound ");
+			if (err & 0x01)		printk("AddrMarkNotFound ");
+			printk("}\n");
+		}
+	}
+}
+
+/**
  *	ata_to_sense_error - convert ATA error to SCSI error
- *	@qc: Command that we are erroring out
  *	@drv_stat: value contained in ATA status register
+ *	@drv_err: value contained in ATA error register
+ *	@sk: the sense key we'll fill out
+ *	@asc: the additional sense code we'll fill out
+ *	@ascq: the additional sense code qualifier we'll fill out
  *
- *	Converts an ATA error into a SCSI error. While we are at it
- *	we decode and dump the ATA error for the user so that they
- *	have some idea what really happened at the non make-believe
- *	layer.
+ *	Converts an ATA error into a SCSI error.  Fill out pointers to
+ *	SK, ASC, and ASCQ bytes for later use in fixed or descriptor
+ *	format sense blocks.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
-
-void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
+void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, 
+			u8 *ascq)
 {
-	struct scsi_cmnd *cmd = qc->scsicmd;
-	u8 err = 0;
+	int i;
+
 	/* Based on the 3ware driver translation table */
 	static unsigned char sense_table[][4] = {
 		/* BBD|ECC|ID|MAR */
@@ -230,96 +473,184 @@ void ata_to_sense_error(struct ata_queue
 		{0x04, 		RECOVERED_ERROR, 0x11, 0x00},	// Recovered ECC error	  Medium error, recovered
 		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
 	};
-	int i = 0;
 
 	/*
 	 *	Is this an error we can process/parse
 	 */
-
-	if(drv_stat & ATA_ERR)
-		/* Read the err bits */
-		err = ata_chk_err(qc->ap);
-
-	/* Display the ATA level error info */
-
-	printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat);
-	if(drv_stat & 0x80)
-	{
-		printk("Busy ");
-		err = 0;	/* Data is not valid in this case */
+	if (drv_stat & ATA_BUSY) {
+		drv_err = 0;	/* Ignore the err bits, they're invalid */
 	}
-	else {
-		if(drv_stat & 0x40)	printk("DriveReady ");
-		if(drv_stat & 0x20)	printk("DeviceFault ");
-		if(drv_stat & 0x10)	printk("SeekComplete ");
-		if(drv_stat & 0x08)	printk("DataRequest ");
-		if(drv_stat & 0x04)	printk("CorrectedError ");
-		if(drv_stat & 0x02)	printk("Index ");
-		if(drv_stat & 0x01)	printk("Error ");
-	}
-	printk("}\n");
-
-	if(err)
-	{
-		printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
-		if(err & 0x04)		printk("DriveStatusError ");
-		if(err & 0x80)
-		{
-			if(err & 0x04)
-				printk("BadCRC ");
-			else
-				printk("Sector ");
+
+	if (drv_err) {
+		/* Look for drv_err */
+		for (i = 0; sense_table[i][0] != 0xFF; i++) {
+			/* Look for best matches first */
+			if ((sense_table[i][0] & drv_err) == 
+			    sense_table[i][0]) {
+				*sk = sense_table[i][1];
+				*asc = sense_table[i][2];
+				*ascq = sense_table[i][3];
+				goto translate_done;
+			}
 		}
-		if(err & 0x40)		printk("UncorrectableError ");
-		if(err & 0x10)		printk("SectorIdNotFound ");
-		if(err & 0x02)		printk("TrackZeroNotFound ");
-		if(err & 0x01)		printk("AddrMarkNotFound ");
-		printk("}\n");
+		/* No immediate match */
+		printk(KERN_WARNING "ata%u: no sense translation for "
+		       "error 0x%02x\n", id, drv_err);
+	}
 
-		/* Should we dump sector info here too ?? */
+	/* Fall back to interpreting status bits */
+	for (i = 0; stat_table[i][0] != 0xFF; i++) {
+		if (stat_table[i][0] & drv_stat) {
+			*sk = stat_table[i][1];
+			*asc = stat_table[i][2];
+			*ascq = stat_table[i][3];
+			goto translate_done;
+		}
 	}
+	/* No error?  Undecoded? */
+	printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", 
+	       id, drv_stat);
+
+	/* For our last chance pick, use medium read error because
+	 * it's much more common than an ATA drive telling you a write
+	 * has failed.
+	 */
+	*sk = MEDIUM_ERROR;
+	*asc = 0x11; /* "unrecovered read error" */
+	*ascq = 0x04; /*  "auto-reallocation failed" */
+
+ translate_done:
+	printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to "
+	       "SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err,
+	       *sk, *asc, *ascq);
+	return;
+}
+
+/*
+ *	ata_gen_ata_desc_sense - Generate check condition sense block.
+ *	@qc: Command that completed.
+ *
+ *	This function is specific to the ATA descriptor format sense
+ *	block specified for the ATA pass through commands.  Regardless
+ *	of whether the command errored or not, return a sense
+ *	block. Copy all controller registers into the sense
+ *	block. Clear sense key, ASC & ASCQ if there is no error.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	struct ata_taskfile *tf = &qc->tf;
+	unsigned char *sb = cmd->sense_buffer;
+	unsigned char *desc = sb + 8;
 
+	memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 
-	/* Look for err */
-	while(sense_table[i][0] != 0xFF)
-	{
-		/* Look for best matches first */
-		if((sense_table[i][0] & err) == sense_table[i][0])
-		{
-			ata_scsi_set_sense(cmd, sense_table[i][1] /* sk */,
-					   sense_table[i][2] /* asc */,
-					   sense_table[i][3] /* ascq */ );
-			return;
-		}
-		i++;
+	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+	/*
+	 * Read the controller registers.
+	 */
+	assert(NULL != qc->ap->ops->tf_read);
+	qc->ap->ops->tf_read(qc->ap, tf);
+
+	/*
+	 * Use ata_to_sense_error() to map status register bits
+	 * onto sense key, asc & ascq.
+	 */
+	if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
+		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
+				   &sb[1], &sb[2], &sb[3]);
+		sb[1] &= 0x0f;
 	}
-	/* No immediate match */
-	if(err)
-		printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err);
 
-	i = 0;
-	/* Fall back to interpreting status bits */
-	while(stat_table[i][0] != 0xFF)
-	{
-		if(stat_table[i][0] & drv_stat)
-		{
-			ata_scsi_set_sense(cmd, sense_table[i][1] /* sk */,
-					   sense_table[i][2] /* asc */,
-					   sense_table[i][3] /* ascq */ );
-			return;
-		}
-		i++;
+	/*
+	 * Sense data is current and format is descriptor.
+	 */
+	sb[0] = 0x72;
+
+	desc[0] = 0x09;
+
+	/*
+	 * Set length of additional sense data.
+	 * Since we only populate descriptor 0, the total
+	 * length is the same (fixed) length as descriptor 0.
+	 */
+	desc[1] = sb[7] = 14;
+
+	/*
+	 * Copy registers into sense buffer.
+	 */
+	desc[2] = 0x00;
+	desc[3] = tf->feature;	/* == error reg */
+	desc[5] = tf->nsect;
+	desc[7] = tf->lbal;
+	desc[9] = tf->lbam;
+	desc[11] = tf->lbah;
+	desc[12] = tf->device;
+	desc[13] = tf->command; /* == status reg */
+
+	/*
+	 * Fill in Extend bit, and the high order bytes
+	 * if applicable.
+	 */
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		desc[2] |= 0x01;
+		desc[4] = tf->hob_nsect;
+		desc[6] = tf->hob_lbal;
+		desc[8] = tf->hob_lbam;
+		desc[10] = tf->hob_lbah;
 	}
-	/* No error ?? */
-	printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
-	/* additional-sense-code[-qualifier] */
-
-	if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
-		ata_scsi_set_sense(cmd, MEDIUM_ERROR, 0x11, 0x4);
-		/* "unrecovered read error" */
-	} else {
-		ata_scsi_set_sense(cmd, MEDIUM_ERROR, 0xc, 0x2);
-		/* "write error - auto-reallocation failed" */
+}
+
+/**
+ *	ata_gen_fixed_sense - generate a SCSI fixed sense block
+ *	@qc: Command that we are erroring out
+ *
+ *	Leverage ata_to_sense_error() to give us the codes.  Fit our
+ *	LBA in here if there's room.
+ *
+ *	LOCKING:
+ *	inherited from caller
+ */
+void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	struct ata_taskfile *tf = &qc->tf;
+	unsigned char *sb = cmd->sense_buffer;
+
+	memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
+
+	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+	/*
+	 * Read the controller registers.
+	 */
+	assert(NULL != qc->ap->ops->tf_read);
+	qc->ap->ops->tf_read(qc->ap, tf);
+
+	/*
+	 * Use ata_to_sense_error() to map status register bits
+	 * onto sense key, asc & ascq.
+	 */
+	if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
+		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
+				   &sb[2], &sb[12], &sb[13]);
+		sb[2] &= 0x0f;
+	}
+
+	sb[0] = 0x70;
+	sb[7] = 0x0a;
+
+	if (tf->flags & ATA_TFLAG_LBA && !(tf->flags & ATA_TFLAG_LBA48)) {
+		/* A small (28b) LBA will fit in the 32b info field */
+		sb[0] |= 0x80;		/* set valid bit */
+		sb[3] = tf->device & 0x0f;
+		sb[4] = tf->lbah;
+		sb[5] = tf->lbam;
+		sb[6] = tf->lbal;
 	}
 }
 
@@ -871,11 +1202,36 @@ nothing_to_do:
 static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
+ 	int need_sense = drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ);
 
-	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
-		ata_to_sense_error(qc, drv_stat);
-	else
-		cmd->result = SAM_STAT_GOOD;
+	/* For ATA pass thru (SAT) commands, generate a sense block if
+	 * user mandated it or if there's an error.  Note that if we
+	 * generate because the user forced us to, a check condition
+	 * is generated and the ATA register values are returned
+	 * whether the command completed successfully or not. If there
+	 * was no error, SK, ASC and ASCQ will all be zero.
+	 */
+	if (((cmd->cmnd[0] == ATA_16) || (cmd->cmnd[0] == ATA_12)) &&
+ 	    ((cmd->cmnd[2] & 0x20) || need_sense)) {
+ 		ata_gen_ata_desc_sense(qc);
+	} else {
+		if (!need_sense) {
+			cmd->result = SAM_STAT_GOOD;
+		} else {
+			/* TODO: decide which descriptor format to use
+			 * for 48b LBA devices and call that here
+			 * instead of the fixed desc, which is only
+			 * good for smaller LBA (and maybe CHS?)
+			 * devices.
+			 */
+			ata_gen_fixed_sense(qc);
+		}
+	}
+
+	if (need_sense) {
+		/* The ata_gen_..._sense routines fill in tf */
+		ata_dump_status(qc->ap->id, &qc->tf);
+	}
 
 	qc->scsidone(cmd);
 
@@ -1266,13 +1622,9 @@ static void ata_msense_push(u8 **ptr_io,
 static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
 				       const u8 *last)
 {
-	u8 page[] = {
-		0x8,				/* page code */
-		0x12,				/* page length */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 10 zeroes */
-		0, 0, 0, 0, 0, 0, 0, 0		/* 8 zeroes */
-	};
+	u8 page[CACHE_MPAGE_LEN];
 
+	memcpy(page, def_cache_mpage, sizeof(page));
 	if (ata_id_wcache_enabled(id))
 		page[2] |= (1 << 2);	/* write cache enable */
 	if (!ata_id_rahead_enabled(id))
@@ -1296,15 +1648,9 @@ static unsigned int ata_msense_caching(u
 
 static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
 {
-	const u8 page[] = {0xa, 0xa, 6, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 30};
-
-	/* byte 2: set the descriptor format sense data bit (bit 2)
-	 * since we need to support returning this format for SAT
-	 * commands and any SCSI commands against a 48b LBA device.
-	 */
-
-	ata_msense_push(ptr_io, last, page, sizeof(page));
-	return sizeof(page);
+	ata_msense_push(ptr_io, last, def_control_mpage,
+			sizeof(def_control_mpage));
+	return sizeof(def_control_mpage);
 }
 
 /**
@@ -1321,15 +1667,10 @@ static unsigned int ata_msense_ctl_mode(
 
 static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
 {
-	const u8 page[] = {
-		0x1,			  /* page code */
-		0xa,			  /* page length */
-		(1 << 7) | (1 << 6),	  /* note auto r/w reallocation */
-		0, 0, 0, 0, 0, 0, 0, 0, 0 /* 9 zeroes */
-	};
 
-	ata_msense_push(ptr_io, last, page, sizeof(page));
-	return sizeof(page);
+	ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
+			sizeof(def_rw_recovery_mpage));
+	return sizeof(def_rw_recovery_mpage);
 }
 
 /**
@@ -1338,7 +1679,9 @@ static unsigned int ata_msense_rw_recove
  *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *	@buflen: Response buffer length.
  *
- *	Simulate MODE SENSE commands.
+ *	Simulate MODE SENSE commands. Assume this is invoked for direct
+ *	access devices (e.g. disks) only. There should be no block
+ *	descriptor for other device types.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
@@ -1348,15 +1691,22 @@ unsigned int ata_scsiop_mode_sense(struc
 				  unsigned int buflen)
 {
 	u8 *scsicmd = args->cmd->cmnd, *p, *last;
-	unsigned int page_control, six_byte, output_len;
+	const u8 sat_blk_desc[] = {
+		0, 0, 0, 0,	/* number of blocks: sat unspecified */
+		0,
+		0, 0x2, 0x0	/* block length: 512 bytes */
+	};
+	u8 pg, spg;
+	unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
 
 	VPRINTK("ENTER\n");
 
 	six_byte = (scsicmd[0] == MODE_SENSE);
-
-	/* we only support saved and current values (which we treat
-	 * in the same manner)
+	ebd = !(scsicmd[1] & 0x8);      /* dbd bit inverted == edb */
+	/*
+	 * LLBA bit in msense(10) ignored (compliant)
 	 */
+
 	page_control = scsicmd[2] >> 6;
 	switch (page_control) {
 	case 0: /* current */
@@ -1369,29 +1719,42 @@ unsigned int ata_scsiop_mode_sense(struc
 		goto invalid_fld;
 	}
 
-	if (six_byte)
-		output_len = 4;
-	else
-		output_len = 8;
+	if (six_byte) {
+		output_len = 4 + (ebd ? 8 : 0);
+		alloc_len = scsicmd[4];
+	} else {
+		output_len = 8 + (ebd ? 8 : 0);
+		alloc_len = (scsicmd[7] << 8) + scsicmd[8];
+	}
+	minlen = (alloc_len < buflen) ? alloc_len : buflen;
 
 	p = rbuf + output_len;
-	last = rbuf + buflen - 1;
+	last = rbuf + minlen - 1;
+
+	pg = scsicmd[2] & 0x3f;
+	spg = scsicmd[3];
+	/*
+	 * No mode subpages supported (yet) but asking for _all_
+	 * subpages may be valid
+	 */
+	if (spg && (spg != ALL_SUB_MPAGES))
+		goto invalid_fld;
 
-	switch(scsicmd[2] & 0x3f) {
-	case 0x01:		/* r/w error recovery */
+	switch(pg) {
+	case RW_RECOVERY_MPAGE:
 		output_len += ata_msense_rw_recovery(&p, last);
 		break;
 
-	case 0x08:		/* caching */
+	case CACHE_MPAGE:
 		output_len += ata_msense_caching(args->id, &p, last);
 		break;
 
-	case 0x0a: {		/* control mode */
+	case CONTROL_MPAGE: {
 		output_len += ata_msense_ctl_mode(&p, last);
 		break;
 		}
 
-	case 0x3f:		/* all pages */
+	case ALL_MPAGES:
 		output_len += ata_msense_rw_recovery(&p, last);
 		output_len += ata_msense_caching(args->id, &p, last);
 		output_len += ata_msense_ctl_mode(&p, last);
@@ -1401,15 +1764,31 @@ unsigned int ata_scsiop_mode_sense(struc
 		goto invalid_fld;
 	}
 
+	if (minlen < 1)
+		return 0;
 	if (six_byte) {
 		output_len--;
 		rbuf[0] = output_len;
+		if (ebd) {
+			if (minlen > 3)
+				rbuf[3] = sizeof(sat_blk_desc);
+			if (minlen > 11)
+				memcpy(rbuf + 4, sat_blk_desc,
+				       sizeof(sat_blk_desc));
+		}
 	} else {
 		output_len -= 2;
 		rbuf[0] = output_len >> 8;
-		rbuf[1] = output_len;
+		if (minlen > 1)
+			rbuf[1] = output_len;
+		if (ebd) {
+			if (minlen > 7)
+				rbuf[7] = sizeof(sat_blk_desc);
+			if (minlen > 15)
+				memcpy(rbuf + 8, sat_blk_desc,
+				       sizeof(sat_blk_desc));
+		}
 	}
-
 	return 0;
 
 invalid_fld:
@@ -1623,7 +2002,12 @@ static int atapi_qc_complete(struct ata_
 	VPRINTK("ENTER, drv_stat == 0x%x\n", drv_stat);
 
 	if (unlikely(drv_stat & (ATA_BUSY | ATA_DRQ)))
-		ata_to_sense_error(qc, drv_stat);
+		/* FIXME: not quite right; we don't want the
+		 * translation of taskfile registers into
+		 * a sense descriptors, since that's only
+		 * correct for ATA, not ATAPI
+		 */
+		ata_gen_ata_desc_sense(qc);
 
 	else if (unlikely(drv_stat & ATA_ERR)) {
 		DPRINTK("request check condition\n");
@@ -1782,6 +2166,143 @@ ata_scsi_find_dev(struct ata_port *ap, c
 	return dev;
 }
 
+/*
+ *	ata_scsi_map_proto - Map pass-thru protocol value to taskfile value.
+ *	@byte1: Byte 1 from pass-thru CDB.
+ *
+ *	RETURNS:
+ *	ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise.
+ */
+static u8
+ata_scsi_map_proto(u8 byte1)
+{
+	switch((byte1 & 0x1e) >> 1) {
+		case 3:		/* Non-data */
+			return ATA_PROT_NODATA;
+
+		case 6:		/* DMA */
+			return ATA_PROT_DMA;
+
+		case 4:		/* PIO Data-in */
+		case 5:		/* PIO Data-out */
+			if (byte1 & 0xe0) {
+				return ATA_PROT_PIO_MULT;
+			}
+			return ATA_PROT_PIO;
+
+		case 10:	/* Device Reset */
+		case 0:		/* Hard Reset */
+		case 1:		/* SRST */
+		case 2:		/* Bus Idle */
+		case 7:		/* Packet */
+		case 8:		/* DMA Queued */
+		case 9:		/* Device Diagnostic */
+		case 11:	/* UDMA Data-in */
+		case 12:	/* UDMA Data-Out */
+		case 13:	/* FPDMA */
+		default:	/* Reserved */
+			break;
+	}
+
+	return ATA_PROT_UNKNOWN;
+}
+
+/**
+ *	ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
+ *	@qc: command structure to be initialized
+ *	@cmd: SCSI command to convert
+ *
+ *	Handles either 12 or 16-byte versions of the CDB.
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on failure.
+ */
+static unsigned int
+ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
+{
+	struct ata_taskfile *tf = &(qc->tf);
+	struct scsi_cmnd *cmd = qc->scsicmd;
+
+	if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN)
+		return 1;
+
+	/*
+	 * 12 and 16 byte CDBs use different offsets to
+	 * provide the various register values.
+	 */
+	if (scsicmd[0] == ATA_16) {
+		/*
+		 * 16-byte CDB - may contain extended commands.
+		 *
+		 * If that is the case, copy the upper byte register values.
+		 */
+		if (scsicmd[1] & 0x01) {
+			tf->hob_feature = scsicmd[3];
+			tf->hob_nsect = scsicmd[5];
+			tf->hob_lbal = scsicmd[7];
+			tf->hob_lbam = scsicmd[9];
+			tf->hob_lbah = scsicmd[11];
+			tf->flags |= ATA_TFLAG_LBA48;
+		} else
+			tf->flags &= ~ATA_TFLAG_LBA48;
+
+		/*
+		 * Always copy low byte, device and command registers.
+		 */
+		tf->feature = scsicmd[4];
+		tf->nsect = scsicmd[6];
+		tf->lbal = scsicmd[8];
+		tf->lbam = scsicmd[10];
+		tf->lbah = scsicmd[12];
+		tf->device = scsicmd[13];
+		tf->command = scsicmd[14];
+	} else {
+		/*
+		 * 12-byte CDB - incapable of extended commands.
+		 */
+		tf->flags &= ~ATA_TFLAG_LBA48;
+
+		tf->feature = scsicmd[3];
+		tf->nsect = scsicmd[4];
+		tf->lbal = scsicmd[5];
+		tf->lbam = scsicmd[6];
+		tf->lbah = scsicmd[7];
+		tf->device = scsicmd[8];
+		tf->command = scsicmd[9];
+	}
+
+	/*
+	 * Filter SET_FEATURES - XFER MODE command -- otherwise,
+	 * SET_FEATURES - XFER MODE must be preceded/succeeded
+	 * by an update to hardware-specific registers for each
+	 * controller (i.e. the reason for ->set_piomode(),
+	 * ->set_dmamode(), and ->post_set_mode() hooks).
+	 */
+	if ((tf->command == ATA_CMD_SET_FEATURES)
+	 && (tf->feature == SETFEATURES_XFER))
+		return 1;
+
+	/*
+	 * Set flags so that all registers will be written,
+	 * and pass on write indication (used for PIO/DMA
+	 * setup.)
+	 */
+	tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE);
+
+	if (cmd->sc_data_direction == DMA_TO_DEVICE)
+		tf->flags |= ATA_TFLAG_WRITE;
+
+	/*
+	 * Set transfer length.
+	 *
+	 * TODO: find out if we need to do more here to
+	 *       cover scatter/gather case.
+	 */
+	qc->nsect = cmd->bufflen / ATA_SECT_SIZE;
+
+	return 0;
+}
+
 /**
  *	ata_get_xlat_func - check if SCSI to ATA translation is possible
  *	@dev: ATA device
@@ -1814,6 +2335,11 @@ static inline ata_xlat_func_t ata_get_xl
 	case VERIFY:
 	case VERIFY_16:
 		return ata_scsi_verify_xlat;
+
+	case ATA_12:
+	case ATA_16:
+		return ata_scsi_pass_thru;
+
 	case START_STOP:
 		return ata_scsi_start_stop_xlat;
 	}
@@ -1972,7 +2498,7 @@ void ata_scsi_simulate(u16 *id,
 			ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
 			break;
 
-		/* mandantory commands we haven't implemented yet */
+		/* mandatory commands we haven't implemented yet */
 		case REQUEST_SENSE:
 
 		/* all other commands */
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 3d60190..65c264b 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -50,13 +50,14 @@ extern void ata_dev_select(struct ata_po
                            unsigned int wait, unsigned int can_sleep);
 extern void ata_tf_to_host_nolock(struct ata_port *ap, const struct ata_taskfile *tf);
 extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
+extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
+extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
 
 
 /* libata-scsi.c */
 extern void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
 			 struct scsi_cmnd *cmd);
 extern void ata_scsi_scan_host(struct ata_port *ap);
-extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat);
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 			       unsigned int buflen);
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index 9820f27..af99feb 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pdc_adma"
-#define DRV_VERSION	"0.01"
+#define DRV_VERSION	"0.03"
 
 /* macro to calculate base address for ATA regs */
 #define ADMA_ATA_REGS(base,port_no)	((base) + ((port_no) * 0x40))
@@ -79,7 +79,6 @@ enum {
 	aNIEN			= (1 << 8), /* irq mask: 1==masked */
 	aGO			= (1 << 7), /* packet trigger ("Go!") */
 	aRSTADM			= (1 << 5), /* ADMA logic reset */
-	aRSTA			= (1 << 2), /* ATA hard reset */
 	aPIOMD4			= 0x0003,   /* PIO mode 4 */
 
 	/* ADMA_STATUS register bits */
@@ -452,24 +451,25 @@ static inline unsigned int adma_intr_pkt
 		struct adma_port_priv *pp;
 		struct ata_queued_cmd *qc;
 		void __iomem *chan = ADMA_REGS(mmio_base, port_no);
-		u8 drv_stat, status = readb(chan + ADMA_STATUS);
+		u8 drv_stat = 0, status = readb(chan + ADMA_STATUS);
 
 		if (status == 0)
 			continue;
 		handled = 1;
 		adma_enter_reg_mode(ap);
-		if ((ap->flags & ATA_FLAG_PORT_DISABLED))
+		if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
 			continue;
 		pp = ap->private_data;
 		if (!pp || pp->state != adma_state_pkt)
 			continue;
 		qc = ata_qc_from_tag(ap, ap->active_tag);
-		drv_stat = 0;
-		if ((status & (aPERR | aPSD | aUIRQ)))
-			drv_stat = ATA_ERR;
-		else if (pp->pkt[0] != cDONE)
-			drv_stat = ATA_ERR;
-		ata_qc_complete(qc, drv_stat);
+		if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+			if ((status & (aPERR | aPSD | aUIRQ)))
+				drv_stat = ATA_ERR;
+			else if (pp->pkt[0] != cDONE)
+				drv_stat = ATA_ERR;
+			ata_qc_complete(qc, drv_stat);
+		}
 	}
 	return handled;
 }
@@ -490,7 +490,7 @@ static inline unsigned int adma_intr_mmi
 			if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
 
 				/* check main status, clearing INTRQ */
-				u8 status = ata_chk_status(ap);
+				u8 status = ata_check_status(ap);
 				if ((status & ATA_BUSY))
 					continue;
 				DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
@@ -561,15 +561,15 @@ static int adma_port_start(struct ata_po
 	if ((pp->pkt_dma & 7) != 0) {
 		printk("bad alignment for pp->pkt_dma: %08x\n",
 						(u32)pp->pkt_dma);
-		goto err_out_kfree2;
+		dma_free_coherent(dev, ADMA_PKT_BYTES,
+						pp->pkt, pp->pkt_dma);
+		goto err_out_kfree;
 	}
 	memset(pp->pkt, 0, ADMA_PKT_BYTES);
 	ap->private_data = pp;
 	adma_reinit_engine(ap);
 	return 0;
 
-err_out_kfree2:
-	kfree(pp);
 err_out_kfree:
 	kfree(pp);
 err_out:
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index eee93b0..63911f1 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -195,6 +195,8 @@ static struct ata_port_info pdc_port_inf
 static struct pci_device_id pdc_ata_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_2037x },
+	{ PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_2037x },
 	{ PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_2037x },
 	{ PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -207,6 +209,8 @@ static struct pci_device_id pdc_ata_pci_
 	  board_2037x },
 	{ PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_2037x },
+	{ PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_2037x },
 
 	{ PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20319 },
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index 250dafa..1aaf330 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -433,7 +433,7 @@ static inline unsigned int qs_intr_mmio(
 			if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
 
 				/* check main status, clearing INTRQ */
-				u8 status = ata_chk_status(ap);
+				u8 status = ata_check_status(ap);
 				if ((status & ATA_BUSY))
 					continue;
 				DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 32d730b..51855d3 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -220,8 +220,8 @@ struct sil24_port_priv {
 
 /* ap->host_set->private_data */
 struct sil24_host_priv {
-	void *host_base;	/* global controller control (128 bytes @BAR0) */
-	void *port_base;	/* port registers (4 * 8192 bytes @BAR2) */
+	void __iomem *host_base;	/* global controller control (128 bytes @BAR0) */
+	void __iomem *port_base;	/* port registers (4 * 8192 bytes @BAR2) */
 };
 
 static u8 sil24_check_status(struct ata_port *ap);
@@ -349,10 +349,12 @@ static struct ata_port_info sil24_port_i
 static inline void sil24_update_tf(struct ata_port *ap)
 {
 	struct sil24_port_priv *pp = ap->private_data;
-	void *port = (void *)ap->ioaddr.cmd_addr;
-	struct sil24_prb *prb = port;
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	struct sil24_prb __iomem *prb = port;
+	u8 fis[6 * 4];
 
-	ata_tf_from_fis(prb->fis, &pp->tf);
+	memcpy_fromio(fis, prb->fis, 6 * 4);
+	ata_tf_from_fis(fis, &pp->tf);
 }
 
 static u8 sil24_check_status(struct ata_port *ap)
@@ -376,9 +378,9 @@ static int sil24_scr_map[] = {
 
 static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
 {
-	void *scr_addr = (void *)ap->ioaddr.scr_addr;
+	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
 	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
-		void *addr;
+		void __iomem *addr;
 		addr = scr_addr + sil24_scr_map[sc_reg] * 4;
 		return readl(scr_addr + sil24_scr_map[sc_reg] * 4);
 	}
@@ -387,9 +389,9 @@ static u32 sil24_scr_read(struct ata_por
 
 static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
 {
-	void *scr_addr = (void *)ap->ioaddr.scr_addr;
+	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
 	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
-		void *addr;
+		void __iomem *addr;
 		addr = scr_addr + sil24_scr_map[sc_reg] * 4;
 		writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
 	}
@@ -454,7 +456,7 @@ static void sil24_qc_prep(struct ata_que
 static int sil24_qc_issue(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void *port = (void *)ap->ioaddr.cmd_addr;
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
 	struct sil24_port_priv *pp = ap->private_data;
 	dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block);
 
@@ -467,7 +469,7 @@ static void sil24_irq_clear(struct ata_p
 	/* unused */
 }
 
-static int __sil24_reset_controller(void *port)
+static int __sil24_reset_controller(void __iomem *port)
 {
 	int cnt;
 	u32 tmp;
@@ -493,7 +495,7 @@ static void sil24_reset_controller(struc
 {
 	printk(KERN_NOTICE DRV_NAME
 	       " ata%u: resetting controller...\n", ap->id);
-	if (__sil24_reset_controller((void *)ap->ioaddr.cmd_addr))
+	if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr))
                 printk(KERN_ERR DRV_NAME
                        " ata%u: failed to reset controller\n", ap->id);
 }
@@ -527,7 +529,7 @@ static void sil24_error_intr(struct ata_
 {
 	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
 	struct sil24_port_priv *pp = ap->private_data;
-	void *port = (void *)ap->ioaddr.cmd_addr;
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
 	u32 irq_stat, cmd_err, sstatus, serror;
 
 	irq_stat = readl(port + PORT_IRQ_STAT);
@@ -574,7 +576,7 @@ static void sil24_error_intr(struct ata_
 static inline void sil24_host_intr(struct ata_port *ap)
 {
 	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
-	void *port = (void *)ap->ioaddr.cmd_addr;
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
 	u32 slot_stat;
 
 	slot_stat = readl(port + PORT_SLOT_STAT);
@@ -689,7 +691,8 @@ static int sil24_init_one(struct pci_dev
 	struct ata_port_info *pinfo = &sil24_port_info[board_id];
 	struct ata_probe_ent *probe_ent = NULL;
 	struct sil24_host_priv *hpriv = NULL;
-	void *host_base = NULL, *port_base = NULL;
+	void __iomem *host_base = NULL;
+	void __iomem *port_base = NULL;
 	int i, rc;
 
 	if (!printed_version++)
@@ -771,7 +774,7 @@ static int sil24_init_one(struct pci_dev
 	writel(0, host_base + HOST_CTRL);
 
 	for (i = 0; i < probe_ent->n_ports; i++) {
-		void *port = port_base + i * PORT_REGS_SIZE;
+		void __iomem *port = port_base + i * PORT_REGS_SIZE;
 		unsigned long portu = (unsigned long)port;
 		u32 tmp;
 		int cnt;
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index e0f9570..46208f5 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -84,6 +84,8 @@
 /* Port stride */
 #define K2_SATA_PORT_OFFSET		0x100
 
+static u8 k2_stat_check_status(struct ata_port *ap);
+
 
 static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
@@ -136,16 +138,24 @@ static void k2_sata_tf_load(struct ata_p
 static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
-	u16 nsect, lbal, lbam, lbah;
+	u16 nsect, lbal, lbam, lbah, feature;
 
-	nsect = tf->nsect = readw(ioaddr->nsect_addr);
-	lbal = tf->lbal = readw(ioaddr->lbal_addr);
-	lbam = tf->lbam = readw(ioaddr->lbam_addr);
-	lbah = tf->lbah = readw(ioaddr->lbah_addr);
+	tf->command = k2_stat_check_status(ap);
 	tf->device = readw(ioaddr->device_addr);
+	feature = readw(ioaddr->error_addr);
+	nsect = readw(ioaddr->nsect_addr);
+	lbal = readw(ioaddr->lbal_addr);
+	lbam = readw(ioaddr->lbam_addr);
+	lbah = readw(ioaddr->lbah_addr);
+
+	tf->feature = feature;
+	tf->nsect = nsect;
+	tf->lbal = lbal;
+	tf->lbam = lbam;
+	tf->lbah = lbah;
 
 	if (tf->flags & ATA_TFLAG_LBA48) {
-		tf->hob_feature = readw(ioaddr->error_addr) >> 8;
+		tf->hob_feature = feature >> 8;
 		tf->hob_nsect = nsect >> 8;
 		tf->hob_lbal = lbal >> 8;
 		tf->hob_lbam = lbam >> 8;
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 5af05fd..54273e0 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -153,16 +153,24 @@ static void vsc_sata_tf_load(struct ata_
 static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
-	u16 nsect, lbal, lbam, lbah;
+	u16 nsect, lbal, lbam, lbah, feature;
 
-	nsect = tf->nsect = readw(ioaddr->nsect_addr);
-	lbal = tf->lbal = readw(ioaddr->lbal_addr);
-	lbam = tf->lbam = readw(ioaddr->lbam_addr);
-	lbah = tf->lbah = readw(ioaddr->lbah_addr);
+	tf->command = ata_check_status(ap);
 	tf->device = readw(ioaddr->device_addr);
+	feature = readw(ioaddr->error_addr);
+	nsect = readw(ioaddr->nsect_addr);
+	lbal = readw(ioaddr->lbal_addr);
+	lbam = readw(ioaddr->lbam_addr);
+	lbah = readw(ioaddr->lbah_addr);
+
+	tf->feature = feature;
+	tf->nsect = nsect;
+	tf->lbal = lbal;
+	tf->lbam = lbam;
+	tf->lbah = lbah;
 
 	if (tf->flags & ATA_TFLAG_LBA48) {
-		tf->hob_feature = readb(ioaddr->error_addr);
+		tf->hob_feature = feature >> 8;
 		tf->hob_nsect = nsect >> 8;
 		tf->hob_lbal = lbal >> 8;
 		tf->hob_lbam = lbam >> 8;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index b361172..6cb1e27 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -116,6 +116,9 @@ extern const char *const scsi_device_typ
 /* values for service action in */
 #define	SAI_READ_CAPACITY_16  0x10
 
+/* Values for T10/04-262r7 */
+#define	ATA_16		      0x85	/* 16-byte pass-thru */
+#define	ATA_12		      0xa1	/* 12-byte pass-thru */
 
 /*
  *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft

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

* Re: [git patches] 2.6.x libata updates
  2005-10-28  0:49 Jeff Garzik
@ 2005-10-28 16:08 ` Linus Torvalds
  0 siblings, 0 replies; 50+ messages in thread
From: Linus Torvalds @ 2005-10-28 16:08 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Andrew Morton, linux-ide, linux-kernel



On Thu, 27 Oct 2005, Jeff Garzik wrote:
> 
> Please pull from 'upstream' branch of
> master.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

Btw, that would be missing a ':'

Pulled, pushed out.

		Linus

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

* [git patches] 2.6.x libata updates
@ 2005-10-28  0:49 Jeff Garzik
  2005-10-28 16:08 ` Linus Torvalds
  0 siblings, 1 reply; 50+ messages in thread
From: Jeff Garzik @ 2005-10-28  0:49 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-ide, linux-kernel


Please pull from 'upstream' branch of
master.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

Broad changes:
* improved PATA support
* new drivers: pdc_adma, sata_sil24
* vastly improved sata_mv driver (60xx only, alas)
* small cleanups etc.


 Documentation/DocBook/libata.tmpl | 1072 +++++++++++++++++++++++++++++++++++
 drivers/scsi/Kconfig              |   22 
 drivers/scsi/Makefile             |    2 
 drivers/scsi/ahci.c               |   41 -
 drivers/scsi/ata_piix.c           |    4 
 drivers/scsi/libata-core.c        |  876 +++++++++++++++++++----------
 drivers/scsi/libata-scsi.c        |  736 +++++++++++++++++-------
 drivers/scsi/libata.h             |   19 
 drivers/scsi/pdc_adma.c           |  739 ++++++++++++++++++++++++
 drivers/scsi/sata_mv.c            | 1145 +++++++++++++++++++++++++++++++-------
 drivers/scsi/sata_nv.c            |    8 
 drivers/scsi/sata_promise.c       |   26 
 drivers/scsi/sata_qstor.c         |    8 
 drivers/scsi/sata_sil.c           |    6 
 drivers/scsi/sata_sil24.c         |  875 +++++++++++++++++++++++++++++
 drivers/scsi/sata_sis.c           |    4 
 drivers/scsi/sata_svw.c           |    4 
 drivers/scsi/sata_sx4.c           |   29 
 drivers/scsi/sata_uli.c           |    4 
 drivers/scsi/sata_via.c           |    4 
 drivers/scsi/sata_vsc.c           |   14 
 include/linux/ata.h               |   41 +
 include/linux/libata.h            |  113 ++-
 23 files changed, 4973 insertions(+), 819 deletions(-)

Al Viro:
      iomem annotations (sata_nv)
      iomem annotations (ahci)
      iomem annotations (sata_promise)
      enum safety (sata_qstor)
      iomem annotations (sata_sx4)
      iomem annotations (sata_sil)
      iomem annotations (sata_vsc)

Alan Cox:
      ata: re-order speeds sensibly.
      libata: bitmask based pci init functions for one or two ports
      libata: handle early device PIO modes correctly
      Add ide-timing functionality to libata.
      [libata] ata_timing fix

Albert Lee:
      [libata] C/H/S support, for older devices
      libata: indent and whitespace change
      libata: rename host states
      libata: minor whitespace, comment, debug message updates
      [libata scsi] tidy up SCSI lba and xfer len calculations
      [libata scsi] add CHS support to ata_scsi_start_stop_xlat()
      libata CHS: move the initialization of taskfile LBA flags (revise #6)
      libata CHS: calculate read/write commands and protocol on the fly (revise #6)
      libata CHS: reread device identify info (revise #6)

Andy Currid:
      Fix sata_nv handling of NVIDIA MCP51/55

Brett Russ:
      libata: Marvell SATA support (DMA mode) (resend: v0.22)
      libata: Marvell spinlock fixes and simplification
      libata: Marvell function headers
      libata: Marvell endian fix

Douglas Gilbert:
      [libata scsi] add ata_scsi_set_sense helper
      [libata scsi] improve scsi error handling with ata_scsi_set_sense()

Jeff Garzik:
      libata: move EH docs to separate DocBook chapter
      [libata] improve device scan
      [libata] improve device scan even more
      libata: add ata_ratelimit(), use it in AHCI driver irq handler
      libata: ATAPI command completion tweaks and notes
      libata: move atapi_request_sense() to libata-scsi module
      [libata sata_mv] fix warning
      libata: minor cleanups
      [libata pdc_adma] license update, minor cleanup
      libata: turn on block layer clustering
      libata: const-ification bombing run

Mark Lord:
      libata: add new driver pdc_adma for PDC ADMA ATA cards

Randy Dunlap:
      libata kernel-doc fixes

Tejun Heo:
      SATA: rewritten sil24 driver
      sil24: add FIXME comment above ata_device_add
      sil24: remove irq disable code on spurious interrupt
      sil24: add testing for PCI fault
      sil24: move error handling out of hot interrupt path
      sil24: remove PORT_TF
      sil24: replace pp->port w/ ap->ioaddr.cmd_addr
      sil24: fix PORT_CTRL_STAT constants
      sil24: add more comments for constants
      sil24: initialization fix
      libata EH document update
      libata: add ATA exceptions chapter to doc
      sil24: ignore non-error exception irqs
      sil24: remove CMDERR clearing
      sil24: implement proper TF register reading & caching
      sil24: implement tf_read callback
      [libata sata_sil24] nit pickings
      [libata sata_sil24] add support for 3131/3531


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

* [git patches] 2.6.x libata updates
@ 2005-08-29  0:25 Jeff Garzik
  0 siblings, 0 replies; 50+ messages in thread
From: Jeff Garzik @ 2005-08-29  0:25 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton; +Cc: linux-ide, linux-kernel


Please pull from the 'upstream' branch of
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

to obtain the changes described in the following diffstat/shortlog/patch.

It's mostly fixes for uncommon paths (PIO, ATAPI), and new PCI IDs.
Stuff not urgent enough for 2.6.13.


 drivers/scsi/ahci.c         |   12 +-
 drivers/scsi/ata_piix.c     |   14 +-
 drivers/scsi/libata-core.c  |  249 ++++++++++++++++++++++++++++++++++++--------
 drivers/scsi/libata-scsi.c  |   66 +++++++++++
 drivers/scsi/libata.h       |    2 
 drivers/scsi/sata_nv.c      |   24 +++-
 drivers/scsi/sata_promise.c |   12 +-
 drivers/scsi/sata_qstor.c   |   12 +-
 drivers/scsi/sata_sil.c     |   36 ++++--
 drivers/scsi/sata_sis.c     |    2 
 drivers/scsi/sata_svw.c     |   10 -
 drivers/scsi/sata_sx4.c     |  146 +++++++++++++------------
 drivers/scsi/sata_uli.c     |    2 
 drivers/scsi/sata_via.c     |    2 
 drivers/scsi/sata_vsc.c     |    5 
 include/linux/ata.h         |    2 
 include/linux/libata.h      |    8 -
 include/linux/pci_ids.h     |    1 
 18 files changed, 451 insertions(+), 154 deletions(-)


Alan Cox:
  libata: typo
  libata: regularize dma_start/stop arguments

Albert Lee:
  libata ata_data_xfer() fix
  libata handle the case when device returns/needs extra data
  libata: Clear ATA_QCFLAG_ACTIVE flag before calling the completion callback

Daniel Drake:
  sata_nv: Support MCP51/MCP55 device IDs
  sata_promise: Add PDC40519 id

Douglas Gilbert:
  [libata scsi] add START STOP UNIT translation

Jason Gaston:
  ahci: AHCI mode SATA patch for Intel ICH7-M DH

Jeff Garzik:
  libata: trim trailing whitespace.
  libata: fix EH locking
  [libata sata_sil] list documentation URL, since its public
  libata: fix a few alan-isms
  [libata scsi] fix read/write translation edge cases

Martin Wilck:
  Fix HD activity LED with ahci

Otto Meier:
  sata_promise: Add PDC40718 id

Tejun Heo:
  fix atapi_packet_task vs. intr race (take 2)
  libata: implement ata_poll_qc_complete and use it in polling functions
  sil: apply M15W quirk selectively (take 2)



diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -269,6 +269,8 @@ static struct pci_device_id ahci_pci_tbl
 	  board_ahci }, /* ESB2 */
 	{ PCI_VENDOR_ID_INTEL, 0x2683, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ESB2 */
+	{ PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH7-M DH */
 	{ }	/* terminate list */
 };
 
@@ -584,12 +586,16 @@ static void ahci_intr_error(struct ata_p
 
 static void ahci_eng_timeout(struct ata_port *ap)
 {
-	void *mmio = ap->host_set->mmio_base;
+	struct ata_host_set *host_set = ap->host_set;
+	void *mmio = host_set->mmio_base;
 	void *port_mmio = ahci_port_base(mmio, ap->port_no);
 	struct ata_queued_cmd *qc;
+	unsigned long flags;
 
 	DPRINTK("ENTER\n");
 
+	spin_lock_irqsave(&host_set->lock, flags);
+
 	ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT));
 
 	qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -607,6 +613,7 @@ static void ahci_eng_timeout(struct ata_
 		ata_qc_complete(qc, ATA_ERR);
 	}
 
+	spin_unlock_irqrestore(&host_set->lock, flags);
 }
 
 static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
@@ -696,9 +703,6 @@ static int ahci_qc_issue(struct ata_queu
 	struct ata_port *ap = qc->ap;
 	void *port_mmio = (void *) ap->ioaddr.cmd_addr;
 
-	writel(1, port_mmio + PORT_SCR_ACT);
-	readl(port_mmio + PORT_SCR_ACT);	/* flush */
-
 	writel(1, port_mmio + PORT_CMD_ISSUE);
 	readl(port_mmio + PORT_CMD_ISSUE);	/* flush */
 
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -629,13 +629,13 @@ static int piix_init_one (struct pci_dev
 	port_info[1] = NULL;
 
 	if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
-               u8 tmp;
-               pci_read_config_byte(pdev, PIIX_SCC, &tmp);
-               if (tmp == PIIX_AHCI_DEVICE) {
-                       int rc = piix_disable_ahci(pdev);
-                       if (rc)
-                           return rc;
-               }
+		u8 tmp;
+		pci_read_config_byte(pdev, PIIX_SCC, &tmp);
+		if (tmp == PIIX_AHCI_DEVICE) {
+			int rc = piix_disable_ahci(pdev);
+			if (rc)
+				return rc;
+		}
 	}
 
 	if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1304,12 +1304,12 @@ static inline u8 ata_dev_knobble(struct 
 /**
  * 	ata_dev_config - Run device specific handlers and check for
  * 			 SATA->PATA bridges
- * 	@ap: Bus 
+ * 	@ap: Bus
  * 	@i:  Device
  *
  * 	LOCKING:
  */
- 
+
 void ata_dev_config(struct ata_port *ap, unsigned int i)
 {
 	/* limit bridge transfers to udma5, 200 sectors */
@@ -2377,6 +2377,27 @@ static int ata_sg_setup(struct ata_queue
 }
 
 /**
+ *	ata_poll_qc_complete - turn irq back on and finish qc
+ *	@qc: Command to complete
+ *	@drv_stat: ATA status register content
+ *
+ *	LOCKING:
+ *	None.  (grabs host lock)
+ */
+
+void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	ap->flags &= ~ATA_FLAG_NOINTR;
+	ata_irq_on(ap);
+	ata_qc_complete(qc, drv_stat);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+}
+
+/**
  *	ata_pio_poll -
  *	@ap:
  *
@@ -2438,11 +2459,10 @@ static void ata_pio_complete (struct ata
 	u8 drv_stat;
 
 	/*
-	 * This is purely hueristic.  This is a fast path.
-	 * Sometimes when we enter, BSY will be cleared in
-	 * a chk-status or two.  If not, the drive is probably seeking
-	 * or something.  Snooze for a couple msecs, then
-	 * chk-status again.  If still busy, fall back to
+	 * This is purely heuristic.  This is a fast path.  Sometimes when
+	 * we enter, BSY will be cleared in a chk-status or two.  If not,
+	 * the drive is probably seeking or something.  Snooze for a couple
+	 * msecs, then chk-status again.  If still busy, fall back to
 	 * PIO_ST_POLL state.
 	 */
 	drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
@@ -2467,9 +2487,7 @@ static void ata_pio_complete (struct ata
 
 	ap->pio_task_state = PIO_ST_IDLE;
 
-	ata_irq_on(ap);
-
-	ata_qc_complete(qc, drv_stat);
+	ata_poll_qc_complete(qc, drv_stat);
 }
 
 
@@ -2494,6 +2512,20 @@ void swap_buf_le16(u16 *buf, unsigned in
 #endif /* __BIG_ENDIAN */
 }
 
+/**
+ *	ata_mmio_data_xfer - Transfer data by MMIO
+ *	@ap: port to read/write
+ *	@buf: data buffer
+ *	@buflen: buffer length
+ *	@do_write: read/write
+ *
+ *	Transfer data from/to the device data register by MMIO.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ */
+
 static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
 			       unsigned int buflen, int write_data)
 {
@@ -2502,6 +2534,7 @@ static void ata_mmio_data_xfer(struct at
 	u16 *buf16 = (u16 *) buf;
 	void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
 
+	/* Transfer multiple of 2 bytes */
 	if (write_data) {
 		for (i = 0; i < words; i++)
 			writew(le16_to_cpu(buf16[i]), mmio);
@@ -2509,19 +2542,76 @@ static void ata_mmio_data_xfer(struct at
 		for (i = 0; i < words; i++)
 			buf16[i] = cpu_to_le16(readw(mmio));
 	}
+
+	/* Transfer trailing 1 byte, if any. */
+	if (unlikely(buflen & 0x01)) {
+		u16 align_buf[1] = { 0 };
+		unsigned char *trailing_buf = buf + buflen - 1;
+
+		if (write_data) {
+			memcpy(align_buf, trailing_buf, 1);
+			writew(le16_to_cpu(align_buf[0]), mmio);
+		} else {
+			align_buf[0] = cpu_to_le16(readw(mmio));
+			memcpy(trailing_buf, align_buf, 1);
+		}
+	}
 }
 
+/**
+ *	ata_pio_data_xfer - Transfer data by PIO
+ *	@ap: port to read/write
+ *	@buf: data buffer
+ *	@buflen: buffer length
+ *	@do_write: read/write
+ *
+ *	Transfer data from/to the device data register by PIO.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ */
+
 static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
 			      unsigned int buflen, int write_data)
 {
-	unsigned int dwords = buflen >> 1;
+	unsigned int words = buflen >> 1;
 
+	/* Transfer multiple of 2 bytes */
 	if (write_data)
-		outsw(ap->ioaddr.data_addr, buf, dwords);
+		outsw(ap->ioaddr.data_addr, buf, words);
 	else
-		insw(ap->ioaddr.data_addr, buf, dwords);
+		insw(ap->ioaddr.data_addr, buf, words);
+
+	/* Transfer trailing 1 byte, if any. */
+	if (unlikely(buflen & 0x01)) {
+		u16 align_buf[1] = { 0 };
+		unsigned char *trailing_buf = buf + buflen - 1;
+
+		if (write_data) {
+			memcpy(align_buf, trailing_buf, 1);
+			outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+		} else {
+			align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
+			memcpy(trailing_buf, align_buf, 1);
+		}
+	}
 }
 
+/**
+ *	ata_data_xfer - Transfer data from/to the data register.
+ *	@ap: port to read/write
+ *	@buf: data buffer
+ *	@buflen: buffer length
+ *	@do_write: read/write
+ *
+ *	Transfer data from/to the device data register.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ */
+
 static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
 			  unsigned int buflen, int do_write)
 {
@@ -2531,6 +2621,16 @@ static void ata_data_xfer(struct ata_por
 		ata_pio_data_xfer(ap, buf, buflen, do_write);
 }
 
+/**
+ *	ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data.
+ *	@qc: Command on going
+ *
+ *	Transfer ATA_SECT_SIZE of data from/to the ATA device.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
 static void ata_pio_sector(struct ata_queued_cmd *qc)
 {
 	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2569,6 +2669,18 @@ static void ata_pio_sector(struct ata_qu
 	kunmap(page);
 }
 
+/**
+ *	__atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ *	@qc: Command on going
+ *	@bytes: number of bytes
+ *
+ *	Transfer Transfer data from/to the ATAPI device.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ */
+
 static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
 {
 	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2578,10 +2690,33 @@ static void __atapi_pio_bytes(struct ata
 	unsigned char *buf;
 	unsigned int offset, count;
 
-	if (qc->curbytes == qc->nbytes - bytes)
+	if (qc->curbytes + bytes >= qc->nbytes)
 		ap->pio_task_state = PIO_ST_LAST;
 
 next_sg:
+	if (unlikely(qc->cursg >= qc->n_elem)) {
+		/* 
+		 * The end of qc->sg is reached and the device expects
+		 * more data to transfer. In order not to overrun qc->sg
+		 * and fulfill length specified in the byte count register,
+		 *    - for read case, discard trailing data from the device
+		 *    - for write case, padding zero data to the device
+		 */
+		u16 pad_buf[1] = { 0 };
+		unsigned int words = bytes >> 1;
+		unsigned int i;
+
+		if (words) /* warning if bytes > 1 */
+			printk(KERN_WARNING "ata%u: %u bytes trailing data\n", 
+			       ap->id, bytes);
+
+		for (i = 0; i < words; i++)
+			ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
+
+		ap->pio_task_state = PIO_ST_LAST;
+		return;
+	}
+
 	sg = &qc->sg[qc->cursg];
 
 	page = sg->page;
@@ -2615,11 +2750,21 @@ next_sg:
 
 	kunmap(page);
 
-	if (bytes) {
+	if (bytes)
 		goto next_sg;
-	}
 }
 
+/**
+ *	atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ *	@qc: Command on going
+ *
+ *	Transfer Transfer data from/to the ATAPI device.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ */
+
 static void atapi_pio_bytes(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
@@ -2692,9 +2837,7 @@ static void ata_pio_block(struct ata_por
 		if ((status & ATA_DRQ) == 0) {
 			ap->pio_task_state = PIO_ST_IDLE;
 
-			ata_irq_on(ap);
-
-			ata_qc_complete(qc, status);
+			ata_poll_qc_complete(qc, status);
 			return;
 		}
 
@@ -2724,9 +2867,7 @@ static void ata_pio_error(struct ata_por
 
 	ap->pio_task_state = PIO_ST_IDLE;
 
-	ata_irq_on(ap);
-
-	ata_qc_complete(qc, drv_stat | ATA_ERR);
+	ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
 }
 
 static void ata_pio_task(void *_data)
@@ -2832,8 +2973,10 @@ static void atapi_request_sense(struct a
 static void ata_qc_timeout(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
+	struct ata_host_set *host_set = ap->host_set;
 	struct ata_device *dev = qc->dev;
 	u8 host_stat = 0, drv_stat;
+	unsigned long flags;
 
 	DPRINTK("ENTER\n");
 
@@ -2844,7 +2987,9 @@ static void ata_qc_timeout(struct ata_qu
 		if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) {
 
 			/* finish completing original command */
+			spin_lock_irqsave(&host_set->lock, flags);
 			__ata_qc_complete(qc);
+			spin_unlock_irqrestore(&host_set->lock, flags);
 
 			atapi_request_sense(ap, dev, cmd);
 
@@ -2855,6 +3000,8 @@ static void ata_qc_timeout(struct ata_qu
 		}
 	}
 
+	spin_lock_irqsave(&host_set->lock, flags);
+
 	/* hack alert!  We cannot use the supplied completion
 	 * function from inside the ->eh_strategy_handler() thread.
 	 * libata is the only user of ->eh_strategy_handler() in
@@ -2870,7 +3017,7 @@ static void ata_qc_timeout(struct ata_qu
 		host_stat = ap->ops->bmdma_status(ap);
 
 		/* before we do anything else, clear DMA-Start bit */
-		ap->ops->bmdma_stop(ap);
+		ap->ops->bmdma_stop(qc);
 
 		/* fall through */
 
@@ -2888,6 +3035,9 @@ static void ata_qc_timeout(struct ata_qu
 		ata_qc_complete(qc, drv_stat);
 		break;
 	}
+
+	spin_unlock_irqrestore(&host_set->lock, flags);
+
 out:
 	DPRINTK("EXIT\n");
 }
@@ -3061,9 +3211,14 @@ void ata_qc_complete(struct ata_queued_c
 	if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
 		ata_sg_clean(qc);
 
+	/* atapi: mark qc as inactive to prevent the interrupt handler
+	 * from completing the command twice later, before the error handler
+	 * is called. (when rc != 0 and atapi request sense is needed)
+	 */
+	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+
 	/* call completion callback */
 	rc = qc->complete_fn(qc, drv_stat);
-	qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
 	/* if callback indicates not to complete command (non-zero),
 	 * return immediately
@@ -3193,11 +3348,13 @@ int ata_qc_issue_prot(struct ata_queued_
 		break;
 
 	case ATA_PROT_ATAPI_NODATA:
+		ap->flags |= ATA_FLAG_NOINTR;
 		ata_tf_to_host_nolock(ap, &qc->tf);
 		queue_work(ata_wq, &ap->packet_task);
 		break;
 
 	case ATA_PROT_ATAPI_DMA:
+		ap->flags |= ATA_FLAG_NOINTR;
 		ap->ops->tf_load(ap, &qc->tf);	 /* load tf registers */
 		ap->ops->bmdma_setup(qc);	    /* set up bmdma */
 		queue_work(ata_wq, &ap->packet_task);
@@ -3242,7 +3399,7 @@ static void ata_bmdma_setup_mmio (struct
 }
 
 /**
- *	ata_bmdma_start - Start a PCI IDE BMDMA transaction
+ *	ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction
  *	@qc: Info associated with this ATA transaction.
  *
  *	LOCKING:
@@ -3413,7 +3570,7 @@ u8 ata_bmdma_status(struct ata_port *ap)
 
 /**
  *	ata_bmdma_stop - Stop PCI IDE BMDMA transfer
- *	@ap: Port associated with this ATA transaction.
+ *	@qc: Command we are ending DMA for
  *
  *	Clears the ATA_DMA_START flag in the dma control register
  *
@@ -3423,8 +3580,9 @@ u8 ata_bmdma_status(struct ata_port *ap)
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_stop(struct ata_port *ap)
+void ata_bmdma_stop(struct ata_queued_cmd *qc)
 {
+	struct ata_port *ap = qc->ap;
 	if (ap->flags & ATA_FLAG_MMIO) {
 		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 
@@ -3476,7 +3634,7 @@ inline unsigned int ata_host_intr (struc
 			goto idle_irq;
 
 		/* before we do anything else, clear DMA-Start bit */
-		ap->ops->bmdma_stop(ap);
+		ap->ops->bmdma_stop(qc);
 
 		/* fall through */
 
@@ -3551,7 +3709,8 @@ irqreturn_t ata_interrupt (int irq, void
 		struct ata_port *ap;
 
 		ap = host_set->ports[i];
-		if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+		if (ap &&
+		    !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
 			struct ata_queued_cmd *qc;
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -3603,19 +3762,27 @@ static void atapi_packet_task(void *_dat
 	/* send SCSI cdb */
 	DPRINTK("send cdb\n");
 	assert(ap->cdb_len >= 12);
-	ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
-
-	/* if we are DMA'ing, irq handler takes over from here */
-	if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
-		ap->ops->bmdma_start(qc);	    /* initiate bmdma */
 
-	/* non-data commands are also handled via irq */
-	else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
-		/* do nothing */
-	}
+	if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
+	    qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
+		unsigned long flags;
+
+		/* Once we're done issuing command and kicking bmdma,
+		 * irq handler takes over.  To not lose irq, we need
+		 * to clear NOINTR flag before sending cdb, but
+		 * interrupt handler shouldn't be invoked before we're
+		 * finished.  Hence, the following locking.
+		 */
+		spin_lock_irqsave(&ap->host_set->lock, flags);
+		ap->flags &= ~ATA_FLAG_NOINTR;
+		ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
+		if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
+			ap->ops->bmdma_start(qc);	/* initiate bmdma */
+		spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	} else {
+		ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
 
-	/* PIO commands are handled by polling */
-	else {
+		/* PIO commands are handled by polling */
 		ap->pio_task_state = PIO_ST;
 		queue_work(ata_wq, &ap->pio_task);
 	}
@@ -3623,7 +3790,7 @@ static void atapi_packet_task(void *_dat
 	return;
 
 err_out:
-	ata_qc_complete(qc, ATA_ERR);
+	ata_poll_qc_complete(qc, ATA_ERR);
 }
 
 
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -392,6 +392,60 @@ int ata_scsi_error(struct Scsi_Host *hos
 }
 
 /**
+ *	ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
+ *	@qc: Storage for translated ATA taskfile
+ *	@scsicmd: SCSI command to translate
+ *
+ *	Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY
+ *	(to start). Perhaps these commands should be preceded by
+ *	CHECK POWER MODE to see what power mode the device is already in.
+ *	[See SAT revision 5 at www.t10.org]
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
+					     u8 *scsicmd)
+{
+	struct ata_taskfile *tf = &qc->tf;
+
+	tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+	tf->protocol = ATA_PROT_NODATA;
+	if (scsicmd[1] & 0x1) {
+		;	/* ignore IMMED bit, violates sat-r05 */
+	}
+	if (scsicmd[4] & 0x2)
+		return 1;	/* LOEJ bit set not supported */
+	if (((scsicmd[4] >> 4) & 0xf) != 0)
+		return 1;	/* power conditions not supported */
+	if (scsicmd[4] & 0x1) {
+		tf->nsect = 1;	/* 1 sector, lba=0 */
+		tf->lbah = 0x0;
+		tf->lbam = 0x0;
+		tf->lbal = 0x0;
+		tf->device |= ATA_LBA;
+		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 */
+	}
+	/*
+	 * Standby and Idle condition timers could be implemented but that
+	 * would require libata to implement the Power condition mode page
+	 * and allow the user to change it. Changing mode pages requires
+	 * MODE SELECT to be implemented.
+	 */
+
+	return 0;
+}
+
+
+/**
  *	ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
  *	@qc: Storage for translated ATA taskfile
  *	@scsicmd: SCSI command to translate (ignored)
@@ -576,11 +630,19 @@ static unsigned int ata_scsi_rw_xlat(str
 		tf->lbah = scsicmd[3];
 
 		VPRINTK("ten-byte command\n");
+		if (qc->nsect == 0) /* we don't support length==0 cmds */
+			return 1;
 		return 0;
 	}
 
 	if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
 		qc->nsect = tf->nsect = scsicmd[4];
+		if (!qc->nsect) {
+			qc->nsect = 256;
+			if (lba48)
+				tf->hob_nsect = 1;
+		}
+
 		tf->lbal = scsicmd[3];
 		tf->lbam = scsicmd[2];
 		tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
@@ -620,6 +682,8 @@ static unsigned int ata_scsi_rw_xlat(str
 		tf->lbah = scsicmd[7];
 
 		VPRINTK("sixteen-byte command\n");
+		if (qc->nsect == 0) /* we don't support length==0 cmds */
+			return 1;
 		return 0;
 	}
 
@@ -1435,6 +1499,8 @@ static inline ata_xlat_func_t ata_get_xl
 	case VERIFY:
 	case VERIFY_16:
 		return ata_scsi_verify_xlat;
+	case START_STOP:
+		return ata_scsi_start_stop_xlat;
 	}
 
 	return NULL;
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -72,7 +72,7 @@ extern unsigned int ata_scsiop_report_lu
 extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
 			    void (*done)(struct scsi_cmnd *),
 			    u8 asc, u8 ascq);
-extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, 
+extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
                         unsigned int (*actor) (struct ata_scsi_args *args,
                                            u8 *rbuf, unsigned int buflen));
 
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -20,6 +20,12 @@
  *  If you do not delete the provisions above, a recipient may use your
  *  version of this file under either the OSL or the GPL.
  *
+ *  0.08
+ *     - Added support for MCP51 and MCP55.
+ *
+ *  0.07
+ *     - Added support for RAID class code.
+ *
  *  0.06
  *     - Added generic SATA support by using a pci_device_id that filters on
  *       the IDE storage class code.
@@ -48,7 +54,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME			"sata_nv"
-#define DRV_VERSION			"0.6"
+#define DRV_VERSION			"0.8"
 
 #define NV_PORTS			2
 #define NV_PIO_MASK			0x1f
@@ -116,7 +122,9 @@ enum nv_host_type
 	GENERIC,
 	NFORCE2,
 	NFORCE3,
-	CK804
+	CK804,
+	MCP51,
+	MCP55
 };
 
 static struct pci_device_id nv_pci_tbl[] = {
@@ -134,9 +142,18 @@ static struct pci_device_id nv_pci_tbl[]
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
 		PCI_ANY_ID, PCI_ANY_ID,
 		PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
+		PCI_ANY_ID, PCI_ANY_ID,
+		PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },
 	{ 0, } /* terminate list */
 };
 
@@ -274,7 +291,8 @@ static irqreturn_t nv_interrupt (int irq
 		struct ata_port *ap;
 
 		ap = host_set->ports[i];
-		if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+		if (ap &&
+		    !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
 			struct ata_queued_cmd *qc;
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -181,6 +181,10 @@ static struct pci_device_id pdc_ata_pci_
 	  board_20319 },
 	{ PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20319 },
+	{ PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_20319 },
+	{ PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_20319 },
 	{ PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20319 },
 
@@ -321,11 +325,15 @@ static void pdc_qc_prep(struct ata_queue
 
 static void pdc_eng_timeout(struct ata_port *ap)
 {
+	struct ata_host_set *host_set = ap->host_set;
 	u8 drv_stat;
 	struct ata_queued_cmd *qc;
+	unsigned long flags;
 
 	DPRINTK("ENTER\n");
 
+	spin_lock_irqsave(&host_set->lock, flags);
+
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	if (!qc) {
 		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
@@ -359,6 +367,7 @@ static void pdc_eng_timeout(struct ata_p
 	}
 
 out:
+	spin_unlock_irqrestore(&host_set->lock, flags);
 	DPRINTK("EXIT\n");
 }
 
@@ -441,7 +450,8 @@ static irqreturn_t pdc_interrupt (int ir
 		VPRINTK("port %u\n", i);
 		ap = host_set->ports[i];
 		tmp = mask & (1 << (i + 1));
-		if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+		if (tmp && ap &&
+		    !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
 			struct ata_queued_cmd *qc;
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -117,7 +117,7 @@ static void qs_phy_reset(struct ata_port
 static void qs_qc_prep(struct ata_queued_cmd *qc);
 static int qs_qc_issue(struct ata_queued_cmd *qc);
 static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
-static void qs_bmdma_stop(struct ata_port *ap);
+static void qs_bmdma_stop(struct ata_queued_cmd *qc);
 static u8 qs_bmdma_status(struct ata_port *ap);
 static void qs_irq_clear(struct ata_port *ap);
 static void qs_eng_timeout(struct ata_port *ap);
@@ -198,7 +198,7 @@ static int qs_check_atapi_dma(struct ata
 	return 1;	/* ATAPI DMA not supported */
 }
 
-static void qs_bmdma_stop(struct ata_port *ap)
+static void qs_bmdma_stop(struct ata_queued_cmd *qc)
 {
 	/* nothing */
 }
@@ -386,7 +386,8 @@ static inline unsigned int qs_intr_pkt(s
 			DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
 					sff1, sff0, port_no, sHST, sDST);
 			handled = 1;
-			if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+			if (ap && !(ap->flags &
+				    (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
 				struct ata_queued_cmd *qc;
 				struct qs_port_priv *pp = ap->private_data;
 				if (!pp || pp->state != qs_state_pkt)
@@ -417,7 +418,8 @@ static inline unsigned int qs_intr_mmio(
 	for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
 		struct ata_port *ap;
 		ap = host_set->ports[port_no];
-		if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+		if (ap &&
+		    !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
 			struct ata_queued_cmd *qc;
 			struct qs_port_priv *pp = ap->private_data;
 			if (!pp || pp->state != qs_state_mmio)
@@ -431,7 +433,7 @@ static inline unsigned int qs_intr_mmio(
 					continue;
 				DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
 					ap->id, qc->tf.protocol, status);
-		
+
 				/* complete taskfile transaction */
 				pp->state = qs_state_idle;
 				ata_qc_complete(qc, status);
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -24,6 +24,11 @@
  *  If you do not delete the provisions above, a recipient may use your
  *  version of this file under either the OSL or the GPL.
  *
+ *  Documentation for SiI 3112:
+ *  http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
+ *
+ *  Other errata and documentation available under NDA.
+ *
  */
 
 #include <linux/kernel.h>
@@ -41,8 +46,11 @@
 #define DRV_VERSION	"0.9"
 
 enum {
+	SIL_FLAG_MOD15WRITE	= (1 << 30),
+
 	sil_3112		= 0,
-	sil_3114		= 1,
+	sil_3112_m15w		= 1,
+	sil_3114		= 2,
 
 	SIL_FIFO_R0		= 0x40,
 	SIL_FIFO_W0		= 0x41,
@@ -76,13 +84,13 @@ static void sil_scr_write (struct ata_po
 static void sil_post_set_mode (struct ata_port *ap);
 
 static struct pci_device_id sil_pci_tbl[] = {
-	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
 	{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
 	{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
-	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
+	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
 	{ }	/* terminate list */
 };
 
@@ -174,6 +182,16 @@ static struct ata_port_info sil_port_inf
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
 		.port_ops	= &sil_ops,
+	}, /* sil_3112_15w - keep it sync'd w/ sil_3112 */
+	{
+		.sht		= &sil_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SRST | ATA_FLAG_MMIO |
+				  SIL_FLAG_MOD15WRITE,
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil_ops,
 	}, /* sil_3114 */
 	{
 		.sht		= &sil_sht,
@@ -323,15 +341,15 @@ static void sil_dev_config(struct ata_po
 	while ((len > 0) && (s[len - 1] == ' '))
 		len--;
 
-	for (n = 0; sil_blacklist[n].product; n++) 
+	for (n = 0; sil_blacklist[n].product; n++)
 		if (!memcmp(sil_blacklist[n].product, s,
 			    strlen(sil_blacklist[n].product))) {
 			quirks = sil_blacklist[n].quirk;
 			break;
 		}
-	
+
 	/* limit requests to 15 sectors */
-	if (quirks & SIL_QUIRK_MOD15WRITE) {
+	if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) {
 		printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
 		       ap->id, dev->devno);
 		ap->host->max_sectors = 15;
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -234,7 +234,7 @@ static int sis_init_one (struct pci_dev 
 	pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
 	if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
 		probe_ent->host_flags |= SIS_FLAG_CFGSCR;
-	
+
 	/* if hardware thinks SCRs are in IO space, but there are
 	 * no IO resources assigned, change to PCI cfg space.
 	 */
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -195,18 +195,18 @@ static void k2_bmdma_start_mmio (struct 
 	/* start host DMA transaction */
 	dmactl = readb(mmio + ATA_DMA_CMD);
 	writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
-	/* There is a race condition in certain SATA controllers that can 
-	   be seen when the r/w command is given to the controller before the 
+	/* There is a race condition in certain SATA controllers that can
+	   be seen when the r/w command is given to the controller before the
 	   host DMA is started. On a Read command, the controller would initiate
 	   the command to the drive even before it sees the DMA start. When there
-	   are very fast drives connected to the controller, or when the data request 
+	   are very fast drives connected to the controller, or when the data request
 	   hits in the drive cache, there is the possibility that the drive returns a part
 	   or all of the requested data to the controller before the DMA start is issued.
 	   In this case, the controller would become confused as to what to do with the data.
 	   In the worst case when all the data is returned back to the controller, the
 	   controller could hang. In other cases it could return partial data returning
 	   in data corruption. This problem has been seen in PPC systems and can also appear
-	   on an system with very fast disks, where the SATA controller is sitting behind a 
+	   on an system with very fast disks, where the SATA controller is sitting behind a
 	   number of bridges, and hence there is significant latency between the r/w command
 	   and the start command. */
 	/* issue r/w command if the access is to ATA*/
@@ -214,7 +214,7 @@ static void k2_bmdma_start_mmio (struct 
 		ap->ops->exec_command(ap, &qc->tf);
 }
 
-									      
+
 static u8 k2_stat_check_status(struct ata_port *ap)
 {
        	return readl((void *) ap->ioaddr.status_addr);
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -94,7 +94,7 @@ enum {
 	PDC_DIMM1_CONTROL_OFFSET      = 0x84,
 	PDC_SDRAM_CONTROL_OFFSET      = 0x88,
 	PDC_I2C_WRITE                 = 0x00000000,
-	PDC_I2C_READ                  = 0x00000040,	
+	PDC_I2C_READ                  = 0x00000040,
 	PDC_I2C_START                 = 0x00000080,
 	PDC_I2C_MASK_INT              = 0x00000020,
 	PDC_I2C_COMPLETE              = 0x00010000,
@@ -105,16 +105,16 @@ enum {
 	PDC_DIMM_SPD_COLUMN_NUM       = 4,
 	PDC_DIMM_SPD_MODULE_ROW       = 5,
 	PDC_DIMM_SPD_TYPE             = 11,
-	PDC_DIMM_SPD_FRESH_RATE       = 12,         
-	PDC_DIMM_SPD_BANK_NUM         = 17,	
+	PDC_DIMM_SPD_FRESH_RATE       = 12,
+	PDC_DIMM_SPD_BANK_NUM         = 17,
 	PDC_DIMM_SPD_CAS_LATENCY      = 18,
-	PDC_DIMM_SPD_ATTRIBUTE        = 21,    
+	PDC_DIMM_SPD_ATTRIBUTE        = 21,
 	PDC_DIMM_SPD_ROW_PRE_CHARGE   = 27,
-	PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,      
+	PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
 	PDC_DIMM_SPD_RAS_CAS_DELAY    = 29,
 	PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
 	PDC_DIMM_SPD_SYSTEM_FREQ      = 126,
-	PDC_CTL_STATUS		      = 0x08,	
+	PDC_CTL_STATUS		      = 0x08,
 	PDC_DIMM_WINDOW_CTLR	      = 0x0C,
 	PDC_TIME_CONTROL              = 0x3C,
 	PDC_TIME_PERIOD               = 0x40,
@@ -157,15 +157,15 @@ static void pdc_exec_command_mmio(struct
 static void pdc20621_host_stop(struct ata_host_set *host_set);
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, 
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
 				      u32 device, u32 subaddr, u32 *pdata);
 static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
 static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
 #ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, 
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
 				   void *psource, u32 offset, u32 size);
 #endif
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, 
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
 				 void *psource, u32 offset, u32 size);
 static void pdc20621_irq_clear(struct ata_port *ap);
 static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -825,7 +825,8 @@ static irqreturn_t pdc20621_interrupt (i
 			ap = host_set->ports[port_no];
 		tmp = mask & (1 << i);
 		VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
-		if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+		if (tmp && ap &&
+		    !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
 			struct ata_queued_cmd *qc;
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -847,10 +848,14 @@ static irqreturn_t pdc20621_interrupt (i
 static void pdc_eng_timeout(struct ata_port *ap)
 {
 	u8 drv_stat;
+	struct ata_host_set *host_set = ap->host_set;
 	struct ata_queued_cmd *qc;
+	unsigned long flags;
 
 	DPRINTK("ENTER\n");
 
+	spin_lock_irqsave(&host_set->lock, flags);
+
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	if (!qc) {
 		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
@@ -884,6 +889,7 @@ static void pdc_eng_timeout(struct ata_p
 	}
 
 out:
+	spin_unlock_irqrestore(&host_set->lock, flags);
 	DPRINTK("EXIT\n");
 }
 
@@ -922,7 +928,7 @@ static void pdc_sata_setup_port(struct a
 
 
 #ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, 
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
 				   u32 offset, u32 size)
 {
 	u32 window_size;
@@ -936,9 +942,9 @@ static void pdc20621_get_from_dimm(struc
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
 
-	page_mask = 0x00;	
-   	window_size = 0x2000 * 4; /* 32K byte uchar size */  
-	idx = (u16) (offset / window_size); 
+	page_mask = 0x00;
+   	window_size = 0x2000 * 4; /* 32K byte uchar size */
+	idx = (u16) (offset / window_size);
 
 	writel(0x01, mmio + PDC_GENERAL_CTLR);
 	readl(mmio + PDC_GENERAL_CTLR);
@@ -947,19 +953,19 @@ static void pdc20621_get_from_dimm(struc
 
 	offset -= (idx * window_size);
 	idx++;
-	dist = ((long) (window_size - (offset + size))) >= 0 ? size : 
+	dist = ((long) (window_size - (offset + size))) >= 0 ? size :
 		(long) (window_size - offset);
-	memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), 
+	memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
 		      dist);
 
-	psource += dist;    
+	psource += dist;
 	size -= dist;
 	for (; (long) size >= (long) window_size ;) {
 		writel(0x01, mmio + PDC_GENERAL_CTLR);
 		readl(mmio + PDC_GENERAL_CTLR);
 		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
 		readl(mmio + PDC_DIMM_WINDOW_CTLR);
-		memcpy_fromio((char *) psource, (char *) (dimm_mmio), 
+		memcpy_fromio((char *) psource, (char *) (dimm_mmio),
 			      window_size / 4);
 		psource += window_size;
 		size -= window_size;
@@ -971,14 +977,14 @@ static void pdc20621_get_from_dimm(struc
 		readl(mmio + PDC_GENERAL_CTLR);
 		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
 		readl(mmio + PDC_DIMM_WINDOW_CTLR);
-		memcpy_fromio((char *) psource, (char *) (dimm_mmio), 
+		memcpy_fromio((char *) psource, (char *) (dimm_mmio),
 			      size / 4);
 	}
 }
 #endif
 
 
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, 
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
 				 u32 offset, u32 size)
 {
 	u32 window_size;
@@ -989,16 +995,16 @@ static void pdc20621_put_to_dimm(struct 
 	struct pdc_host_priv *hpriv = pe->private_data;
 	void *dimm_mmio = hpriv->dimm_mmio;
 
-	/* hard-code chip #0 */   
+	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
 
-	page_mask = 0x00;	
-   	window_size = 0x2000 * 4;       /* 32K byte uchar size */  
+	page_mask = 0x00;
+   	window_size = 0x2000 * 4;       /* 32K byte uchar size */
 	idx = (u16) (offset / window_size);
 
 	writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
 	readl(mmio + PDC_DIMM_WINDOW_CTLR);
-	offset -= (idx * window_size); 
+	offset -= (idx * window_size);
 	idx++;
 	dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
 		(long) (window_size - offset);
@@ -1006,12 +1012,12 @@ static void pdc20621_put_to_dimm(struct 
 	writel(0x01, mmio + PDC_GENERAL_CTLR);
 	readl(mmio + PDC_GENERAL_CTLR);
 
-	psource += dist;    
+	psource += dist;
 	size -= dist;
 	for (; (long) size >= (long) window_size ;) {
 		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
 		readl(mmio + PDC_DIMM_WINDOW_CTLR);
-		memcpy_toio((char *) (dimm_mmio), (char *) psource, 
+		memcpy_toio((char *) (dimm_mmio), (char *) psource,
 			    window_size / 4);
 		writel(0x01, mmio + PDC_GENERAL_CTLR);
 		readl(mmio + PDC_GENERAL_CTLR);
@@ -1019,7 +1025,7 @@ static void pdc20621_put_to_dimm(struct 
 		size -= window_size;
 		idx ++;
 	}
-    
+
 	if (size) {
 		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
 		readl(mmio + PDC_DIMM_WINDOW_CTLR);
@@ -1030,12 +1036,12 @@ static void pdc20621_put_to_dimm(struct 
 }
 
 
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, 
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
 				      u32 subaddr, u32 *pdata)
 {
 	void *mmio = pe->mmio_base;
 	u32 i2creg  = 0;
-	u32 status;     
+	u32 status;
 	u32 count =0;
 
 	/* hard-code chip #0 */
@@ -1049,7 +1055,7 @@ static unsigned int pdc20621_i2c_read(st
 	readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
 
 	/* Write Control to perform read operation, mask int */
-	writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, 
+	writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
 	       mmio + PDC_I2C_CONTROL_OFFSET);
 
 	for (count = 0; count <= 1000; count ++) {
@@ -1062,26 +1068,26 @@ static unsigned int pdc20621_i2c_read(st
 	}
 
 	*pdata = (status >> 8) & 0x000000ff;
-	return 1;           
+	return 1;
 }
 
 
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
 {
 	u32 data=0 ;
-  	if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+  	if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
 			     PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
    		if (data == 100)
 			return 100;
   	} else
 		return 0;
- 	
+
    	if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
-		if(data <= 0x75) 
+		if(data <= 0x75)
 			return 133;
    	} else
 		return 0;
-   	
+
    	return 0;
 }
 
@@ -1091,15 +1097,15 @@ static int pdc20621_prog_dimm0(struct at
 	u32 spd0[50];
 	u32 data = 0;
    	int size, i;
-   	u8 bdimmsize; 
+   	u8 bdimmsize;
    	void *mmio = pe->mmio_base;
 	static const struct {
 		unsigned int reg;
 		unsigned int ofs;
 	} pdc_i2c_read_data [] = {
-		{ PDC_DIMM_SPD_TYPE, 11 },		
+		{ PDC_DIMM_SPD_TYPE, 11 },
 		{ PDC_DIMM_SPD_FRESH_RATE, 12 },
-		{ PDC_DIMM_SPD_COLUMN_NUM, 4 }, 
+		{ PDC_DIMM_SPD_COLUMN_NUM, 4 },
 		{ PDC_DIMM_SPD_ATTRIBUTE, 21 },
 		{ PDC_DIMM_SPD_ROW_NUM, 3 },
 		{ PDC_DIMM_SPD_BANK_NUM, 17 },
@@ -1108,7 +1114,7 @@ static int pdc20621_prog_dimm0(struct at
 		{ PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 },
 		{ PDC_DIMM_SPD_RAS_CAS_DELAY, 29 },
 		{ PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 },
-		{ PDC_DIMM_SPD_CAS_LATENCY, 18 },       
+		{ PDC_DIMM_SPD_CAS_LATENCY, 18 },
 	};
 
 	/* hard-code chip #0 */
@@ -1116,17 +1122,17 @@ static int pdc20621_prog_dimm0(struct at
 
 	for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
 		pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
-				  pdc_i2c_read_data[i].reg, 
+				  pdc_i2c_read_data[i].reg,
 				  &spd0[pdc_i2c_read_data[i].ofs]);
-  
+
    	data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
-   	data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | 
+   	data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
 		((((spd0[27] + 9) / 10) - 1) << 8) ;
-   	data |= (((((spd0[29] > spd0[28]) 
-		    ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; 
+   	data |= (((((spd0[29] > spd0[28])
+		    ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
    	data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
-   
-   	if (spd0[18] & 0x08) 
+
+   	if (spd0[18] & 0x08)
 		data |= ((0x03) << 14);
    	else if (spd0[18] & 0x04)
 		data |= ((0x02) << 14);
@@ -1135,7 +1141,7 @@ static int pdc20621_prog_dimm0(struct at
    	else
 		data |= (0 << 14);
 
-  	/* 
+  	/*
 	   Calculate the size of bDIMMSize (power of 2) and
 	   merge the DIMM size by program start/end address.
 	*/
@@ -1145,9 +1151,9 @@ static int pdc20621_prog_dimm0(struct at
    	data |= (((size / 16) - 1) << 16);
    	data |= (0 << 23);
 	data |= 8;
-   	writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); 
+   	writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
 	readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
-   	return size;                          
+   	return size;
 }
 
 
@@ -1167,12 +1173,12 @@ static unsigned int pdc20621_prog_dimm_g
 	  Refresh Enable (bit 17)
 	*/
 
-	data = 0x022259F1;   
+	data = 0x022259F1;
 	writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
 	readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
 
 	/* Turn on for ECC */
-	pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+	pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
 			  PDC_DIMM_SPD_TYPE, &spd0);
 	if (spd0 == 0x02) {
 		data |= (0x01 << 16);
@@ -1186,22 +1192,22 @@ static unsigned int pdc20621_prog_dimm_g
    	data |= (1<<19);
    	writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
 
-   	error = 1;                     
+   	error = 1;
    	for (i = 1; i <= 10; i++) {   /* polling ~5 secs */
 		data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
 		if (!(data & (1<<19))) {
 	   		error = 0;
-	   		break;     
+	   		break;
 		}
 		msleep(i*100);
    	}
    	return error;
 }
-	
+
 
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
 {
-	int speed, size, length; 
+	int speed, size, length;
 	u32 addr,spd0,pci_status;
 	u32 tmp=0;
 	u32 time_period=0;
@@ -1228,7 +1234,7 @@ static unsigned int pdc20621_dimm_init(s
 	/* Wait 3 seconds */
 	msleep(3000);
 
-	/* 
+	/*
 	   When timer is enabled, counter is decreased every internal
 	   clock cycle.
 	*/
@@ -1236,24 +1242,24 @@ static unsigned int pdc20621_dimm_init(s
 	tcount = readl(mmio + PDC_TIME_COUNTER);
 	VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount);
 
-	/* 
+	/*
 	   If SX4 is on PCI-X bus, after 3 seconds, the timer counter
 	   register should be >= (0xffffffff - 3x10^8).
 	*/
 	if(tcount >= PCI_X_TCOUNT) {
 		ticks = (time_period - tcount);
 		VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks);
-	
+
 		clock = (ticks / 300000);
 		VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock);
-		
+
 		clock = (clock * 33);
 		VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock);
 
 		/* PLL F Param (bit 22:16) */
 		fparam = (1400000 / clock) - 2;
 		VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam);
-		
+
 		/* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */
 		pci_status = (0x8a001824 | (fparam << 16));
 	} else
@@ -1264,21 +1270,21 @@ static unsigned int pdc20621_dimm_init(s
 	writel(pci_status, mmio + PDC_CTL_STATUS);
 	readl(mmio + PDC_CTL_STATUS);
 
-	/* 
+	/*
 	   Read SPD of DIMM by I2C interface,
 	   and program the DIMM Module Controller.
 	*/
  	if (!(speed = pdc20621_detect_dimm(pe))) {
-		printk(KERN_ERR "Detect Local DIMM Fail\n");  
+		printk(KERN_ERR "Detect Local DIMM Fail\n");
 		return 1;	/* DIMM error */
    	}
    	VPRINTK("Local DIMM Speed = %d\n", speed);
 
-   	/* Programming DIMM0 Module Control Register (index_CID0:80h) */ 
+   	/* Programming DIMM0 Module Control Register (index_CID0:80h) */
    	size = pdc20621_prog_dimm0(pe);
    	VPRINTK("Local DIMM Size = %dMB\n",size);
 
-   	/* Programming DIMM Module Global Control Register (index_CID0:88h) */ 
+   	/* Programming DIMM Module Global Control Register (index_CID0:88h) */
    	if (pdc20621_prog_dimm_global(pe)) {
 		printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
 		return 1;
@@ -1297,30 +1303,30 @@ static unsigned int pdc20621_dimm_init(s
 
 		pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
 		pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
-		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
 		       test_parttern2[1], &(test_parttern2[2]));
-		pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040, 
+		pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
 				       40);
-		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
 		       test_parttern2[1], &(test_parttern2[2]));
 
 		pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
 		pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
-		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
 		       test_parttern2[1], &(test_parttern2[2]));
 	}
 #endif
 
 	/* ECC initiliazation. */
 
-	pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+	pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
 			  PDC_DIMM_SPD_TYPE, &spd0);
 	if (spd0 == 0x02) {
 		VPRINTK("Start ECC initialization\n");
 		addr = 0;
 		length = size * 1024 * 1024;
 		while (addr < length) {
-			pdc20621_put_to_dimm(pe, (void *) &tmp, addr, 
+			pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
 					     sizeof(u32));
 			addr += sizeof(u32);
 		}
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -214,7 +214,7 @@ static int uli_init_one (struct pci_dev 
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
-	
+
 	switch (board_idx) {
 	case uli_5287:
 		probe_ent->port[0].scr_addr = ULI5287_BASE;
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -347,7 +347,7 @@ static int svia_init_one (struct pci_dev
 		probe_ent = vt6420_init_probe_ent(pdev);
 	else
 		probe_ent = vt6421_init_probe_ent(pdev);
-	
+
 	if (!probe_ent) {
 		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
 		       pci_name(pdev));
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -173,7 +173,8 @@ static irqreturn_t vsc_sata_interrupt (i
 			struct ata_port *ap;
 
 			ap = host_set->ports[i];
-			if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+			if (ap && !(ap->flags &
+				    (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
 				struct ata_queued_cmd *qc;
 
 				qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -342,7 +343,7 @@ static int __devinit vsc_sata_init_one (
 
 	pci_set_master(pdev);
 
-	/* 
+	/*
 	 * Config offset 0x98 is "Extended Control and Status Register 0"
 	 * Default value is (1 << 28).  All bits except bit 28 are reserved in
 	 * DPA mode.  If bit 28 is set, LED 0 reflects all ports' activity.
diff --git a/include/linux/ata.h b/include/linux/ata.h
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -108,6 +108,8 @@ enum {
 
 	/* ATA device commands */
 	ATA_CMD_CHK_POWER	= 0xE5, /* check power mode */
+	ATA_CMD_STANDBY		= 0xE2, /* place in standby power mode */
+	ATA_CMD_IDLE		= 0xE3, /* place in idle power mode */
 	ATA_CMD_EDD		= 0x90,	/* execute device diagnostic */
 	ATA_CMD_FLUSH		= 0xE7,
 	ATA_CMD_FLUSH_EXT	= 0xEA,
diff --git a/include/linux/libata.h b/include/linux/libata.h
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -113,6 +113,8 @@ enum {
 	ATA_FLAG_MMIO		= (1 << 6), /* use MMIO, not PIO */
 	ATA_FLAG_SATA_RESET	= (1 << 7), /* use COMRESET */
 	ATA_FLAG_PIO_DMA	= (1 << 8), /* PIO cmds via DMA */
+	ATA_FLAG_NOINTR		= (1 << 9), /* FIXME: Remove this once
+					     * proper HSM is in place. */
 
 	ATA_QCFLAG_ACTIVE	= (1 << 1), /* cmd not yet ack'd to scsi lyer */
 	ATA_QCFLAG_SG		= (1 << 3), /* have s/g table? */
@@ -363,7 +365,7 @@ struct ata_port_operations {
 
 	void (*host_stop) (struct ata_host_set *host_set);
 
-	void (*bmdma_stop) (struct ata_port *ap);
+	void (*bmdma_stop) (struct ata_queued_cmd *qc);
 	u8   (*bmdma_status) (struct ata_port *ap);
 };
 
@@ -424,7 +426,7 @@ extern void ata_dev_id_string(u16 *id, u
 extern void ata_dev_config(struct ata_port *ap, unsigned int i);
 extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
 extern void ata_bmdma_start (struct ata_queued_cmd *qc);
-extern void ata_bmdma_stop(struct ata_port *ap);
+extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
 extern u8   ata_bmdma_status(struct ata_port *ap);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
 extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
@@ -644,7 +646,7 @@ static inline void scr_write(struct ata_
 	ap->ops->scr_write(ap, reg, val);
 }
 
-static inline void scr_write_flush(struct ata_port *ap, unsigned int reg, 
+static inline void scr_write_flush(struct ata_port *ap, unsigned int reg,
 				   u32 val)
 {
 	ap->ops->scr_write(ap, reg, val);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1249,6 +1249,7 @@
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA	0x0266
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2	0x0267
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE	0x036E
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA	0x036F
 #define PCI_DEVICE_ID_NVIDIA_NVENET_12		0x0268
 #define PCI_DEVICE_ID_NVIDIA_NVENET_13		0x0269
 #define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO	0x026B

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

* [git patches] 2.6.x libata updates
@ 2005-06-28 16:59 Jeff Garzik
  0 siblings, 0 replies; 50+ messages in thread
From: Jeff Garzik @ 2005-06-28 16:59 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-ide, Linux Kernel

[-- Attachment #1: Type: text/plain, Size: 175 bytes --]

please pull from branch 'upstream-20050628-1' of
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

to obtain the changes described in the attachment.


[-- Attachment #2: libata-dev.txt --]
[-- Type: text/plain, Size: 9681 bytes --]



 Documentation/DocBook/libata.tmpl |   96 ++++++++++++++++++++++++++++++++++++--
 drivers/scsi/ahci.c               |   22 +-------
 drivers/scsi/libata-core.c        |    6 +-
 3 files changed, 101 insertions(+), 23 deletions(-)


Edward Falk:
  Minor libata documentation patch

Jeff Garzik:
  libata: update DMA blacklist

Tejun Heo:
  libata: ahci: remove ata_port_start/stop() calls
  libata: lengthen COMMRESET delay



diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -84,6 +84,14 @@ void (*port_disable) (struct ata_port *)
 	Called from ata_bus_probe() and ata_bus_reset() error paths,
 	as well as when unregistering from the SCSI module (rmmod, hot
 	unplug).
+	This function should do whatever needs to be done to take the
+	port out of use.  In most cases, ata_port_disable() can be used
+	as this hook.
+	</para>
+	<para>
+	Called from ata_bus_probe() on a failed probe.
+	Called from ata_bus_reset() on a failed bus reset.
+	Called from ata_scsi_release().
 	</para>
 
 	</sect2>
@@ -98,6 +106,13 @@ void (*dev_config) (struct ata_port *, s
 	found.  Typically used to apply device-specific fixups prior to
 	issue of SET FEATURES - XFER MODE, and prior to operation.
 	</para>
+	<para>
+	Called by ata_device_add() after ata_dev_identify() determines
+	a device is present.
+	</para>
+	<para>
+	This entry may be specified as NULL in ata_port_operations.
+	</para>
 
 	</sect2>
 
@@ -135,6 +150,8 @@ void (*tf_read) (struct ata_port *ap, st
 	registers / DMA buffers.  ->tf_read() is called to read the
 	hardware registers / DMA buffers, to obtain the current set of
 	taskfile register values.
+	Most drivers for taskfile-based hardware (PIO or MMIO) use
+	ata_tf_load() and ata_tf_read() for these hooks.
 	</para>
 
 	</sect2>
@@ -147,6 +164,8 @@ void (*exec_command)(struct ata_port *ap
 	<para>
 	causes an ATA command, previously loaded with
 	->tf_load(), to be initiated in hardware.
+	Most drivers for taskfile-based hardware use ata_exec_command()
+	for this hook.
 	</para>
 
 	</sect2>
@@ -161,6 +180,10 @@ Allow low-level driver to filter ATA PAC
 indicating whether or not it is OK to use DMA for the supplied PACKET
 command.
 	</para>
+	<para>
+	This hook may be specified as NULL, in which case libata will
+	assume that atapi dma can be supported.
+	</para>
 
 	</sect2>
 
@@ -175,6 +198,14 @@ u8   (*check_err)(struct ata_port *ap);
 	Reads the Status/AltStatus/Error ATA shadow register from
 	hardware.  On some hardware, reading the Status register has
 	the side effect of clearing the interrupt condition.
+	Most drivers for taskfile-based hardware use
+	ata_check_status() for this hook.
+	</para>
+	<para>
+	Note that because this is called from ata_device_add(), at
+	least a dummy function that clears device interrupts must be
+	provided for all drivers, even if the controller doesn't
+	actually have a taskfile status register.
 	</para>
 
 	</sect2>
@@ -188,7 +219,13 @@ void (*dev_select)(struct ata_port *ap, 
 	Issues the low-level hardware command(s) that causes one of N
 	hardware devices to be considered 'selected' (active and
 	available for use) on the ATA bus.  This generally has no
-meaning on FIS-based devices.
+	meaning on FIS-based devices.
+	</para>
+	<para>
+	Most drivers for taskfile-based hardware use
+	ata_std_dev_select() for this hook.  Controllers which do not
+	support second drives on a port (such as SATA contollers) will
+	use ata_noop_dev_select().
 	</para>
 
 	</sect2>
@@ -204,6 +241,8 @@ void (*phy_reset) (struct ata_port *ap);
 	for device presence (PATA and SATA), typically a soft reset
 	(SRST) will be performed.  Drivers typically use the helper
 	functions ata_bus_reset() or sata_phy_reset() for this hook.
+	Many SATA drivers use sata_phy_reset() or call it from within
+	their own phy_reset() functions.
 	</para>
 
 	</sect2>
@@ -227,6 +266,25 @@ PCI IDE DMA Status register.
 These hooks are typically either no-ops, or simply not implemented, in
 FIS-based drivers.
 	</para>
+	<para>
+Most legacy IDE drivers use ata_bmdma_setup() for the bmdma_setup()
+hook.  ata_bmdma_setup() will write the pointer to the PRD table to
+the IDE PRD Table Address register, enable DMA in the DMA Command
+register, and call exec_command() to begin the transfer.
+	</para>
+	<para>
+Most legacy IDE drivers use ata_bmdma_start() for the bmdma_start()
+hook.  ata_bmdma_start() will write the ATA_DMA_START flag to the DMA
+Command register.
+	</para>
+	<para>
+Many legacy IDE drivers use ata_bmdma_stop() for the bmdma_stop()
+hook.  ata_bmdma_stop() clears the ATA_DMA_START flag in the DMA
+command register.
+	</para>
+	<para>
+Many legacy IDE drivers use ata_bmdma_status() as the bmdma_status() hook.
+	</para>
 
 	</sect2>
 
@@ -250,6 +308,10 @@ int (*qc_issue) (struct ata_queued_cmd *
 	helper function ata_qc_issue_prot() for taskfile protocol-based
 	dispatch.  More advanced drivers implement their own ->qc_issue.
 	</para>
+	<para>
+	ata_qc_issue_prot() calls ->tf_load(), ->bmdma_setup(), and
+	->bmdma_start() as necessary to initiate a transfer.
+	</para>
 
 	</sect2>
 
@@ -279,6 +341,21 @@ void (*irq_clear) (struct ata_port *);
 	before the interrupt handler is registered, to be sure hardware
 	is quiet.
 	</para>
+	<para>
+	The second argument, dev_instance, should be cast to a pointer
+	to struct ata_host_set.
+	</para>
+	<para>
+	Most legacy IDE drivers use ata_interrupt() for the
+	irq_handler hook, which scans all ports in the host_set,
+	determines which queued command was active (if any), and calls
+	ata_host_intr(ap,qc).
+	</para>
+	<para>
+	Most legacy IDE drivers use ata_bmdma_irq_clear() for the
+	irq_clear() hook, which simply clears the interrupt and error
+	flags in the DMA status register.
+	</para>
 
 	</sect2>
 
@@ -292,6 +369,7 @@ void (*scr_write) (struct ata_port *ap, 
 	<para>
 	Read and write standard SATA phy registers.  Currently only used
 	if ->phy_reset hook called the sata_phy_reset() helper function.
+	sc_reg is one of SCR_STATUS, SCR_CONTROL, SCR_ERROR, or SCR_ACTIVE.
 	</para>
 
 	</sect2>
@@ -307,17 +385,29 @@ void (*host_stop) (struct ata_host_set *
 	->port_start() is called just after the data structures for each
 	port are initialized.  Typically this is used to alloc per-port
 	DMA buffers / tables / rings, enable DMA engines, and similar
-	tasks.  
+	tasks.  Some drivers also use this entry point as a chance to
+	allocate driver-private memory for ap->private_data.
+	</para>
+	<para>
+	Many drivers use ata_port_start() as this hook or call
+	it from their own port_start() hooks.  ata_port_start()
+	allocates space for a legacy IDE PRD table and returns.
 	</para>
 	<para>
 	->port_stop() is called after ->host_stop().  It's sole function
 	is to release DMA/memory resources, now that they are no longer
-	actively being used.
+	actively being used.  Many drivers also free driver-private
+	data from port at this time.
+	</para>
+	<para>
+	Many drivers use ata_port_stop() as this hook, which frees the
+	PRD table.
 	</para>
 	<para>
 	->host_stop() is called after all ->port_stop() calls
 have completed.  The hook must finalize hardware shutdown, release DMA
 and other resources, etc.
+	This hook may be specified as NULL, in which case it is not called.
 	</para>
 
 	</sect2>
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -304,26 +304,19 @@ static int ahci_port_start(struct ata_po
 	struct device *dev = ap->host_set->dev;
 	struct ahci_host_priv *hpriv = ap->host_set->private_data;
 	struct ahci_port_priv *pp;
-	int rc;
 	void *mem, *mmio = ap->host_set->mmio_base;
 	void *port_mmio = ahci_port_base(mmio, ap->port_no);
 	dma_addr_t mem_dma;
 
-	rc = ata_port_start(ap);
-	if (rc)
-		return rc;
-
 	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
-	if (!pp) {
-		rc = -ENOMEM;
-		goto err_out;
-	}
+	if (!pp)
+		return -ENOMEM;
 	memset(pp, 0, sizeof(*pp));
 
 	mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
 	if (!mem) {
-		rc = -ENOMEM;
-		goto err_out_kfree;
+		kfree(pp);
+		return -ENOMEM;
 	}
 	memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
 
@@ -373,12 +366,6 @@ static int ahci_port_start(struct ata_po
 	readl(port_mmio + PORT_CMD); /* flush */
 
 	return 0;
-
-err_out_kfree:
-	kfree(pp);
-err_out:
-	ata_port_stop(ap);
-	return rc;
 }
 
 
@@ -404,7 +391,6 @@ static void ahci_port_stop(struct ata_po
 	dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
 			  pp->cmd_slot, pp->cmd_slot_dma);
 	kfree(pp);
-	ata_port_stop(ap);
 }
 
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1408,7 +1408,9 @@ void __sata_phy_reset(struct ata_port *a
 	if (ap->flags & ATA_FLAG_SATA_RESET) {
 		/* issue phy wake/reset */
 		scr_write_flush(ap, SCR_CONTROL, 0x301);
-		udelay(400);			/* FIXME: a guess */
+		/* Couldn't find anything in SATA I/II specs, but
+		 * AHCI-1.1 10.4.2 says at least 1 ms. */
+		mdelay(1);
 	}
 	scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */
 
@@ -1920,6 +1922,7 @@ static const char * ata_dma_blacklist []
 	"HITACHI CDR-8335",
 	"HITACHI CDR-8435",
 	"Toshiba CD-ROM XM-6202B",
+	"TOSHIBA CD-ROM XM-1702BC",
 	"CD-532E-A",
 	"E-IDE CD-ROM CR-840",
 	"CD-ROM Drive/F5A",
@@ -1927,7 +1930,6 @@ static const char * ata_dma_blacklist []
 	"SAMSUNG CD-ROM SC-148C",
 	"SAMSUNG CD-ROM SC",
 	"SanDisk SDP3B-64",
-	"SAMSUNG CD-ROM SN-124",
 	"ATAPI CD-ROM DRIVE 40X MAXIMUM",
 	"_NEC DV5800A",
 };

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

end of thread, other threads:[~2006-01-18  5:19 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-01-18  2:15 [git patches] 2.6.x libata updates Jeff Garzik
2006-01-18  2:33 ` Andrew Morton
2006-01-18  5:18   ` Jeff Garzik
  -- strict thread matches above, loose matches on Subject: below --
2006-01-03 16:43 Jeff Garzik
2006-01-03 16:51 ` Bartlomiej Zolnierkiewicz
2006-01-03 16:56   ` Jeff Garzik
2006-01-03 17:32   ` Alan Cox
2006-01-03 17:43     ` Jeff Garzik
2006-01-03 18:35       ` Bartlomiej Zolnierkiewicz
2006-01-03 18:50         ` Alan Cox
2006-01-04 14:02       ` Alan Cox
2005-11-11 16:23 Jeff Garzik
2005-11-09  6:54 Jeff Garzik
2005-10-29 18:22 Jeff Garzik
2005-10-29 19:14 ` Andrew Morton
2005-10-29 19:20   ` Jeff Garzik
2005-10-29 19:37     ` Linus Torvalds
2005-10-29 20:09       ` Al Viro
2005-10-29 20:16       ` Jeff Garzik
2005-10-29 20:18       ` Nicolas Pitre
2005-10-29 21:01         ` Linus Torvalds
2005-10-30 15:46           ` Nicolas Pitre
2005-10-29 22:21       ` Andrew Morton
2005-10-29 22:30         ` Linus Torvalds
2005-10-30  0:55           ` Tony Luck
2005-10-30  2:28       ` Horst von Brand
2005-10-30 12:44       ` Rob Landley
2005-10-30 22:36         ` Linus Torvalds
2005-10-30 23:31           ` Rob Landley
2005-10-31  0:58             ` Linus Torvalds
2005-10-31  2:35               ` Rob Landley
2005-10-31  7:46                 ` Junio C Hamano
2005-10-31  8:10                   ` David Lang
2005-10-31  8:28                     ` David Lang
2005-10-31  9:00                     ` Junio C Hamano
2005-10-31  9:13                       ` David Lang
2005-10-31  9:34                         ` Rob Landley
2005-10-31 11:45                           ` Giuseppe Bilotta
2005-10-31 17:49                             ` David Lang
2005-10-31 18:06                               ` Giuseppe Bilotta
2005-10-31  2:52               ` Rob Landley
2005-11-10  0:36               ` Matthias Urlichs
2005-10-30 23:59           ` Rob Landley
2005-10-31  0:16             ` Randy.Dunlap
2005-10-30 13:11       ` Pavel Machek
2005-10-31  3:55       ` David Lang
2005-10-28  0:49 Jeff Garzik
2005-10-28 16:08 ` Linus Torvalds
2005-08-29  0:25 Jeff Garzik
2005-06-28 16:59 Jeff Garzik

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