[kernel] r7593 - in dists/trunk/linux-2.6/debian: . patches/features/all/drivers patches/series

Bastian Blank waldi at costa.debian.org
Tue Oct 10 14:43:22 UTC 2006


Author: waldi
Date: Tue Oct 10 14:43:21 2006
New Revision: 7593

Added:
   dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-1.patch
   dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-2.patch
   dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-3.patch
   dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-4.patch
   dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-suspend-1.patch
   dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-suspend-2.patch
   dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-suspend-3.patch
Modified:
   dists/trunk/linux-2.6/debian/changelog
   dists/trunk/linux-2.6/debian/patches/series/3

Log:
Add AHCI suspend support.

* debian/changelog: Update.
* debian/patches/features/all/drivers/scsi-ahci-*: Add.
* debian/patches/series/3: Add patches.


Modified: dists/trunk/linux-2.6/debian/changelog
==============================================================================
--- dists/trunk/linux-2.6/debian/changelog	(original)
+++ dists/trunk/linux-2.6/debian/changelog	Tue Oct 10 14:43:21 2006
@@ -4,6 +4,7 @@
   * Fix home of patch apply script.
   * Unify CPUSET option. (closes: #391931)
   * Support xen version 3.0.3-1 and 3.0.3-rc1.
+  * Add AHCI suspend support. 
 
   [ Steve Langasek ]
   * [alpha] restore alpha-prctl.patch, which keeps disappearing every time
@@ -30,7 +31,7 @@
   * bugfix/sky2-receive-FIFO-fix.patch: fix sky2 hangs on some chips
     Thanks to Stephen Hemminger for the patch. (Closes: #391382)
 
- -- Frederik Schüler <fs at debian.org>  Tue, 10 Oct 2006 13:50:08 +0200
+ -- Bastian Blank <waldi at debian.org>  Tue, 10 Oct 2006 16:40:26 +0200
 
 linux-2.6 (2.6.18-2) unstable; urgency=low
 

Added: dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-1.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-1.patch	Tue Oct 10 14:43:21 2006
@@ -0,0 +1,183 @@
+# [PATCH] The redefinition of ahci_start_engine() and ahci_stop_engine()
+# 5457f2194ad198a0aba4190ec99a6a81846fdca5
+
+diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
+index 77e7202..f1516ca 100644
+--- a/drivers/scsi/ahci.c
++++ b/drivers/scsi/ahci.c
+@@ -205,6 +205,8 @@ static irqreturn_t ahci_interrupt (int i
+ static void ahci_irq_clear(struct ata_port *ap);
+ static int ahci_port_start(struct ata_port *ap);
+ static void ahci_port_stop(struct ata_port *ap);
++static int ahci_start_engine(void __iomem *port_mmio);
++static int ahci_stop_engine(void __iomem *port_mmio);
+ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+ static void ahci_qc_prep(struct ata_queued_cmd *qc);
+ static u8 ahci_check_status(struct ata_port *ap);
+@@ -508,41 +510,64 @@ static void ahci_scr_write (struct ata_p
+ 	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ }
+ 
+-static int ahci_stop_engine(struct ata_port *ap)
++static int ahci_stop_engine(void __iomem *port_mmio)
+ {
+-	void __iomem *mmio = ap->host_set->mmio_base;
+-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+-	int work;
+ 	u32 tmp;
+ 
+ 	tmp = readl(port_mmio + PORT_CMD);
++
++	/* Check if the HBA is idle */
++	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
++		return 0;
++
++	/* Setting HBA to idle */
+ 	tmp &= ~PORT_CMD_START;
+ 	writel(tmp, port_mmio + PORT_CMD);
+ 
+-	/* wait for engine to stop.  TODO: this could be
++	/* wait for engine to stop. This could be
+ 	 * as long as 500 msec
+ 	 */
+-	work = 1000;
+-	while (work-- > 0) {
+-		tmp = readl(port_mmio + PORT_CMD);
+-		if ((tmp & PORT_CMD_LIST_ON) == 0)
+-			return 0;
+-		udelay(10);
+-	}
++	tmp = ata_wait_register(port_mmio + PORT_CMD,
++			        PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
++	if(tmp & PORT_CMD_LIST_ON)
++		return -EIO;
+ 
+-	return -EIO;
++	return 0;
+ }
+ 
+-static void ahci_start_engine(struct ata_port *ap)
++static int ahci_start_engine(void __iomem *port_mmio)
+ {
+-	void __iomem *mmio = ap->host_set->mmio_base;
+-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ 	u32 tmp;
+ 
++	/*
++	 * Get current status
++	 */
+ 	tmp = readl(port_mmio + PORT_CMD);
++
++	/*
++	 * AHCI rev 1.1 section 10.3.1:
++	 * Software shall not set PxCMD.ST to '1' until it verifies
++	 * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
++	 */
++	if ((tmp & PORT_CMD_FIS_RX) == 0)
++		return -EPERM;
++
++	/*
++	 * wait for engine to become idle.
++	 */
++	tmp = ata_wait_register(port_mmio + PORT_CMD,
++				PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
++	if(tmp & PORT_CMD_LIST_ON)
++		return -EBUSY;
++
++	/*
++	 * Start DMA
++	 */
+ 	tmp |= PORT_CMD_START;
+ 	writel(tmp, port_mmio + PORT_CMD);
+ 	readl(port_mmio + PORT_CMD); /* flush */
++
++	return 0;
+ }
+ 
+ static unsigned int ahci_dev_classify(struct ata_port *ap)
+@@ -626,7 +651,7 @@ static int ahci_softreset(struct ata_por
+ 	}
+ 
+ 	/* prepare for SRST (AHCI-1.1 10.4.1) */
+-	rc = ahci_stop_engine(ap);
++	rc = ahci_stop_engine(port_mmio);
+ 	if (rc) {
+ 		reason = "failed to stop engine";
+ 		goto fail_restart;
+@@ -647,7 +672,7 @@ static int ahci_softreset(struct ata_por
+ 	}
+ 
+ 	/* restart engine */
+-	ahci_start_engine(ap);
++	ahci_start_engine(port_mmio);
+ 
+ 	ata_tf_init(ap->device, &tf);
+ 	fis = pp->cmd_tbl;
+@@ -706,7 +731,7 @@ static int ahci_softreset(struct ata_por
+ 	return 0;
+ 
+  fail_restart:
+-	ahci_start_engine(ap);
++	ahci_start_engine(port_mmio);
+  fail:
+ 	ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
+ 	return rc;
+@@ -717,11 +742,13 @@ static int ahci_hardreset(struct ata_por
+ 	struct ahci_port_priv *pp = ap->private_data;
+ 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ 	struct ata_taskfile tf;
++	void __iomem *mmio = ap->host_set->mmio_base;
++	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ 	int rc;
+ 
+ 	DPRINTK("ENTER\n");
+ 
+-	ahci_stop_engine(ap);
++	ahci_stop_engine(port_mmio);
+ 
+ 	/* clear D2H reception area to properly wait for D2H FIS */
+ 	ata_tf_init(ap->device, &tf);
+@@ -730,7 +757,7 @@ static int ahci_hardreset(struct ata_por
+ 
+ 	rc = sata_std_hardreset(ap, class);
+ 
+-	ahci_start_engine(ap);
++	ahci_start_engine(port_mmio);
+ 
+ 	if (rc == 0 && ata_port_online(ap))
+ 		*class = ahci_dev_classify(ap);
+@@ -1052,10 +1079,13 @@ static void ahci_thaw(struct ata_port *a
+ 
+ static void ahci_error_handler(struct ata_port *ap)
+ {
++	void __iomem *mmio = ap->host_set->mmio_base;
++	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
++
+ 	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+ 		/* restart engine */
+-		ahci_stop_engine(ap);
+-		ahci_start_engine(ap);
++		ahci_stop_engine(port_mmio);
++		ahci_start_engine(port_mmio);
+ 	}
+ 
+ 	/* perform recovery */
+@@ -1066,14 +1096,16 @@ static void ahci_error_handler(struct at
+ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
++	void __iomem *mmio = ap->host_set->mmio_base;
++	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ 
+ 	if (qc->flags & ATA_QCFLAG_FAILED)
+ 		qc->err_mask |= AC_ERR_OTHER;
+ 
+ 	if (qc->err_mask) {
+ 		/* make DMA engine forget about the failed command */
+-		ahci_stop_engine(ap);
+-		ahci_start_engine(ap);
++		ahci_stop_engine(port_mmio);
++		ahci_start_engine(port_mmio);
+ 	}
+ }
+ 

Added: dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-2.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-2.patch	Tue Oct 10 14:43:21 2006
@@ -0,0 +1,297 @@
+# [PATCH] ahci: relocate several internal functions
+# 254950cd56fee220c9d548f3e57211b95976ba64
+
+diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
+index f1516ca..92e2b95 100644
+--- a/drivers/scsi/ahci.c
++++ b/drivers/scsi/ahci.c
+@@ -205,8 +205,6 @@ static irqreturn_t ahci_interrupt (int i
+ static void ahci_irq_clear(struct ata_port *ap);
+ static int ahci_port_start(struct ata_port *ap);
+ static void ahci_port_stop(struct ata_port *ap);
+-static int ahci_start_engine(void __iomem *port_mmio);
+-static int ahci_stop_engine(void __iomem *port_mmio);
+ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+ static void ahci_qc_prep(struct ata_queued_cmd *qc);
+ static u8 ahci_check_status(struct ata_port *ap);
+@@ -374,108 +372,6 @@ static inline void __iomem *ahci_port_ba
+ 	return (void __iomem *) ahci_port_base_ul((unsigned long)base, port);
+ }
+ 
+-static int ahci_port_start(struct ata_port *ap)
+-{
+-	struct device *dev = ap->host_set->dev;
+-	struct ahci_host_priv *hpriv = ap->host_set->private_data;
+-	struct ahci_port_priv *pp;
+-	void __iomem *mmio = ap->host_set->mmio_base;
+-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+-	void *mem;
+-	dma_addr_t mem_dma;
+-	int rc;
+-
+-	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+-	if (!pp)
+-		return -ENOMEM;
+-	memset(pp, 0, sizeof(*pp));
+-
+-	rc = ata_pad_alloc(ap, dev);
+-	if (rc) {
+-		kfree(pp);
+-		return rc;
+-	}
+-
+-	mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
+-	if (!mem) {
+-		ata_pad_free(ap, dev);
+-		kfree(pp);
+-		return -ENOMEM;
+-	}
+-	memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
+-
+-	/*
+-	 * First item in chunk of DMA memory: 32-slot command table,
+-	 * 32 bytes each in size
+-	 */
+-	pp->cmd_slot = mem;
+-	pp->cmd_slot_dma = mem_dma;
+-
+-	mem += AHCI_CMD_SLOT_SZ;
+-	mem_dma += AHCI_CMD_SLOT_SZ;
+-
+-	/*
+-	 * Second item: Received-FIS area
+-	 */
+-	pp->rx_fis = mem;
+-	pp->rx_fis_dma = mem_dma;
+-
+-	mem += AHCI_RX_FIS_SZ;
+-	mem_dma += AHCI_RX_FIS_SZ;
+-
+-	/*
+-	 * Third item: data area for storing a single command
+-	 * and its scatter-gather table
+-	 */
+-	pp->cmd_tbl = mem;
+-	pp->cmd_tbl_dma = mem_dma;
+-
+-	ap->private_data = pp;
+-
+-	if (hpriv->cap & HOST_CAP_64)
+-		writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
+-	writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
+-	readl(port_mmio + PORT_LST_ADDR); /* flush */
+-
+-	if (hpriv->cap & HOST_CAP_64)
+-		writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
+-	writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
+-	readl(port_mmio + PORT_FIS_ADDR); /* flush */
+-
+-	writel(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
+-	       PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
+-	       PORT_CMD_START, port_mmio + PORT_CMD);
+-	readl(port_mmio + PORT_CMD); /* flush */
+-
+-	return 0;
+-}
+-
+-
+-static void ahci_port_stop(struct ata_port *ap)
+-{
+-	struct device *dev = ap->host_set->dev;
+-	struct ahci_port_priv *pp = ap->private_data;
+-	void __iomem *mmio = ap->host_set->mmio_base;
+-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+-	u32 tmp;
+-
+-	tmp = readl(port_mmio + PORT_CMD);
+-	tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX);
+-	writel(tmp, port_mmio + PORT_CMD);
+-	readl(port_mmio + PORT_CMD); /* flush */
+-
+-	/* spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so
+-	 * this is slightly incorrect.
+-	 */
+-	msleep(500);
+-
+-	ap->private_data = NULL;
+-	dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
+-			  pp->cmd_slot, pp->cmd_slot_dma);
+-	ata_pad_free(ap, dev);
+-	kfree(pp);
+-}
+-
+ static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
+ {
+ 	unsigned int sc_reg;
+@@ -510,31 +406,6 @@ static void ahci_scr_write (struct ata_p
+ 	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ }
+ 
+-static int ahci_stop_engine(void __iomem *port_mmio)
+-{
+-	u32 tmp;
+-
+-	tmp = readl(port_mmio + PORT_CMD);
+-
+-	/* Check if the HBA is idle */
+-	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+-		return 0;
+-
+-	/* Setting HBA to idle */
+-	tmp &= ~PORT_CMD_START;
+-	writel(tmp, port_mmio + PORT_CMD);
+-
+-	/* wait for engine to stop. This could be
+-	 * as long as 500 msec
+-	 */
+-	tmp = ata_wait_register(port_mmio + PORT_CMD,
+-			        PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+-	if(tmp & PORT_CMD_LIST_ON)
+-		return -EIO;
+-
+-	return 0;
+-}
+-
+ static int ahci_start_engine(void __iomem *port_mmio)
+ {
+ 	u32 tmp;
+@@ -570,6 +441,31 @@ static int ahci_start_engine(void __iome
+ 	return 0;
+ }
+ 
++static int ahci_stop_engine(void __iomem *port_mmio)
++{
++	u32 tmp;
++
++	tmp = readl(port_mmio + PORT_CMD);
++
++	/* Check if the HBA is idle */
++	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
++		return 0;
++
++	/* Setting HBA to idle */
++	tmp &= ~PORT_CMD_START;
++	writel(tmp, port_mmio + PORT_CMD);
++
++	/* wait for engine to stop. This could be
++	 * as long as 500 msec
++	 */
++	tmp = ata_wait_register(port_mmio + PORT_CMD,
++			        PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
++	if(tmp & PORT_CMD_LIST_ON)
++		return -EIO;
++
++	return 0;
++}
++
+ static unsigned int ahci_dev_classify(struct ata_port *ap)
+ {
+ 	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+@@ -1109,6 +1005,107 @@ static void ahci_post_internal_cmd(struc
+ 	}
+ }
+ 
++static int ahci_port_start(struct ata_port *ap)
++{
++	struct device *dev = ap->host_set->dev;
++	struct ahci_host_priv *hpriv = ap->host_set->private_data;
++	struct ahci_port_priv *pp;
++	void __iomem *mmio = ap->host_set->mmio_base;
++	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
++	void *mem;
++	dma_addr_t mem_dma;
++	int rc;
++
++	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
++	if (!pp)
++		return -ENOMEM;
++	memset(pp, 0, sizeof(*pp));
++
++	rc = ata_pad_alloc(ap, dev);
++	if (rc) {
++		kfree(pp);
++		return rc;
++	}
++
++	mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
++	if (!mem) {
++		ata_pad_free(ap, dev);
++		kfree(pp);
++		return -ENOMEM;
++	}
++	memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
++
++	/*
++	 * First item in chunk of DMA memory: 32-slot command table,
++	 * 32 bytes each in size
++	 */
++	pp->cmd_slot = mem;
++	pp->cmd_slot_dma = mem_dma;
++
++	mem += AHCI_CMD_SLOT_SZ;
++	mem_dma += AHCI_CMD_SLOT_SZ;
++
++	/*
++	 * Second item: Received-FIS area
++	 */
++	pp->rx_fis = mem;
++	pp->rx_fis_dma = mem_dma;
++
++	mem += AHCI_RX_FIS_SZ;
++	mem_dma += AHCI_RX_FIS_SZ;
++
++	/*
++	 * Third item: data area for storing a single command
++	 * and its scatter-gather table
++	 */
++	pp->cmd_tbl = mem;
++	pp->cmd_tbl_dma = mem_dma;
++
++	ap->private_data = pp;
++
++	if (hpriv->cap & HOST_CAP_64)
++		writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
++	writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
++	readl(port_mmio + PORT_LST_ADDR); /* flush */
++
++	if (hpriv->cap & HOST_CAP_64)
++		writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
++	writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
++	readl(port_mmio + PORT_FIS_ADDR); /* flush */
++
++	writel(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
++	       PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
++	       PORT_CMD_START, port_mmio + PORT_CMD);
++	readl(port_mmio + PORT_CMD); /* flush */
++
++	return 0;
++}
++
++static void ahci_port_stop(struct ata_port *ap)
++{
++	struct device *dev = ap->host_set->dev;
++	struct ahci_port_priv *pp = ap->private_data;
++	void __iomem *mmio = ap->host_set->mmio_base;
++	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
++	u32 tmp;
++
++	tmp = readl(port_mmio + PORT_CMD);
++	tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX);
++	writel(tmp, port_mmio + PORT_CMD);
++	readl(port_mmio + PORT_CMD); /* flush */
++
++	/* spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so
++	 * this is slightly incorrect.
++	 */
++	msleep(500);
++
++	ap->private_data = NULL;
++	dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
++			  pp->cmd_slot, pp->cmd_slot_dma);
++	ata_pad_free(ap, dev);
++	kfree(pp);
++}
++
+ static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
+ 			    unsigned int port_idx)
+ {

Added: dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-3.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-3.patch	Tue Oct 10 14:43:21 2006
@@ -0,0 +1,68 @@
+# [PATCH] ahci: cosmetic changes to ahci_start/stop_engine()
+# d8fcd116d203dfe2f6c272d0cd67724b172f1bc2
+
+diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
+index 92e2b95..ee00aed 100644
+--- a/drivers/scsi/ahci.c
++++ b/drivers/scsi/ahci.c
+@@ -410,30 +410,23 @@ static int ahci_start_engine(void __iome
+ {
+ 	u32 tmp;
+ 
+-	/*
+-	 * Get current status
+-	 */
++	/* get current status */
+ 	tmp = readl(port_mmio + PORT_CMD);
+ 
+-	/*
+-	 * AHCI rev 1.1 section 10.3.1:
++	/* AHCI rev 1.1 section 10.3.1:
+ 	 * Software shall not set PxCMD.ST to '1' until it verifies
+ 	 * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
+ 	 */
+ 	if ((tmp & PORT_CMD_FIS_RX) == 0)
+ 		return -EPERM;
+ 
+-	/*
+-	 * wait for engine to become idle.
+-	 */
++	/* wait for engine to become idle */
+ 	tmp = ata_wait_register(port_mmio + PORT_CMD,
+ 				PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
+-	if(tmp & PORT_CMD_LIST_ON)
++	if (tmp & PORT_CMD_LIST_ON)
+ 		return -EBUSY;
+ 
+-	/*
+-	 * Start DMA
+-	 */
++	/* start DMA */
+ 	tmp |= PORT_CMD_START;
+ 	writel(tmp, port_mmio + PORT_CMD);
+ 	readl(port_mmio + PORT_CMD); /* flush */
+@@ -447,20 +440,18 @@ static int ahci_stop_engine(void __iomem
+ 
+ 	tmp = readl(port_mmio + PORT_CMD);
+ 
+-	/* Check if the HBA is idle */
++	/* check if the HBA is idle */
+ 	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+ 		return 0;
+ 
+-	/* Setting HBA to idle */
++	/* setting HBA to idle */
+ 	tmp &= ~PORT_CMD_START;
+ 	writel(tmp, port_mmio + PORT_CMD);
+ 
+-	/* wait for engine to stop. This could be
+-	 * as long as 500 msec
+-	 */
++	/* wait for engine to stop. This could be as long as 500 msec */
+ 	tmp = ata_wait_register(port_mmio + PORT_CMD,
+ 			        PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+-	if(tmp & PORT_CMD_LIST_ON)
++	if (tmp & PORT_CMD_LIST_ON)
+ 		return -EIO;
+ 
+ 	return 0;

Added: dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-4.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-cleanup-4.patch	Tue Oct 10 14:43:21 2006
@@ -0,0 +1,42 @@
+# [PATCH] ahci: simplify ahci_start_engine()
+# 9f5920567bfabbd1be26112a31c44652b6587394
+
+diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
+index ee00aed..e02b9c6 100644
+--- a/drivers/scsi/ahci.c
++++ b/drivers/scsi/ahci.c
+@@ -406,32 +406,15 @@ static void ahci_scr_write (struct ata_p
+ 	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ }
+ 
+-static int ahci_start_engine(void __iomem *port_mmio)
++static void ahci_start_engine(void __iomem *port_mmio)
+ {
+ 	u32 tmp;
+ 
+-	/* get current status */
+-	tmp = readl(port_mmio + PORT_CMD);
+-
+-	/* AHCI rev 1.1 section 10.3.1:
+-	 * Software shall not set PxCMD.ST to '1' until it verifies
+-	 * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
+-	 */
+-	if ((tmp & PORT_CMD_FIS_RX) == 0)
+-		return -EPERM;
+-
+-	/* wait for engine to become idle */
+-	tmp = ata_wait_register(port_mmio + PORT_CMD,
+-				PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
+-	if (tmp & PORT_CMD_LIST_ON)
+-		return -EBUSY;
+-
+ 	/* start DMA */
++	tmp = readl(port_mmio + PORT_CMD);
+ 	tmp |= PORT_CMD_START;
+ 	writel(tmp, port_mmio + PORT_CMD);
+ 	readl(port_mmio + PORT_CMD); /* flush */
+-
+-	return 0;
+ }
+ 
+ static int ahci_stop_engine(void __iomem *port_mmio)

Added: dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-suspend-1.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-suspend-1.patch	Tue Oct 10 14:43:21 2006
@@ -0,0 +1,281 @@
+# [PATCH] libata: improve driver initialization and deinitialization
+# 0be0aa98985dfec42502c0d0af2a1baff9bdb19f
+
+diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
+index e02b9c6..fb71fa7 100644
+--- a/drivers/scsi/ahci.c
++++ b/drivers/scsi/ahci.c
+@@ -92,7 +92,9 @@ enum {
+ 	HOST_AHCI_EN		= (1 << 31), /* AHCI enabled */
+ 
+ 	/* HOST_CAP bits */
++	HOST_CAP_SSC		= (1 << 14), /* Slumber capable */
+ 	HOST_CAP_CLO		= (1 << 24), /* Command List Override support */
++	HOST_CAP_SSS		= (1 << 27), /* Staggered Spin-up */
+ 	HOST_CAP_NCQ		= (1 << 30), /* Native Command Queueing */
+ 	HOST_CAP_64		= (1 << 31), /* PCI DAC (64-bit DMA) support */
+ 
+@@ -155,6 +157,7 @@ enum {
+ 	PORT_CMD_SPIN_UP	= (1 << 1), /* Spin up device */
+ 	PORT_CMD_START		= (1 << 0), /* Enable port DMA engine */
+ 
++	PORT_CMD_ICC_MASK	= (0xf << 28), /* i/f ICC state mask */
+ 	PORT_CMD_ICC_ACTIVE	= (0x1 << 28), /* Put i/f in active state */
+ 	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
+ 	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
+@@ -440,6 +443,135 @@ static int ahci_stop_engine(void __iomem
+ 	return 0;
+ }
+ 
++static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
++			      dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
++{
++	u32 tmp;
++
++	/* set FIS registers */
++	if (cap & HOST_CAP_64)
++		writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
++	writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
++
++	if (cap & HOST_CAP_64)
++		writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
++	writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
++
++	/* enable FIS reception */
++	tmp = readl(port_mmio + PORT_CMD);
++	tmp |= PORT_CMD_FIS_RX;
++	writel(tmp, port_mmio + PORT_CMD);
++
++	/* flush */
++	readl(port_mmio + PORT_CMD);
++}
++
++static int ahci_stop_fis_rx(void __iomem *port_mmio)
++{
++	u32 tmp;
++
++	/* disable FIS reception */
++	tmp = readl(port_mmio + PORT_CMD);
++	tmp &= ~PORT_CMD_FIS_RX;
++	writel(tmp, port_mmio + PORT_CMD);
++
++	/* wait for completion, spec says 500ms, give it 1000 */
++	tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
++				PORT_CMD_FIS_ON, 10, 1000);
++	if (tmp & PORT_CMD_FIS_ON)
++		return -EBUSY;
++
++	return 0;
++}
++
++static void ahci_power_up(void __iomem *port_mmio, u32 cap)
++{
++	u32 cmd;
++
++	cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
++
++	/* spin up device */
++	if (cap & HOST_CAP_SSS) {
++		cmd |= PORT_CMD_SPIN_UP;
++		writel(cmd, port_mmio + PORT_CMD);
++	}
++
++	/* wake up link */
++	writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
++}
++
++static void ahci_power_down(void __iomem *port_mmio, u32 cap)
++{
++	u32 cmd, scontrol;
++
++	cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
++
++	if (cap & HOST_CAP_SSC) {
++		/* enable transitions to slumber mode */
++		scontrol = readl(port_mmio + PORT_SCR_CTL);
++		if ((scontrol & 0x0f00) > 0x100) {
++			scontrol &= ~0xf00;
++			writel(scontrol, port_mmio + PORT_SCR_CTL);
++		}
++
++		/* put device into slumber mode */
++		writel(cmd | PORT_CMD_ICC_SLUMBER, port_mmio + PORT_CMD);
++
++		/* wait for the transition to complete */
++		ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_ICC_SLUMBER,
++				  PORT_CMD_ICC_SLUMBER, 1, 50);
++	}
++
++	/* put device into listen mode */
++	if (cap & HOST_CAP_SSS) {
++		/* first set PxSCTL.DET to 0 */
++		scontrol = readl(port_mmio + PORT_SCR_CTL);
++		scontrol &= ~0xf;
++		writel(scontrol, port_mmio + PORT_SCR_CTL);
++
++		/* then set PxCMD.SUD to 0 */
++		cmd &= ~PORT_CMD_SPIN_UP;
++		writel(cmd, port_mmio + PORT_CMD);
++	}
++}
++
++static void ahci_init_port(void __iomem *port_mmio, u32 cap,
++			   dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
++{
++	/* power up */
++	ahci_power_up(port_mmio, cap);
++
++	/* enable FIS reception */
++	ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
++
++	/* enable DMA */
++	ahci_start_engine(port_mmio);
++}
++
++static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
++{
++	int rc;
++
++	/* disable DMA */
++	rc = ahci_stop_engine(port_mmio);
++	if (rc) {
++		*emsg = "failed to stop engine";
++		return rc;
++	}
++
++	/* disable FIS reception */
++	rc = ahci_stop_fis_rx(port_mmio);
++	if (rc) {
++		*emsg = "failed stop FIS RX";
++		return rc;
++	}
++
++	/* put device into slumber mode */
++	ahci_power_down(port_mmio, cap);
++
++	return 0;
++}
++
+ static unsigned int ahci_dev_classify(struct ata_port *ap)
+ {
+ 	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+@@ -1037,20 +1169,8 @@ static int ahci_port_start(struct ata_po
+ 
+ 	ap->private_data = pp;
+ 
+-	if (hpriv->cap & HOST_CAP_64)
+-		writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
+-	writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
+-	readl(port_mmio + PORT_LST_ADDR); /* flush */
+-
+-	if (hpriv->cap & HOST_CAP_64)
+-		writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
+-	writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
+-	readl(port_mmio + PORT_FIS_ADDR); /* flush */
+-
+-	writel(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
+-	       PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
+-	       PORT_CMD_START, port_mmio + PORT_CMD);
+-	readl(port_mmio + PORT_CMD); /* flush */
++	/* initialize port */
++	ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
+ 
+ 	return 0;
+ }
+@@ -1058,20 +1178,17 @@ static int ahci_port_start(struct ata_po
+ static void ahci_port_stop(struct ata_port *ap)
+ {
+ 	struct device *dev = ap->host_set->dev;
++	struct ahci_host_priv *hpriv = ap->host_set->private_data;
+ 	struct ahci_port_priv *pp = ap->private_data;
+ 	void __iomem *mmio = ap->host_set->mmio_base;
+ 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+-	u32 tmp;
+-
+-	tmp = readl(port_mmio + PORT_CMD);
+-	tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX);
+-	writel(tmp, port_mmio + PORT_CMD);
+-	readl(port_mmio + PORT_CMD); /* flush */
++	const char *emsg = NULL;
++	int rc;
+ 
+-	/* spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so
+-	 * this is slightly incorrect.
+-	 */
+-	msleep(500);
++	/* de-initialize port */
++	rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
++	if (rc)
++		ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
+ 
+ 	ap->private_data = NULL;
+ 	dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
+@@ -1099,7 +1216,7 @@ static int ahci_host_init(struct ata_pro
+ 	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+ 	void __iomem *mmio = probe_ent->mmio_base;
+ 	u32 tmp, cap_save;
+-	unsigned int i, j, using_dac;
++	unsigned int i, using_dac;
+ 	int rc;
+ 	void __iomem *port_mmio;
+ 
+@@ -1175,6 +1292,8 @@ static int ahci_host_init(struct ata_pro
+ 	}
+ 
+ 	for (i = 0; i < probe_ent->n_ports; i++) {
++		const char *emsg = NULL;
++
+ #if 0 /* BIOSen initialize this incorrectly */
+ 		if (!(hpriv->port_map & (1 << i)))
+ 			continue;
+@@ -1187,43 +1306,24 @@ #endif
+ 				(unsigned long) mmio, i);
+ 
+ 		/* make sure port is not active */
+-		tmp = readl(port_mmio + PORT_CMD);
+-		VPRINTK("PORT_CMD 0x%x\n", tmp);
+-		if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
+-			   PORT_CMD_FIS_RX | PORT_CMD_START)) {
+-			tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
+-				 PORT_CMD_FIS_RX | PORT_CMD_START);
+-			writel(tmp, port_mmio + PORT_CMD);
+-			readl(port_mmio + PORT_CMD); /* flush */
+-
+-			/* spec says 500 msecs for each bit, so
+-			 * this is slightly incorrect.
+-			 */
+-			msleep(500);
+-		}
+-
+-		writel(PORT_CMD_SPIN_UP, port_mmio + PORT_CMD);
+-
+-		j = 0;
+-		while (j < 100) {
+-			msleep(10);
+-			tmp = readl(port_mmio + PORT_SCR_STAT);
+-			if ((tmp & 0xf) == 0x3)
+-				break;
+-			j++;
+-		}
++		rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
++		if (rc)
++			dev_printk(KERN_WARNING, &pdev->dev,
++				   "%s (%d)\n", emsg, rc);
+ 
++		/* clear SError */
+ 		tmp = readl(port_mmio + PORT_SCR_ERR);
+ 		VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
+ 		writel(tmp, port_mmio + PORT_SCR_ERR);
+ 
+-		/* ack any pending irq events for this port */
++		/* clear & turn off port IRQ */
+ 		tmp = readl(port_mmio + PORT_IRQ_STAT);
+ 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
+ 		if (tmp)
+ 			writel(tmp, port_mmio + PORT_IRQ_STAT);
+ 
+ 		writel(1 << i, mmio + HOST_IRQ_STAT);
++		writel(0, port_mmio + PORT_IRQ_MASK);
+ 	}
+ 
+ 	tmp = readl(mmio + HOST_CTL);

Added: dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-suspend-2.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-suspend-2.patch	Tue Oct 10 14:43:21 2006
@@ -0,0 +1,203 @@
+# [PATCH] ahci: separate out ahci_reset_controller() and ahci_init_controller()
+# d91542c11f3981768367815cf087ad36e792ea4a
+
+diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
+index fb71fa7..a9e0c5f 100644
+--- a/drivers/scsi/ahci.c
++++ b/drivers/scsi/ahci.c
+@@ -572,6 +572,94 @@ static int ahci_deinit_port(void __iomem
+ 	return 0;
+ }
+ 
++static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
++{
++	u32 cap_save, tmp;
++
++	cap_save = readl(mmio + HOST_CAP);
++	cap_save &= ( (1<<28) | (1<<17) );
++	cap_save |= (1 << 27);
++
++	/* global controller reset */
++	tmp = readl(mmio + HOST_CTL);
++	if ((tmp & HOST_RESET) == 0) {
++		writel(tmp | HOST_RESET, mmio + HOST_CTL);
++		readl(mmio + HOST_CTL); /* flush */
++	}
++
++	/* reset must complete within 1 second, or
++	 * the hardware should be considered fried.
++	 */
++	ssleep(1);
++
++	tmp = readl(mmio + HOST_CTL);
++	if (tmp & HOST_RESET) {
++		dev_printk(KERN_ERR, &pdev->dev,
++			   "controller reset failed (0x%x)\n", tmp);
++		return -EIO;
++	}
++
++	writel(HOST_AHCI_EN, mmio + HOST_CTL);
++	(void) readl(mmio + HOST_CTL);	/* flush */
++	writel(cap_save, mmio + HOST_CAP);
++	writel(0xf, mmio + HOST_PORTS_IMPL);
++	(void) readl(mmio + HOST_PORTS_IMPL);	/* flush */
++
++	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
++		u16 tmp16;
++
++		/* configure PCS */
++		pci_read_config_word(pdev, 0x92, &tmp16);
++		tmp16 |= 0xf;
++		pci_write_config_word(pdev, 0x92, tmp16);
++	}
++
++	return 0;
++}
++
++static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
++				 int n_ports, u32 cap)
++{
++	int i, rc;
++	u32 tmp;
++
++	for (i = 0; i < n_ports; i++) {
++		void __iomem *port_mmio = ahci_port_base(mmio, i);
++		const char *emsg = NULL;
++
++#if 0 /* BIOSen initialize this incorrectly */
++		if (!(hpriv->port_map & (1 << i)))
++			continue;
++#endif
++
++		/* make sure port is not active */
++		rc = ahci_deinit_port(port_mmio, cap, &emsg);
++		if (rc)
++			dev_printk(KERN_WARNING, &pdev->dev,
++				   "%s (%d)\n", emsg, rc);
++
++		/* clear SError */
++		tmp = readl(port_mmio + PORT_SCR_ERR);
++		VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
++		writel(tmp, port_mmio + PORT_SCR_ERR);
++
++		/* clear & turn off port IRQ */
++		tmp = readl(port_mmio + PORT_IRQ_STAT);
++		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
++		if (tmp)
++			writel(tmp, port_mmio + PORT_IRQ_STAT);
++
++		writel(1 << i, mmio + HOST_IRQ_STAT);
++		writel(0, port_mmio + PORT_IRQ_MASK);
++	}
++
++	tmp = readl(mmio + HOST_CTL);
++	VPRINTK("HOST_CTL 0x%x\n", tmp);
++	writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
++	tmp = readl(mmio + HOST_CTL);
++	VPRINTK("HOST_CTL 0x%x\n", tmp);
++}
++
+ static unsigned int ahci_dev_classify(struct ata_port *ap)
+ {
+ 	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+@@ -1215,47 +1303,12 @@ static int ahci_host_init(struct ata_pro
+ 	struct ahci_host_priv *hpriv = probe_ent->private_data;
+ 	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+ 	void __iomem *mmio = probe_ent->mmio_base;
+-	u32 tmp, cap_save;
+ 	unsigned int i, using_dac;
+ 	int rc;
+-	void __iomem *port_mmio;
+-
+-	cap_save = readl(mmio + HOST_CAP);
+-	cap_save &= ( (1<<28) | (1<<17) );
+-	cap_save |= (1 << 27);
+-
+-	/* global controller reset */
+-	tmp = readl(mmio + HOST_CTL);
+-	if ((tmp & HOST_RESET) == 0) {
+-		writel(tmp | HOST_RESET, mmio + HOST_CTL);
+-		readl(mmio + HOST_CTL); /* flush */
+-	}
+-
+-	/* reset must complete within 1 second, or
+-	 * the hardware should be considered fried.
+-	 */
+-	ssleep(1);
+-
+-	tmp = readl(mmio + HOST_CTL);
+-	if (tmp & HOST_RESET) {
+-		dev_printk(KERN_ERR, &pdev->dev,
+-			   "controller reset failed (0x%x)\n", tmp);
+-		return -EIO;
+-	}
+ 
+-	writel(HOST_AHCI_EN, mmio + HOST_CTL);
+-	(void) readl(mmio + HOST_CTL);	/* flush */
+-	writel(cap_save, mmio + HOST_CAP);
+-	writel(0xf, mmio + HOST_PORTS_IMPL);
+-	(void) readl(mmio + HOST_PORTS_IMPL);	/* flush */
+-
+-	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+-		u16 tmp16;
+-
+-		pci_read_config_word(pdev, 0x92, &tmp16);
+-		tmp16 |= 0xf;
+-		pci_write_config_word(pdev, 0x92, tmp16);
+-	}
++	rc = ahci_reset_controller(mmio, pdev);
++	if (rc)
++		return rc;
+ 
+ 	hpriv->cap = readl(mmio + HOST_CAP);
+ 	hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
+@@ -1291,46 +1344,10 @@ static int ahci_host_init(struct ata_pro
+ 		}
+ 	}
+ 
+-	for (i = 0; i < probe_ent->n_ports; i++) {
+-		const char *emsg = NULL;
+-
+-#if 0 /* BIOSen initialize this incorrectly */
+-		if (!(hpriv->port_map & (1 << i)))
+-			continue;
+-#endif
++	for (i = 0; i < probe_ent->n_ports; i++)
++		ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
+ 
+-		port_mmio = ahci_port_base(mmio, i);
+-		VPRINTK("mmio %p  port_mmio %p\n", mmio, port_mmio);
+-
+-		ahci_setup_port(&probe_ent->port[i],
+-				(unsigned long) mmio, i);
+-
+-		/* make sure port is not active */
+-		rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+-		if (rc)
+-			dev_printk(KERN_WARNING, &pdev->dev,
+-				   "%s (%d)\n", emsg, rc);
+-
+-		/* clear SError */
+-		tmp = readl(port_mmio + PORT_SCR_ERR);
+-		VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
+-		writel(tmp, port_mmio + PORT_SCR_ERR);
+-
+-		/* clear & turn off port IRQ */
+-		tmp = readl(port_mmio + PORT_IRQ_STAT);
+-		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
+-		if (tmp)
+-			writel(tmp, port_mmio + PORT_IRQ_STAT);
+-
+-		writel(1 << i, mmio + HOST_IRQ_STAT);
+-		writel(0, port_mmio + PORT_IRQ_MASK);
+-	}
+-
+-	tmp = readl(mmio + HOST_CTL);
+-	VPRINTK("HOST_CTL 0x%x\n", tmp);
+-	writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
+-	tmp = readl(mmio + HOST_CTL);
+-	VPRINTK("HOST_CTL 0x%x\n", tmp);
++	ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap);
+ 
+ 	pci_set_master(pdev);
+ 

Added: dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-suspend-3.patch
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/features/all/drivers/scsi-ahci-suspend-3.patch	Tue Oct 10 14:43:21 2006
@@ -0,0 +1,126 @@
+# [PATCH] ahci: implement Power Management support
+# c1332875cbe0c148c7f200d4f9b36b64e34d9872
+
+diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
+index a9e0c5f..909a4dc 100644
+--- a/drivers/scsi/ahci.c
++++ b/drivers/scsi/ahci.c
+@@ -215,6 +215,10 @@ static void ahci_freeze(struct ata_port 
+ static void ahci_thaw(struct ata_port *ap);
+ static void ahci_error_handler(struct ata_port *ap);
+ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
++static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
++static int ahci_port_resume(struct ata_port *ap);
++static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
++static int ahci_pci_device_resume(struct pci_dev *pdev);
+ static void ahci_remove_one (struct pci_dev *pdev);
+ 
+ static struct scsi_host_template ahci_sht = {
+@@ -234,6 +238,8 @@ static struct scsi_host_template ahci_sh
+ 	.slave_configure	= ata_scsi_slave_config,
+ 	.slave_destroy		= ata_scsi_slave_destroy,
+ 	.bios_param		= ata_std_bios_param,
++	.suspend		= ata_scsi_device_suspend,
++	.resume			= ata_scsi_device_resume,
+ };
+ 
+ static const struct ata_port_operations ahci_ops = {
+@@ -260,6 +266,9 @@ static const struct ata_port_operations 
+ 	.error_handler		= ahci_error_handler,
+ 	.post_internal_cmd	= ahci_post_internal_cmd,
+ 
++	.port_suspend		= ahci_port_suspend,
++	.port_resume		= ahci_port_resume,
++
+ 	.port_start		= ahci_port_start,
+ 	.port_stop		= ahci_port_stop,
+ };
+@@ -361,6 +370,8 @@ static struct pci_driver ahci_pci_driver
+ 	.name			= DRV_NAME,
+ 	.id_table		= ahci_pci_tbl,
+ 	.probe			= ahci_init_one,
++	.suspend		= ahci_pci_device_suspend,
++	.resume			= ahci_pci_device_resume,
+ 	.remove			= ahci_remove_one,
+ };
+ 
+@@ -1199,6 +1210,79 @@ static void ahci_post_internal_cmd(struc
+ 	}
+ }
+ 
++static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
++{
++	struct ahci_host_priv *hpriv = ap->host_set->private_data;
++	struct ahci_port_priv *pp = ap->private_data;
++	void __iomem *mmio = ap->host_set->mmio_base;
++	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
++	const char *emsg = NULL;
++	int rc;
++
++	rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
++	if (rc) {
++		ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
++		ahci_init_port(port_mmio, hpriv->cap,
++			       pp->cmd_slot_dma, pp->rx_fis_dma);
++	}
++
++	return rc;
++}
++
++static int ahci_port_resume(struct ata_port *ap)
++{
++	struct ahci_port_priv *pp = ap->private_data;
++	struct ahci_host_priv *hpriv = ap->host_set->private_data;
++	void __iomem *mmio = ap->host_set->mmio_base;
++	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
++
++	ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
++
++	return 0;
++}
++
++static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
++{
++	struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
++	void __iomem *mmio = host_set->mmio_base;
++	u32 ctl;
++
++	if (mesg.event == PM_EVENT_SUSPEND) {
++		/* AHCI spec rev1.1 section 8.3.3:
++		 * Software must disable interrupts prior to requesting a
++		 * transition of the HBA to D3 state.
++		 */
++		ctl = readl(mmio + HOST_CTL);
++		ctl &= ~HOST_IRQ_EN;
++		writel(ctl, mmio + HOST_CTL);
++		readl(mmio + HOST_CTL); /* flush */
++	}
++
++	return ata_pci_device_suspend(pdev, mesg);
++}
++
++static int ahci_pci_device_resume(struct pci_dev *pdev)
++{
++	struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
++	struct ahci_host_priv *hpriv = host_set->private_data;
++	void __iomem *mmio = host_set->mmio_base;
++	int rc;
++
++	ata_pci_device_do_resume(pdev);
++
++	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
++		rc = ahci_reset_controller(mmio, pdev);
++		if (rc)
++			return rc;
++
++		ahci_init_controller(mmio, pdev, host_set->n_ports, hpriv->cap);
++	}
++
++	ata_host_set_resume(host_set);
++
++	return 0;
++}
++
+ static int ahci_port_start(struct ata_port *ap)
+ {
+ 	struct device *dev = ap->host_set->dev;

Modified: dists/trunk/linux-2.6/debian/patches/series/3
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/3	(original)
+++ dists/trunk/linux-2.6/debian/patches/series/3	Tue Oct 10 14:43:21 2006
@@ -5,3 +5,10 @@
 + bugfix/mips/cobalt_hz.patch
 + bugfix/mips/real-cpu-cpuinfo.patch
 + bugfix/sky2-receive-FIFO-fix.patch
++ features/all/drivers/scsi-ahci-cleanup-1.patch
++ features/all/drivers/scsi-ahci-cleanup-2.patch
++ features/all/drivers/scsi-ahci-cleanup-3.patch
++ features/all/drivers/scsi-ahci-cleanup-4.patch
++ features/all/drivers/scsi-ahci-suspend-1.patch
++ features/all/drivers/scsi-ahci-suspend-2.patch
++ features/all/drivers/scsi-ahci-suspend-3.patch



More information about the Kernel-svn-changes mailing list