[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