summaryrefslogtreecommitdiffstats
path: root/target/linux/cns3xxx/patches-2.6.31/102-cns3xxx_ata_support.patch
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2012-04-21 16:42:05 +0000
committerGabor Juhos <juhosg@openwrt.org>2012-04-21 16:42:05 +0000
commit26b3cdad1ce60a8f1fd919de9cdbb5251c113efa (patch)
tree9b6bf99af67a5743d9603d24db7d5ab2e3ebeee6 /target/linux/cns3xxx/patches-2.6.31/102-cns3xxx_ata_support.patch
parentb2b965a6962f64ebb23c89d0b587da01a92d5615 (diff)
downloadmaster-31e0f0ae-26b3cdad1ce60a8f1fd919de9cdbb5251c113efa.tar.gz
master-31e0f0ae-26b3cdad1ce60a8f1fd919de9cdbb5251c113efa.tar.bz2
master-31e0f0ae-26b3cdad1ce60a8f1fd919de9cdbb5251c113efa.zip
cns3xxx: remove 2.6.31 support
SVN-Revision: 31418
Diffstat (limited to 'target/linux/cns3xxx/patches-2.6.31/102-cns3xxx_ata_support.patch')
-rw-r--r--target/linux/cns3xxx/patches-2.6.31/102-cns3xxx_ata_support.patch3350
1 files changed, 0 insertions, 3350 deletions
diff --git a/target/linux/cns3xxx/patches-2.6.31/102-cns3xxx_ata_support.patch b/target/linux/cns3xxx/patches-2.6.31/102-cns3xxx_ata_support.patch
deleted file mode 100644
index 5c7156dd2b..0000000000
--- a/target/linux/cns3xxx/patches-2.6.31/102-cns3xxx_ata_support.patch
+++ /dev/null
@@ -1,3350 +0,0 @@
---- /dev/null
-+++ b/drivers/ata/cns3xxx_ahci.c
-@@ -0,0 +1,3281 @@
-+/*
-+ * ahci.c - AHCI SATA support
-+ *
-+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
-+ * Please ALWAYS copy linux-ide@vger.kernel.org
-+ * on emails.
-+ *
-+ * Copyright 2004-2005 Red Hat, Inc.
-+ *
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; see the file COPYING. If not, write to
-+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ *
-+ * libata documentation is available via 'make {ps|pdf}docs',
-+ * as Documentation/DocBook/libata.*
-+ *
-+ * AHCI hardware documentation:
-+ * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
-+ * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
-+ *
-+ */
-+/*
-+ * Cavium CNS3XXX notice
-+ * This driver is copy from ahci, and this driver only modify memory access function.
-+ * Let the driver support non-PCI device
-+ */
-+#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 <linux/interrupt.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/device.h>
-+#include <linux/dmi.h>
-+#include <scsi/scsi_host.h>
-+#include <scsi/scsi_cmnd.h>
-+#include <linux/libata.h>
-+#include <linux/platform_device.h>
-+#include <mach/pm.h>
-+#include <mach/misc.h>
-+
-+#define DRV_NAME "cns3xxx_ahci"
-+#define DRV_VERSION "3.0"
-+
-+#define MISC_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_MISC_BASE_VIRT+offset)))
-+#define CNS3XXX_MISC_REGISTER MISC_REG_VALUE(0x514)
-+#define AHCI_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_SATA2_BASE_VIRT+offset)))
-+#define CNS3XXX_AHCI_HOSTCTL_REG AHCI_REG_VALUE(0x04)
-+
-+/* Enclosure Management Control */
-+#define EM_CTRL_MSG_TYPE 0x000f0000
-+
-+/* Enclosure Management LED Message Type */
-+#define EM_MSG_LED_HBA_PORT 0x0000000f
-+#define EM_MSG_LED_PMP_SLOT 0x0000ff00
-+#define EM_MSG_LED_VALUE 0xffff0000
-+#define EM_MSG_LED_VALUE_ACTIVITY 0x00070000
-+#define EM_MSG_LED_VALUE_OFF 0xfff80000
-+#define EM_MSG_LED_VALUE_ON 0x00010000
-+
-+/* PHY Misc Define */
-+#define MISC_SATA_POWER_MODE MISC_MEM_MAP_VALUE(0x310)
-+#define MISC_SATA_CORE_ID MISC_MEM_MAP_VALUE(0x600)
-+#define MISC_SATA_PORT0_PHY_CFG MISC_MEM_MAP_VALUE(0x604)
-+#define MISC_SATA_PORT1_PHY_CFG MISC_MEM_MAP_VALUE(0x608)
-+#define MISC_SATA_PORT0_PHY_TST MISC_MEM_MAP_VALUE(0x60C)
-+#define MISC_SATA_PORT1_PHY_TST MISC_MEM_MAP_VALUE(0x610)
-+
-+
-+static int ahci_skip_host_reset;
-+static int ahci_ignore_sss;
-+
-+module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
-+MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
-+
-+module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
-+MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
-+
-+static int ahci_enable_alpm(struct ata_port *ap,
-+ enum link_pm policy);
-+static void ahci_disable_alpm(struct ata_port *ap);
-+static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
-+static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
-+ size_t size);
-+static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
-+ ssize_t size);
-+
-+enum {
-+ AHCI_PCI_BAR = 5,
-+ AHCI_MAX_PORTS = 32,
-+ AHCI_MAX_SG = 168, /* hardware max is 64K */
-+ AHCI_DMA_BOUNDARY = 0xffffffff,
-+ AHCI_MAX_CMDS = 32,
-+ AHCI_CMD_SZ = 32,
-+ AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ,
-+ AHCI_RX_FIS_SZ = 256,
-+ AHCI_CMD_TBL_CDB = 0x40,
-+ AHCI_CMD_TBL_HDR_SZ = 0x80,
-+ AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16),
-+ AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
-+ AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
-+ AHCI_RX_FIS_SZ,
-+ AHCI_IRQ_ON_SG = (1 << 31),
-+ AHCI_CMD_ATAPI = (1 << 5),
-+ AHCI_CMD_WRITE = (1 << 6),
-+ AHCI_CMD_PREFETCH = (1 << 7),
-+ AHCI_CMD_RESET = (1 << 8),
-+ AHCI_CMD_CLR_BUSY = (1 << 10),
-+
-+ RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
-+ RX_FIS_SDB = 0x58, /* offset of SDB FIS data */
-+ RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
-+
-+ board_ahci = 0,
-+ board_ahci_vt8251 = 1,
-+ board_ahci_ign_iferr = 2,
-+ board_ahci_sb600 = 3,
-+ board_ahci_mv = 4,
-+ board_ahci_sb700 = 5, /* for SB700 and SB800 */
-+ board_ahci_mcp65 = 6,
-+ board_ahci_nopmp = 7,
-+ board_ahci_yesncq = 8,
-+
-+ /* global controller registers */
-+ HOST_CAP = 0x00, /* host capabilities */
-+ HOST_CTL = 0x04, /* global host control */
-+ HOST_IRQ_STAT = 0x08, /* interrupt status */
-+ HOST_PORTS_IMPL = 0x0c, /* bitmap of implemented ports */
-+ HOST_VERSION = 0x10, /* AHCI spec. version compliancy */
-+ HOST_EM_LOC = 0x1c, /* Enclosure Management location */
-+ HOST_EM_CTL = 0x20, /* Enclosure Management Control */
-+
-+ /* HOST_CTL bits */
-+ HOST_RESET = (1 << 0), /* reset controller; self-clear */
-+ HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
-+ HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
-+
-+ /* HOST_CAP bits */
-+ HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */
-+ HOST_CAP_SSC = (1 << 14), /* Slumber capable */
-+ HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
-+ HOST_CAP_CLO = (1 << 24), /* Command List Override support */
-+ HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
-+ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
-+ HOST_CAP_SNTF = (1 << 29), /* SNotification register */
-+ HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
-+ HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
-+
-+ /* registers for each SATA port */
-+ PORT_LST_ADDR = 0x00, /* command list DMA addr */
-+ PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */
-+ PORT_FIS_ADDR = 0x08, /* FIS rx buf addr */
-+ PORT_FIS_ADDR_HI = 0x0c, /* FIS rx buf addr hi */
-+ PORT_IRQ_STAT = 0x10, /* interrupt status */
-+ PORT_IRQ_MASK = 0x14, /* interrupt enable/disable mask */
-+ PORT_CMD = 0x18, /* port command */
-+ PORT_TFDATA = 0x20, /* taskfile data */
-+ PORT_SIG = 0x24, /* device TF signature */
-+ PORT_CMD_ISSUE = 0x38, /* command issue */
-+ PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */
-+ PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */
-+ PORT_SCR_ERR = 0x30, /* SATA phy register: SError */
-+ PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */
-+ PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */
-+
-+ /* PORT_IRQ_{STAT,MASK} bits */
-+ PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
-+ PORT_IRQ_TF_ERR = (1 << 30), /* task file error */
-+ PORT_IRQ_HBUS_ERR = (1 << 29), /* host bus fatal error */
-+ PORT_IRQ_HBUS_DATA_ERR = (1 << 28), /* host bus data error */
-+ PORT_IRQ_IF_ERR = (1 << 27), /* interface fatal error */
-+ PORT_IRQ_IF_NONFATAL = (1 << 26), /* interface non-fatal error */
-+ PORT_IRQ_OVERFLOW = (1 << 24), /* xfer exhausted available S/G */
-+ PORT_IRQ_BAD_PMP = (1 << 23), /* incorrect port multiplier */
-+
-+ PORT_IRQ_PHYRDY = (1 << 22), /* PhyRdy changed */
-+ PORT_IRQ_DEV_ILCK = (1 << 7), /* device interlock */
-+ PORT_IRQ_CONNECT = (1 << 6), /* port connect change status */
-+ PORT_IRQ_SG_DONE = (1 << 5), /* descriptor processed */
-+ PORT_IRQ_UNK_FIS = (1 << 4), /* unknown FIS rx'd */
-+ PORT_IRQ_SDB_FIS = (1 << 3), /* Set Device Bits FIS rx'd */
-+ PORT_IRQ_DMAS_FIS = (1 << 2), /* DMA Setup FIS rx'd */
-+ PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */
-+ PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */
-+
-+ PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR |
-+ PORT_IRQ_IF_ERR |
-+ PORT_IRQ_CONNECT |
-+ PORT_IRQ_PHYRDY |
-+ PORT_IRQ_UNK_FIS |
-+ PORT_IRQ_BAD_PMP,
-+ PORT_IRQ_ERROR = PORT_IRQ_FREEZE |
-+ PORT_IRQ_TF_ERR |
-+ PORT_IRQ_HBUS_DATA_ERR,
-+ DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
-+ PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
-+ PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
-+
-+ /* PORT_CMD bits */
-+ PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
-+ PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
-+ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
-+ PORT_CMD_PMP = (1 << 17), /* PMP attached */
-+ PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
-+ PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
-+ PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
-+ PORT_CMD_CLO = (1 << 3), /* Command list override */
-+ PORT_CMD_POWER_ON = (1 << 2), /* Power up device */
-+ 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 */
-+
-+ /* hpriv->flags bits */
-+ AHCI_HFLAG_NO_NCQ = (1 << 0),
-+ AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */
-+ AHCI_HFLAG_IGN_SERR_INTERNAL = (1 << 2), /* ignore SERR_INTERNAL */
-+ AHCI_HFLAG_32BIT_ONLY = (1 << 3), /* force 32bit */
-+ AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
-+ AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
-+ AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
-+ AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
-+ AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
-+ AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
-+ AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */
-+ AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as
-+ link offline */
-+
-+ /* ap->flags bits */
-+
-+ AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-+ ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
-+ ATA_FLAG_IPM,
-+
-+ ICH_MAP = 0x90, /* ICH MAP register */
-+
-+ /* em constants */
-+ EM_MAX_SLOTS = 8,
-+ EM_MAX_RETRY = 5,
-+
-+ /* em_ctl bits */
-+ EM_CTL_RST = (1 << 9), /* Reset */
-+ EM_CTL_TM = (1 << 8), /* Transmit Message */
-+ EM_CTL_ALHD = (1 << 26), /* Activity LED */
-+
-+ /* CNS3XXX define */
-+ HOST_TIMER1MS = 0xe0, /* Timer 1ms register */
-+};
-+
-+struct ahci_cmd_hdr {
-+ __le32 opts;
-+ __le32 status;
-+ __le32 tbl_addr;
-+ __le32 tbl_addr_hi;
-+ __le32 reserved[4];
-+};
-+
-+struct ahci_sg {
-+ __le32 addr;
-+ __le32 addr_hi;
-+ __le32 reserved;
-+ __le32 flags_size;
-+};
-+
-+struct ahci_em_priv {
-+ enum sw_activity blink_policy;
-+ struct timer_list timer;
-+ unsigned long saved_activity;
-+ unsigned long activity;
-+ unsigned long led_state;
-+};
-+
-+struct ahci_host_priv {
-+ unsigned int flags; /* AHCI_HFLAG_* */
-+ u32 cap; /* cap to use */
-+ u32 port_map; /* port map to use */
-+ u32 saved_cap; /* saved initial cap */
-+ u32 saved_port_map; /* saved initial port_map */
-+ u32 em_loc; /* enclosure management location */
-+};
-+
-+struct ahci_port_priv {
-+ struct ata_link *active_link;
-+ struct ahci_cmd_hdr *cmd_slot;
-+ dma_addr_t cmd_slot_dma;
-+ void *cmd_tbl;
-+ dma_addr_t cmd_tbl_dma;
-+ void *rx_fis;
-+ dma_addr_t rx_fis_dma;
-+ /* for NCQ spurious interrupt analysis */
-+ unsigned int ncq_saw_d2h:1;
-+ unsigned int ncq_saw_dmas:1;
-+ unsigned int ncq_saw_sdb:1;
-+ u32 intr_mask; /* interrupts to enable */
-+ /* enclosure management info per PM slot */
-+ struct ahci_em_priv em_priv[EM_MAX_SLOTS];
-+};
-+
-+static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
-+static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
-+#if 0
-+static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-+#else
-+static int ahci_probe(struct platform_device *pdev);
-+static int ahci_remove(struct platform_device *pdev);
-+#endif
-+static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
-+static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
-+static int ahci_port_start(struct ata_port *ap);
-+static void ahci_port_stop(struct ata_port *ap);
-+static void ahci_qc_prep(struct ata_queued_cmd *qc);
-+static void ahci_freeze(struct ata_port *ap);
-+static void ahci_thaw(struct ata_port *ap);
-+static void ahci_pmp_attach(struct ata_port *ap);
-+static void ahci_pmp_detach(struct ata_port *ap);
-+static int ahci_softreset(struct ata_link *link, unsigned int *class,
-+ unsigned long deadline);
-+static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
-+ unsigned long deadline);
-+static int ahci_hardreset(struct ata_link *link, unsigned int *class,
-+ unsigned long deadline);
-+static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
-+ unsigned long deadline);
-+#if 0
-+static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
-+ unsigned long deadline);
-+#endif
-+static void ahci_postreset(struct ata_link *link, unsigned int *class);
-+static void ahci_error_handler(struct ata_port *ap);
-+static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
-+static int ahci_port_resume(struct ata_port *ap);
-+static void ahci_dev_config(struct ata_device *dev);
-+static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
-+ u32 opts);
-+#ifdef CONFIG_PM
-+static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
-+static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
-+static int ahci_pci_device_resume(struct pci_dev *pdev);
-+#endif
-+static ssize_t ahci_activity_show(struct ata_device *dev, char *buf);
-+static ssize_t ahci_activity_store(struct ata_device *dev,
-+ enum sw_activity val);
-+static void ahci_init_sw_activity(struct ata_link *link);
-+
-+static struct device_attribute *ahci_shost_attrs[] = {
-+ &dev_attr_link_power_management_policy,
-+ &dev_attr_em_message_type,
-+ &dev_attr_em_message,
-+ NULL
-+};
-+
-+static struct device_attribute *ahci_sdev_attrs[] = {
-+ &dev_attr_sw_activity,
-+ &dev_attr_unload_heads,
-+ NULL
-+};
-+
-+static struct scsi_host_template ahci_sht = {
-+ ATA_NCQ_SHT(DRV_NAME),
-+ .can_queue = AHCI_MAX_CMDS - 1,
-+ .sg_tablesize = AHCI_MAX_SG,
-+ .dma_boundary = AHCI_DMA_BOUNDARY,
-+ .shost_attrs = ahci_shost_attrs,
-+ .sdev_attrs = ahci_sdev_attrs,
-+};
-+
-+static struct ata_port_operations ahci_ops = {
-+ .inherits = &sata_pmp_port_ops,
-+
-+ .qc_defer = sata_pmp_qc_defer_cmd_switch,
-+ .qc_prep = ahci_qc_prep,
-+ .qc_issue = ahci_qc_issue,
-+ .qc_fill_rtf = ahci_qc_fill_rtf,
-+
-+ .freeze = ahci_freeze,
-+ .thaw = ahci_thaw,
-+ .softreset = ahci_softreset,
-+ .hardreset = ahci_hardreset,
-+ .postreset = ahci_postreset,
-+ .pmp_softreset = ahci_softreset,
-+ .error_handler = ahci_error_handler,
-+ .post_internal_cmd = ahci_post_internal_cmd,
-+ .dev_config = ahci_dev_config,
-+
-+ .scr_read = ahci_scr_read,
-+ .scr_write = ahci_scr_write,
-+ .pmp_attach = ahci_pmp_attach,
-+ .pmp_detach = ahci_pmp_detach,
-+
-+ .enable_pm = ahci_enable_alpm,
-+ .disable_pm = ahci_disable_alpm,
-+ .em_show = ahci_led_show,
-+ .em_store = ahci_led_store,
-+ .sw_activity_show = ahci_activity_show,
-+ .sw_activity_store = ahci_activity_store,
-+#ifdef CONFIG_PM
-+ .port_suspend = ahci_port_suspend,
-+ .port_resume = ahci_port_resume,
-+#endif
-+ .port_start = ahci_port_start,
-+ .port_stop = ahci_port_stop,
-+};
-+
-+static struct ata_port_operations ahci_vt8251_ops = {
-+ .inherits = &ahci_ops,
-+ .hardreset = ahci_vt8251_hardreset,
-+};
-+
-+#if 0
-+static struct ata_port_operations ahci_p5wdh_ops = {
-+ .inherits = &ahci_ops,
-+ .hardreset = ahci_p5wdh_hardreset,
-+};
-+#endif
-+
-+static struct ata_port_operations ahci_sb600_ops = {
-+ .inherits = &ahci_ops,
-+ .softreset = ahci_sb600_softreset,
-+ .pmp_softreset = ahci_sb600_softreset,
-+};
-+
-+#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
-+
-+static const struct ata_port_info ahci_port_info[] = {
-+ [board_ahci] =
-+ {
-+ .flags = AHCI_FLAG_COMMON,
-+ .pio_mask = ATA_PIO4,
-+ .udma_mask = ATA_UDMA6,
-+ .port_ops = &ahci_ops,
-+ },
-+ [board_ahci_vt8251] =
-+ {
-+ AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
-+ .flags = AHCI_FLAG_COMMON,
-+ .pio_mask = ATA_PIO4,
-+ .udma_mask = ATA_UDMA6,
-+ .port_ops = &ahci_vt8251_ops,
-+ },
-+ [board_ahci_ign_iferr] =
-+ {
-+ AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
-+ .flags = AHCI_FLAG_COMMON,
-+ .pio_mask = ATA_PIO4,
-+ .udma_mask = ATA_UDMA6,
-+ .port_ops = &ahci_ops,
-+ },
-+ [board_ahci_sb600] =
-+ {
-+ AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
-+ AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255),
-+ .flags = AHCI_FLAG_COMMON,
-+ .pio_mask = ATA_PIO4,
-+ .udma_mask = ATA_UDMA6,
-+ .port_ops = &ahci_sb600_ops,
-+ },
-+ [board_ahci_mv] =
-+ {
-+ AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
-+ AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
-+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
-+ .pio_mask = ATA_PIO4,
-+ .udma_mask = ATA_UDMA6,
-+ .port_ops = &ahci_ops,
-+ },
-+ [board_ahci_sb700] = /* for SB700 and SB800 */
-+ {
-+ AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
-+ .flags = AHCI_FLAG_COMMON,
-+ .pio_mask = ATA_PIO4,
-+ .udma_mask = ATA_UDMA6,
-+ .port_ops = &ahci_sb600_ops,
-+ },
-+ [board_ahci_mcp65] =
-+ {
-+ AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
-+ .flags = AHCI_FLAG_COMMON,
-+ .pio_mask = ATA_PIO4,
-+ .udma_mask = ATA_UDMA6,
-+ .port_ops = &ahci_ops,
-+ },
-+ [board_ahci_nopmp] =
-+ {
-+ AHCI_HFLAGS (AHCI_HFLAG_NO_PMP),
-+ .flags = AHCI_FLAG_COMMON,
-+ .pio_mask = ATA_PIO4,
-+ .udma_mask = ATA_UDMA6,
-+ .port_ops = &ahci_ops,
-+ },
-+ /* board_ahci_yesncq */
-+ {
-+ AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
-+ .flags = AHCI_FLAG_COMMON,
-+ .pio_mask = ATA_PIO4,
-+ .udma_mask = ATA_UDMA6,
-+ .port_ops = &ahci_ops,
-+ },
-+};
-+
-+static const struct pci_device_id ahci_pci_tbl[] = {
-+ /* Intel */
-+ { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
-+ { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
-+ { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
-+ { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
-+ { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
-+ { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
-+ { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
-+ { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
-+ { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
-+ { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
-+ { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
-+ { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
-+ { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
-+ { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
-+ { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
-+ { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
-+ { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
-+ { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
-+ { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
-+ { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
-+ { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
-+ { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
-+ { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
-+ { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
-+ { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
-+ { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
-+ { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
-+ { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
-+ { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
-+ { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
-+ { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
-+ { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
-+ { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
-+ { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
-+ { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
-+ { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
-+ { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
-+ { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
-+ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
-+ { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
-+
-+ /* JMicron 360/1/3/5/6, match class to avoid IDE function */
-+ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-+ PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
-+
-+ /* ATI */
-+ { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
-+ { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
-+ { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
-+ { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
-+ { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
-+ { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
-+ { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
-+
-+ /* VIA */
-+ { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
-+ { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
-+
-+ /* NVIDIA */
-+ { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */
-+ { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */
-+ { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */
-+ { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */
-+ { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */
-+ { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */
-+ { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */
-+ { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */
-+ { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq }, /* MCP67 */
-+ { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_yesncq }, /* MCP73 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci }, /* MCP89 */
-+ { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci }, /* MCP89 */
-+
-+ /* SiS */
-+ { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
-+ { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */
-+ { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
-+
-+ /* Marvell */
-+ { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
-+ { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */
-+
-+ /* Promise */
-+ { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */
-+
-+ /* Generic, PCI class code for AHCI */
-+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-+ PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
-+
-+ { } /* terminate list */
-+};
-+
-+
-+#if 0
-+static struct pci_driver ahci_pci_driver = {
-+ .name = DRV_NAME,
-+ .id_table = ahci_pci_tbl,
-+ .probe = ahci_init_one,
-+ .remove = ata_pci_remove_one,
-+#ifdef CONFIG_PM
-+ .suspend = ahci_pci_device_suspend,
-+ .resume = ahci_pci_device_resume,
-+#endif
-+};
-+#else
-+static struct platform_driver ahci_driver = {
-+ .probe = ahci_probe,
-+ .remove = __devexit_p(ahci_remove),
-+ .driver = {
-+ .name = DRV_NAME,
-+ .owner = THIS_MODULE,
-+ },
-+};
-+#endif
-+
-+static int ahci_em_messages = 1;
-+module_param(ahci_em_messages, int, 0444);
-+/* add other LED protocol types when they become supported */
-+MODULE_PARM_DESC(ahci_em_messages,
-+ "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
-+
-+#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
-+static int marvell_enable;
-+#else
-+static int marvell_enable = 1;
-+#endif
-+module_param(marvell_enable, int, 0644);
-+MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
-+
-+
-+static inline int ahci_nr_ports(u32 cap)
-+{
-+ return (cap & 0x1f) + 1;
-+}
-+
-+static inline void __iomem *__ahci_port_base(struct ata_host *host,
-+ unsigned int port_no)
-+{
-+#if 0
-+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-+#else
-+ void __iomem *mmio = (void __iomem *)host->iomap;//[AHCI_BAR];
-+#endif
-+
-+ return mmio + 0x100 + (port_no * 0x80);
-+}
-+
-+static inline void __iomem *ahci_port_base(struct ata_port *ap)
-+{
-+ return __ahci_port_base(ap->host, ap->port_no);
-+}
-+
-+static void ahci_enable_ahci(void __iomem *mmio)
-+{
-+ int i;
-+ u32 tmp;
-+
-+ /* turn on AHCI_EN */
-+ tmp = readl(mmio + HOST_CTL);
-+ if (tmp & HOST_AHCI_EN)
-+ return;
-+
-+ /* Some controllers need AHCI_EN to be written multiple times.
-+ * Try a few times before giving up.
-+ */
-+ for (i = 0; i < 5; i++) {
-+ tmp |= HOST_AHCI_EN;
-+ writel(tmp, mmio + HOST_CTL);
-+ tmp = readl(mmio + HOST_CTL); /* flush && sanity check */
-+ if (tmp & HOST_AHCI_EN)
-+ return;
-+ msleep(10);
-+ }
-+
-+ WARN_ON(1);
-+}
-+
-+/**
-+ * ahci_save_initial_config - Save and fixup initial config values
-+ * @pdev: target PCI device
-+ * @hpriv: host private area to store config values
-+ *
-+ * Some registers containing configuration info might be setup by
-+ * BIOS and might be cleared on reset. This function saves the
-+ * initial values of those registers into @hpriv such that they
-+ * can be restored after controller reset.
-+ *
-+ * If inconsistent, config values are fixed up by this function.
-+ *
-+ * LOCKING:
-+ * None.
-+ */
-+#if 0
-+static void ahci_save_initial_config(struct pci_dev *pdev,
-+ struct ahci_host_priv *hpriv)
-+#else
-+static void ahci_save_initial_config(struct platform_device *pdev,
-+ struct ahci_host_priv *hpriv,
-+ u8 * base)
-+#endif
-+{
-+#if 0
-+ void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
-+#else
-+ void __iomem *mmio = (void __iomem *)base;
-+#endif
-+ u32 cap, port_map;
-+ int i;
-+#if 0
-+ int mv;
-+#endif
-+
-+ /* make sure AHCI mode is enabled before accessing CAP */
-+ ahci_enable_ahci(mmio);
-+
-+ /* Values prefixed with saved_ are written back to host after
-+ * reset. Values without are used for driver operation.
-+ */
-+ hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
-+ hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
-+
-+ /* some chips have errata preventing 64bit use */
-+ if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
-+ dev_printk(KERN_INFO, &pdev->dev,
-+ "controller can't do 64bit DMA, forcing 32bit\n");
-+ cap &= ~HOST_CAP_64;
-+ }
-+
-+ if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
-+ dev_printk(KERN_INFO, &pdev->dev,
-+ "controller can't do NCQ, turning off CAP_NCQ\n");
-+ cap &= ~HOST_CAP_NCQ;
-+ }
-+
-+ if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
-+ dev_printk(KERN_INFO, &pdev->dev,
-+ "controller can do NCQ, turning on CAP_NCQ\n");
-+ cap |= HOST_CAP_NCQ;
-+ }
-+
-+ if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
-+ dev_printk(KERN_INFO, &pdev->dev,
-+ "controller can't do PMP, turning off CAP_PMP\n");
-+ cap &= ~HOST_CAP_PMP;
-+ }
-+#if 0
-+ if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 &&
-+ port_map != 1) {
-+ dev_printk(KERN_INFO, &pdev->dev,
-+ "JMB361 has only one port, port_map 0x%x -> 0x%x\n",
-+ port_map, 1);
-+ port_map = 1;
-+ }
-+
-+ /*
-+ * Temporary Marvell 6145 hack: PATA port presence
-+ * is asserted through the standard AHCI port
-+ * presence register, as bit 4 (counting from 0)
-+ */
-+ if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
-+ if (pdev->device == 0x6121)
-+ mv = 0x3;
-+ else
-+ mv = 0xf;
-+ dev_printk(KERN_ERR, &pdev->dev,
-+ "MV_AHCI HACK: port_map %x -> %x\n",
-+ port_map,
-+ port_map & mv);
-+ dev_printk(KERN_ERR, &pdev->dev,
-+ "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
-+
-+ port_map &= mv;
-+ }
-+#endif
-+
-+ /* cross check port_map and cap.n_ports */
-+ if (port_map) {
-+ int map_ports = 0;
-+
-+ for (i = 0; i < AHCI_MAX_PORTS; i++)
-+ if (port_map & (1 << i))
-+ map_ports++;
-+
-+ /* If PI has more ports than n_ports, whine, clear
-+ * port_map and let it be generated from n_ports.
-+ */
-+ if (map_ports > ahci_nr_ports(cap)) {
-+ dev_printk(KERN_WARNING, &pdev->dev,
-+ "implemented port map (0x%x) contains more "
-+ "ports than nr_ports (%u), using nr_ports\n",
-+ port_map, ahci_nr_ports(cap));
-+ port_map = 0;
-+ }
-+ }
-+
-+ /* fabricate port_map from cap.nr_ports */
-+ if (!port_map) {
-+ port_map = (1 << ahci_nr_ports(cap)) - 1;
-+ dev_printk(KERN_WARNING, &pdev->dev,
-+ "forcing PORTS_IMPL to 0x%x\n", port_map);
-+
-+ /* write the fixed up value to the PI register */
-+ hpriv->saved_port_map = port_map;
-+ }
-+
-+ /* record values to use during operation */
-+ hpriv->cap = cap;
-+ hpriv->port_map = port_map;
-+}
-+
-+/**
-+ * ahci_restore_initial_config - Restore initial config
-+ * @host: target ATA host
-+ *
-+ * Restore initial config stored by ahci_save_initial_config().
-+ *
-+ * LOCKING:
-+ * None.
-+ */
-+static void ahci_restore_initial_config(struct ata_host *host)
-+{
-+ struct ahci_host_priv *hpriv = host->private_data;
-+#if 0
-+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-+#else
-+ void __iomem *mmio = (void __iomem *)host->iomap;//[AHCI_BAR];
-+#endif
-+
-+ writel(hpriv->saved_cap, mmio + HOST_CAP);
-+ writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
-+ (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
-+}
-+
-+static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
-+{
-+ static const int offset[] = {
-+ [SCR_STATUS] = PORT_SCR_STAT,
-+ [SCR_CONTROL] = PORT_SCR_CTL,
-+ [SCR_ERROR] = PORT_SCR_ERR,
-+ [SCR_ACTIVE] = PORT_SCR_ACT,
-+ [SCR_NOTIFICATION] = PORT_SCR_NTF,
-+ };
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+
-+ if (sc_reg < ARRAY_SIZE(offset) &&
-+ (sc_reg != SCR_NOTIFICATION || (hpriv->cap & HOST_CAP_SNTF)))
-+ return offset[sc_reg];
-+ return 0;
-+}
-+
-+static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
-+{
-+ void __iomem *port_mmio = ahci_port_base(link->ap);
-+ int offset = ahci_scr_offset(link->ap, sc_reg);
-+
-+ if (offset) {
-+ *val = readl(port_mmio + offset);
-+ return 0;
-+ }
-+ return -EINVAL;
-+}
-+
-+static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
-+{
-+ void __iomem *port_mmio = ahci_port_base(link->ap);
-+ int offset = ahci_scr_offset(link->ap, sc_reg);
-+
-+ if (offset) {
-+ writel(val, port_mmio + offset);
-+ return 0;
-+ }
-+ return -EINVAL;
-+}
-+
-+static void ahci_start_engine(struct ata_port *ap)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ u32 tmp;
-+
-+ /* start DMA */
-+ tmp = readl(port_mmio + PORT_CMD);
-+ tmp |= PORT_CMD_START;
-+ writel(tmp, port_mmio + PORT_CMD);
-+ readl(port_mmio + PORT_CMD); /* flush */
-+}
-+
-+static int ahci_stop_engine(struct ata_port *ap)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ 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 void ahci_start_fis_rx(struct ata_port *ap)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ u32 tmp;
-+
-+ /* set FIS registers */
-+ 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);
-+
-+ 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);
-+
-+ /* 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(struct ata_port *ap)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ 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(struct ata_port *ap)
-+{
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ u32 cmd;
-+
-+ cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
-+
-+ /* spin up device */
-+ if (hpriv->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_disable_alpm(struct ata_port *ap)
-+{
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ u32 cmd;
-+ struct ahci_port_priv *pp = ap->private_data;
-+
-+ /* IPM bits should be disabled by libata-core */
-+ /* get the existing command bits */
-+ cmd = readl(port_mmio + PORT_CMD);
-+
-+ /* disable ALPM and ASP */
-+ cmd &= ~PORT_CMD_ASP;
-+ cmd &= ~PORT_CMD_ALPE;
-+
-+ /* force the interface back to active */
-+ cmd |= PORT_CMD_ICC_ACTIVE;
-+
-+ /* write out new cmd value */
-+ writel(cmd, port_mmio + PORT_CMD);
-+ cmd = readl(port_mmio + PORT_CMD);
-+
-+ /* wait 10ms to be sure we've come out of any low power state */
-+ msleep(10);
-+
-+ /* clear out any PhyRdy stuff from interrupt status */
-+ writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
-+
-+ /* go ahead and clean out PhyRdy Change from Serror too */
-+ ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
-+
-+ /*
-+ * Clear flag to indicate that we should ignore all PhyRdy
-+ * state changes
-+ */
-+ hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
-+
-+ /*
-+ * Enable interrupts on Phy Ready.
-+ */
-+ pp->intr_mask |= PORT_IRQ_PHYRDY;
-+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
-+
-+ /*
-+ * don't change the link pm policy - we can be called
-+ * just to turn of link pm temporarily
-+ */
-+}
-+
-+static int ahci_enable_alpm(struct ata_port *ap,
-+ enum link_pm policy)
-+{
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ u32 cmd;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ u32 asp;
-+
-+ /* Make sure the host is capable of link power management */
-+ if (!(hpriv->cap & HOST_CAP_ALPM))
-+ return -EINVAL;
-+
-+ switch (policy) {
-+ case MAX_PERFORMANCE:
-+ case NOT_AVAILABLE:
-+ /*
-+ * if we came here with NOT_AVAILABLE,
-+ * it just means this is the first time we
-+ * have tried to enable - default to max performance,
-+ * and let the user go to lower power modes on request.
-+ */
-+ ahci_disable_alpm(ap);
-+ return 0;
-+ case MIN_POWER:
-+ /* configure HBA to enter SLUMBER */
-+ asp = PORT_CMD_ASP;
-+ break;
-+ case MEDIUM_POWER:
-+ /* configure HBA to enter PARTIAL */
-+ asp = 0;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * Disable interrupts on Phy Ready. This keeps us from
-+ * getting woken up due to spurious phy ready interrupts
-+ * TBD - Hot plug should be done via polling now, is
-+ * that even supported?
-+ */
-+ pp->intr_mask &= ~PORT_IRQ_PHYRDY;
-+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
-+
-+ /*
-+ * Set a flag to indicate that we should ignore all PhyRdy
-+ * state changes since these can happen now whenever we
-+ * change link state
-+ */
-+ hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
-+
-+ /* get the existing command bits */
-+ cmd = readl(port_mmio + PORT_CMD);
-+
-+ /*
-+ * Set ASP based on Policy
-+ */
-+ cmd |= asp;
-+
-+ /*
-+ * Setting this bit will instruct the HBA to aggressively
-+ * enter a lower power link state when it's appropriate and
-+ * based on the value set above for ASP
-+ */
-+ cmd |= PORT_CMD_ALPE;
-+
-+ /* write out new cmd value */
-+ writel(cmd, port_mmio + PORT_CMD);
-+ cmd = readl(port_mmio + PORT_CMD);
-+
-+ /* IPM bits should be set by libata-core */
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static void ahci_power_down(struct ata_port *ap)
-+{
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ u32 cmd, scontrol;
-+
-+ if (!(hpriv->cap & HOST_CAP_SSS))
-+ return;
-+
-+ /* put device into listen mode, 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 = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
-+ cmd &= ~PORT_CMD_SPIN_UP;
-+ writel(cmd, port_mmio + PORT_CMD);
-+}
-+#endif
-+
-+static void ahci_start_port(struct ata_port *ap)
-+{
-+ struct ahci_port_priv *pp = ap->private_data;
-+ struct ata_link *link;
-+ struct ahci_em_priv *emp;
-+ ssize_t rc;
-+ int i;
-+
-+ /* enable FIS reception */
-+ ahci_start_fis_rx(ap);
-+
-+ /* enable DMA */
-+ ahci_start_engine(ap);
-+
-+ /* turn on LEDs */
-+ if (ap->flags & ATA_FLAG_EM) {
-+ ata_for_each_link(link, ap, EDGE) {
-+ emp = &pp->em_priv[link->pmp];
-+
-+ /* EM Transmit bit maybe busy during init */
-+ for (i = 0; i < EM_MAX_RETRY; i++) {
-+ rc = ahci_transmit_led_message(ap,
-+ emp->led_state,
-+ 4);
-+ if (rc == -EBUSY)
-+ msleep(1);
-+ else
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (ap->flags & ATA_FLAG_SW_ACTIVITY)
-+ ata_for_each_link(link, ap, EDGE)
-+ ahci_init_sw_activity(link);
-+
-+}
-+
-+static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
-+{
-+ int rc;
-+
-+ /* disable DMA */
-+ rc = ahci_stop_engine(ap);
-+ if (rc) {
-+ *emsg = "failed to stop engine";
-+ return rc;
-+ }
-+
-+ /* disable FIS reception */
-+ rc = ahci_stop_fis_rx(ap);
-+ if (rc) {
-+ *emsg = "failed stop FIS RX";
-+ return rc;
-+ }
-+
-+ return 0;
-+}
-+
-+static int ahci_reset_controller(struct ata_host *host)
-+{
-+#if 0
-+ struct pci_dev *pdev = to_pci_dev(host->dev);
-+ struct ahci_host_priv *hpriv = host->private_data;
-+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-+#else
-+ void __iomem *mmio = (void __iomem *)host->iomap;//[AHCI_BAR];
-+#endif
-+ u32 tmp;
-+
-+ /* we must be in AHCI mode, before using anything
-+ * AHCI-specific, such as HOST_RESET.
-+ */
-+ ahci_enable_ahci(mmio);
-+
-+ /* global controller reset */
-+ if (!ahci_skip_host_reset) {
-+ tmp = readl(mmio + HOST_CTL);
-+ if ((tmp & HOST_RESET) == 0) {
-+ writel(tmp | HOST_RESET, mmio + HOST_CTL);
-+ readl(mmio + HOST_CTL); /* flush */
-+ }
-+
-+ /*
-+ * to perform host reset, OS should set HOST_RESET
-+ * and poll until this bit is read to be "0".
-+ * reset must complete within 1 second, or
-+ * the hardware should be considered fried.
-+ */
-+ tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET,
-+ HOST_RESET, 10, 1000);
-+
-+ if (tmp & HOST_RESET) {
-+ dev_printk(KERN_ERR, host->dev,
-+ "controller reset failed (0x%x)\n", tmp);
-+ return -EIO;
-+ }
-+
-+ /* turn on AHCI mode */
-+ ahci_enable_ahci(mmio);
-+
-+ /* Some registers might be cleared on reset. Restore
-+ * initial values.
-+ */
-+ ahci_restore_initial_config(host);
-+ } else
-+ dev_printk(KERN_INFO, host->dev,
-+ "skipping global host reset\n");
-+
-+#if 0
-+ if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
-+ u16 tmp16;
-+
-+ /* configure PCS */
-+ pci_read_config_word(pdev, 0x92, &tmp16);
-+ if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
-+ tmp16 |= hpriv->port_map;
-+ pci_write_config_word(pdev, 0x92, tmp16);
-+ }
-+ }
-+#endif
-+
-+ return 0;
-+}
-+
-+static void ahci_sw_activity(struct ata_link *link)
-+{
-+ struct ata_port *ap = link->ap;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
-+
-+ if (!(link->flags & ATA_LFLAG_SW_ACTIVITY))
-+ return;
-+
-+ emp->activity++;
-+ if (!timer_pending(&emp->timer))
-+ mod_timer(&emp->timer, jiffies + msecs_to_jiffies(10));
-+}
-+
-+static void ahci_sw_activity_blink(unsigned long arg)
-+{
-+ struct ata_link *link = (struct ata_link *)arg;
-+ struct ata_port *ap = link->ap;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
-+ unsigned long led_message = emp->led_state;
-+ u32 activity_led_state;
-+ unsigned long flags;
-+
-+ led_message &= EM_MSG_LED_VALUE;
-+ led_message |= ap->port_no | (link->pmp << 8);
-+
-+ /* check to see if we've had activity. If so,
-+ * toggle state of LED and reset timer. If not,
-+ * turn LED to desired idle state.
-+ */
-+ spin_lock_irqsave(ap->lock, flags);
-+ if (emp->saved_activity != emp->activity) {
-+ emp->saved_activity = emp->activity;
-+ /* get the current LED state */
-+ activity_led_state = led_message & EM_MSG_LED_VALUE_ON;
-+
-+ if (activity_led_state)
-+ activity_led_state = 0;
-+ else
-+ activity_led_state = 1;
-+
-+ /* clear old state */
-+ led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
-+
-+ /* toggle state */
-+ led_message |= (activity_led_state << 16);
-+ mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100));
-+ } else {
-+ /* switch to idle */
-+ led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
-+ if (emp->blink_policy == BLINK_OFF)
-+ led_message |= (1 << 16);
-+ }
-+ spin_unlock_irqrestore(ap->lock, flags);
-+ ahci_transmit_led_message(ap, led_message, 4);
-+}
-+
-+static void ahci_init_sw_activity(struct ata_link *link)
-+{
-+ struct ata_port *ap = link->ap;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
-+
-+ /* init activity stats, setup timer */
-+ emp->saved_activity = emp->activity = 0;
-+ setup_timer(&emp->timer, ahci_sw_activity_blink, (unsigned long)link);
-+
-+ /* check our blink policy and set flag for link if it's enabled */
-+ if (emp->blink_policy)
-+ link->flags |= ATA_LFLAG_SW_ACTIVITY;
-+}
-+
-+static int ahci_reset_em(struct ata_host *host)
-+{
-+#if 0
-+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-+#else
-+ void __iomem *mmio = (void __iomem *)host->iomap;//[AHCI_BAR];
-+#endif
-+ u32 em_ctl;
-+
-+ em_ctl = readl(mmio + HOST_EM_CTL);
-+ if ((em_ctl & EM_CTL_TM) || (em_ctl & EM_CTL_RST))
-+ return -EINVAL;
-+
-+ writel(em_ctl | EM_CTL_RST, mmio + HOST_EM_CTL);
-+ return 0;
-+}
-+
-+static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
-+ ssize_t size)
-+{
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+ struct ahci_port_priv *pp = ap->private_data;
-+#if 0
-+ void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-+#else
-+ void __iomem *mmio = (void __iomem *)ap->host->iomap;//[AHCI_BAR];
-+#endif
-+ u32 em_ctl;
-+ u32 message[] = {0, 0};
-+ unsigned long flags;
-+ int pmp;
-+ struct ahci_em_priv *emp;
-+
-+ /* get the slot number from the message */
-+ pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
-+ if (pmp < EM_MAX_SLOTS)
-+ emp = &pp->em_priv[pmp];
-+ else
-+ return -EINVAL;
-+
-+ spin_lock_irqsave(ap->lock, flags);
-+
-+ /*
-+ * if we are still busy transmitting a previous message,
-+ * do not allow
-+ */
-+ em_ctl = readl(mmio + HOST_EM_CTL);
-+ if (em_ctl & EM_CTL_TM) {
-+ spin_unlock_irqrestore(ap->lock, flags);
-+ return -EBUSY;
-+ }
-+
-+ /*
-+ * create message header - this is all zero except for
-+ * the message size, which is 4 bytes.
-+ */
-+ message[0] |= (4 << 8);
-+
-+ /* ignore 0:4 of byte zero, fill in port info yourself */
-+ message[1] = ((state & ~EM_MSG_LED_HBA_PORT) | ap->port_no);
-+
-+ /* write message to EM_LOC */
-+ writel(message[0], mmio + hpriv->em_loc);
-+ writel(message[1], mmio + hpriv->em_loc+4);
-+
-+ /* save off new led state for port/slot */
-+ emp->led_state = state;
-+
-+ /*
-+ * tell hardware to transmit the message
-+ */
-+ writel(em_ctl | EM_CTL_TM, mmio + HOST_EM_CTL);
-+
-+ spin_unlock_irqrestore(ap->lock, flags);
-+ return size;
-+}
-+
-+static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
-+{
-+ struct ahci_port_priv *pp = ap->private_data;
-+ struct ata_link *link;
-+ struct ahci_em_priv *emp;
-+ int rc = 0;
-+
-+ ata_for_each_link(link, ap, EDGE) {
-+ emp = &pp->em_priv[link->pmp];
-+ rc += sprintf(buf, "%lx\n", emp->led_state);
-+ }
-+ return rc;
-+}
-+
-+static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
-+ size_t size)
-+{
-+ int state;
-+ int pmp;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ struct ahci_em_priv *emp;
-+
-+ state = simple_strtoul(buf, NULL, 0);
-+
-+ /* get the slot number from the message */
-+ pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
-+ if (pmp < EM_MAX_SLOTS)
-+ emp = &pp->em_priv[pmp];
-+ else
-+ return -EINVAL;
-+
-+ /* mask off the activity bits if we are in sw_activity
-+ * mode, user should turn off sw_activity before setting
-+ * activity led through em_message
-+ */
-+ if (emp->blink_policy)
-+ state &= ~EM_MSG_LED_VALUE_ACTIVITY;
-+
-+ return ahci_transmit_led_message(ap, state, size);
-+}
-+
-+static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)
-+{
-+ struct ata_link *link = dev->link;
-+ struct ata_port *ap = link->ap;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
-+ u32 port_led_state = emp->led_state;
-+
-+ /* save the desired Activity LED behavior */
-+ if (val == OFF) {
-+ /* clear LFLAG */
-+ link->flags &= ~(ATA_LFLAG_SW_ACTIVITY);
-+
-+ /* set the LED to OFF */
-+ port_led_state &= EM_MSG_LED_VALUE_OFF;
-+ port_led_state |= (ap->port_no | (link->pmp << 8));
-+ ahci_transmit_led_message(ap, port_led_state, 4);
-+ } else {
-+ link->flags |= ATA_LFLAG_SW_ACTIVITY;
-+ if (val == BLINK_OFF) {
-+ /* set LED to ON for idle */
-+ port_led_state &= EM_MSG_LED_VALUE_OFF;
-+ port_led_state |= (ap->port_no | (link->pmp << 8));
-+ port_led_state |= EM_MSG_LED_VALUE_ON; /* check this */
-+ ahci_transmit_led_message(ap, port_led_state, 4);
-+ }
-+ }
-+ emp->blink_policy = val;
-+ return 0;
-+}
-+
-+static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
-+{
-+ struct ata_link *link = dev->link;
-+ struct ata_port *ap = link->ap;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
-+
-+ /* display the saved value of activity behavior for this
-+ * disk.
-+ */
-+ return sprintf(buf, "%d\n", emp->blink_policy);
-+}
-+
-+#if 0
-+static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
-+ int port_no, void __iomem *mmio,
-+ void __iomem *port_mmio)
-+#else
-+static void ahci_port_init(struct platform_device *pdev, struct ata_port *ap,
-+ int port_no, void __iomem *mmio,
-+ void __iomem *port_mmio)
-+#endif
-+{
-+ const char *emsg = NULL;
-+ int rc;
-+ u32 tmp;
-+
-+ /* make sure port is not active */
-+ rc = ahci_deinit_port(ap, &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 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 << port_no, mmio + HOST_IRQ_STAT);
-+}
-+
-+static void ahci_init_controller(struct ata_host *host)
-+{
-+ struct ahci_host_priv *hpriv = host->private_data;
-+#if 0
-+ struct pci_dev *pdev = to_pci_dev(host->dev);
-+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-+#else
-+ struct platform_device *pdev = to_platform_device(host->dev);
-+ void __iomem *mmio = (void __iomem *)host->iomap;//[AHCI_BAR];
-+#endif
-+ int i;
-+ void __iomem *port_mmio;
-+ u32 tmp;
-+ int mv;
-+
-+ if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
-+#if 0
-+ if (pdev->device == 0x6121)
-+ mv = 2;
-+ else
-+ mv = 4;
-+#else
-+ mv = 0;
-+#endif
-+ port_mmio = __ahci_port_base(host, mv);
-+
-+ writel(0, port_mmio + PORT_IRQ_MASK);
-+
-+ /* clear 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);
-+ }
-+
-+ /* set Timer 1ms, hclk = 200Mhz */
-+ /* FIXME: Add auto detect function */
-+ printk("CPU clock : %d \n", cns3xxx_cpu_clock());
-+ tmp = readl(mmio + HOST_TIMER1MS);
-+ printk("*** Timer 1ms: %d(0x%x) ***\n",tmp,tmp);
-+ writel(cns3xxx_cpu_clock()*500, mmio + HOST_TIMER1MS);
-+ tmp = readl(mmio + HOST_TIMER1MS);
-+ printk("*** Set to: %d(0x%x) ***\n",tmp, tmp);
-+
-+
-+
-+ for (i = 0; i < host->n_ports; i++) {
-+ struct ata_port *ap = host->ports[i];
-+
-+ port_mmio = ahci_port_base(ap);
-+ if (ata_port_is_dummy(ap))
-+ continue;
-+
-+ ahci_port_init(pdev, ap, i, mmio, port_mmio);
-+ }
-+
-+ 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 void ahci_dev_config(struct ata_device *dev)
-+{
-+ struct ahci_host_priv *hpriv = dev->link->ap->host->private_data;
-+
-+ if (hpriv->flags & AHCI_HFLAG_SECT255) {
-+ dev->max_sectors = 255;
-+ ata_dev_printk(dev, KERN_INFO,
-+ "SB600 AHCI: limiting to 255 sectors per cmd\n");
-+ }
-+}
-+
-+static unsigned int ahci_dev_classify(struct ata_port *ap)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ struct ata_taskfile tf;
-+ u32 tmp;
-+
-+ tmp = readl(port_mmio + PORT_SIG);
-+ tf.lbah = (tmp >> 24) & 0xff;
-+ tf.lbam = (tmp >> 16) & 0xff;
-+ tf.lbal = (tmp >> 8) & 0xff;
-+ tf.nsect = (tmp) & 0xff;
-+
-+ return ata_dev_classify(&tf);
-+}
-+
-+static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
-+ u32 opts)
-+{
-+ dma_addr_t cmd_tbl_dma;
-+
-+ cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
-+
-+#if 0
-+ pp->cmd_slot[tag].opts = cpu_to_le32(opts);
-+#else
-+ pp->cmd_slot[tag].opts = opts;
-+#endif
-+ pp->cmd_slot[tag].status = 0;
-+#if 0
-+ pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
-+ pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
-+#else
-+ pp->cmd_slot[tag].tbl_addr = cmd_tbl_dma & 0xffffffff;
-+ pp->cmd_slot[tag].tbl_addr_hi = (cmd_tbl_dma >> 16) >> 16;
-+#endif
-+}
-+
-+static int ahci_kick_engine(struct ata_port *ap, int force_restart)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+ u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
-+ u32 tmp;
-+ int busy, rc;
-+
-+ /* do we need to kick the port? */
-+ busy = status & (ATA_BUSY | ATA_DRQ);
-+ if (!busy && !force_restart)
-+ return 0;
-+
-+ /* stop engine */
-+ rc = ahci_stop_engine(ap);
-+ if (rc)
-+ goto out_restart;
-+
-+ /* need to do CLO? */
-+ if (!busy) {
-+ rc = 0;
-+ goto out_restart;
-+ }
-+
-+ if (!(hpriv->cap & HOST_CAP_CLO)) {
-+ rc = -EOPNOTSUPP;
-+ goto out_restart;
-+ }
-+
-+ /* perform CLO */
-+ tmp = readl(port_mmio + PORT_CMD);
-+ tmp |= PORT_CMD_CLO;
-+ writel(tmp, port_mmio + PORT_CMD);
-+
-+ rc = 0;
-+ tmp = ata_wait_register(port_mmio + PORT_CMD,
-+ PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
-+ if (tmp & PORT_CMD_CLO)
-+ rc = -EIO;
-+
-+ /* restart engine */
-+ out_restart:
-+ ahci_start_engine(ap);
-+ return rc;
-+}
-+
-+static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
-+ struct ata_taskfile *tf, int is_cmd, u16 flags,
-+ unsigned long timeout_msec)
-+{
-+ const u32 cmd_fis_len = 5; /* five dwords */
-+ struct ahci_port_priv *pp = ap->private_data;
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ u8 *fis = pp->cmd_tbl;
-+ u32 tmp;
-+
-+ /* prep the command */
-+ ata_tf_to_fis(tf, pmp, is_cmd, fis);
-+ ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12));
-+
-+ /* issue & wait */
-+ writel(1, port_mmio + PORT_CMD_ISSUE);
-+
-+ if (timeout_msec) {
-+ tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1,
-+ 1, timeout_msec);
-+ if (tmp & 0x1) {
-+ ahci_kick_engine(ap, 1);
-+ return -EBUSY;
-+ }
-+ } else
-+ readl(port_mmio + PORT_CMD_ISSUE); /* flush */
-+
-+ return 0;
-+}
-+
-+static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
-+ int pmp, unsigned long deadline,
-+ int (*check_ready)(struct ata_link *link))
-+{
-+ struct ata_port *ap = link->ap;
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+ const char *reason = NULL;
-+ unsigned long now, msecs;
-+ struct ata_taskfile tf;
-+ int rc;
-+
-+ DPRINTK("ENTER\n");
-+
-+ /* prepare for SRST (AHCI-1.1 10.4.1) */
-+ rc = ahci_kick_engine(ap, 1);
-+ if (rc && rc != -EOPNOTSUPP)
-+ ata_link_printk(link, KERN_WARNING,
-+ "failed to reset engine (errno=%d)\n", rc);
-+
-+ ata_tf_init(link->device, &tf);
-+
-+ /* issue the first D2H Register FIS */
-+ msecs = 0;
-+ now = jiffies;
-+ if (time_after(now, deadline))
-+ msecs = jiffies_to_msecs(deadline - now);
-+
-+ tf.ctl |= ATA_SRST;
-+ if (ahci_exec_polled_cmd(ap, pmp, &tf, 0,
-+ AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs)) {
-+ rc = -EIO;
-+ reason = "1st FIS failed";
-+ goto fail;
-+ }
-+
-+ /* spec says at least 5us, but be generous and sleep for 1ms */
-+ msleep(1);
-+
-+ /* issue the second D2H Register FIS */
-+ tf.ctl &= ~ATA_SRST;
-+ ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
-+
-+ /* wait for link to become ready */
-+ rc = ata_wait_after_reset(link, deadline, check_ready);
-+ if (rc == -EBUSY && hpriv->flags & AHCI_HFLAG_SRST_TOUT_IS_OFFLINE) {
-+ /*
-+ * Workaround for cases where link online status can't
-+ * be trusted. Treat device readiness timeout as link
-+ * offline.
-+ */
-+ ata_link_printk(link, KERN_INFO,
-+ "device not ready, treating as offline\n");
-+ *class = ATA_DEV_NONE;
-+ } else if (rc) {
-+ /* link occupied, -ENODEV too is an error */
-+ reason = "device not ready";
-+ goto fail;
-+ } else
-+ *class = ahci_dev_classify(ap);
-+
-+ DPRINTK("EXIT, class=%u\n", *class);
-+ return 0;
-+
-+ fail:
-+ ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
-+ return rc;
-+}
-+
-+static int ahci_check_ready(struct ata_link *link)
-+{
-+ void __iomem *port_mmio = ahci_port_base(link->ap);
-+ u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
-+
-+ return ata_check_ready(status);
-+}
-+
-+static int ahci_softreset(struct ata_link *link, unsigned int *class,
-+ unsigned long deadline)
-+{
-+ int pmp = sata_srst_pmp(link);
-+
-+ DPRINTK("ENTER\n");
-+
-+ return ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
-+}
-+
-+static int ahci_sb600_check_ready(struct ata_link *link)
-+{
-+ void __iomem *port_mmio = ahci_port_base(link->ap);
-+ u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
-+ u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
-+
-+ /*
-+ * There is no need to check TFDATA if BAD PMP is found due to HW bug,
-+ * which can save timeout delay.
-+ */
-+ if (irq_status & PORT_IRQ_BAD_PMP)
-+ return -EIO;
-+
-+ return ata_check_ready(status);
-+}
-+
-+static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
-+ unsigned long deadline)
-+{
-+ struct ata_port *ap = link->ap;
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ int pmp = sata_srst_pmp(link);
-+ int rc;
-+ u32 irq_sts;
-+
-+ DPRINTK("ENTER\n");
-+
-+ rc = ahci_do_softreset(link, class, pmp, deadline,
-+ ahci_sb600_check_ready);
-+
-+ /*
-+ * Soft reset fails on some ATI chips with IPMS set when PMP
-+ * is enabled but SATA HDD/ODD is connected to SATA port,
-+ * do soft reset again to port 0.
-+ */
-+ if (rc == -EIO) {
-+ irq_sts = readl(port_mmio + PORT_IRQ_STAT);
-+ if (irq_sts & PORT_IRQ_BAD_PMP) {
-+ ata_link_printk(link, KERN_WARNING,
-+ "applying SB600 PMP SRST workaround "
-+ "and retrying\n");
-+ rc = ahci_do_softreset(link, class, 0, deadline,
-+ ahci_check_ready);
-+ }
-+ }
-+
-+ return rc;
-+}
-+
-+static int ahci_hardreset(struct ata_link *link, unsigned int *class,
-+ unsigned long deadline)
-+{
-+ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
-+ struct ata_port *ap = link->ap;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
-+ struct ata_taskfile tf;
-+ bool online;
-+ int rc;
-+
-+ DPRINTK("ENTER\n");
-+
-+ ahci_stop_engine(ap);
-+
-+ /* clear D2H reception area to properly wait for D2H FIS */
-+ ata_tf_init(link->device, &tf);
-+ tf.command = 0x80;
-+ ata_tf_to_fis(&tf, 0, 0, d2h_fis);
-+
-+ rc = sata_link_hardreset(link, timing, deadline, &online,
-+ ahci_check_ready);
-+
-+ ahci_start_engine(ap);
-+
-+ if (online)
-+ *class = ahci_dev_classify(ap);
-+
-+ DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
-+ return rc;
-+}
-+
-+static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
-+ unsigned long deadline)
-+{
-+ struct ata_port *ap = link->ap;
-+ bool online;
-+ int rc;
-+
-+ DPRINTK("ENTER\n");
-+
-+ ahci_stop_engine(ap);
-+
-+ rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
-+ deadline, &online, NULL);
-+
-+ ahci_start_engine(ap);
-+
-+ DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
-+
-+ /* vt8251 doesn't clear BSY on signature FIS reception,
-+ * request follow-up softreset.
-+ */
-+ return online ? -EAGAIN : rc;
-+}
-+
-+#if 0
-+static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
-+ unsigned long deadline)
-+{
-+ struct ata_port *ap = link->ap;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
-+ struct ata_taskfile tf;
-+ bool online;
-+ int rc;
-+
-+ ahci_stop_engine(ap);
-+
-+ /* clear D2H reception area to properly wait for D2H FIS */
-+ ata_tf_init(link->device, &tf);
-+ tf.command = 0x80;
-+ ata_tf_to_fis(&tf, 0, 0, d2h_fis);
-+
-+ rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
-+ deadline, &online, NULL);
-+
-+ ahci_start_engine(ap);
-+
-+ /* The pseudo configuration device on SIMG4726 attached to
-+ * ASUS P5W-DH Deluxe doesn't send signature FIS after
-+ * hardreset if no device is attached to the first downstream
-+ * port && the pseudo device locks up on SRST w/ PMP==0. To
-+ * work around this, wait for !BSY only briefly. If BSY isn't
-+ * cleared, perform CLO and proceed to IDENTIFY (achieved by
-+ * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
-+ *
-+ * Wait for two seconds. Devices attached to downstream port
-+ * which can't process the following IDENTIFY after this will
-+ * have to be reset again. For most cases, this should
-+ * suffice while making probing snappish enough.
-+ */
-+ if (online) {
-+ rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
-+ ahci_check_ready);
-+ if (rc)
-+ ahci_kick_engine(ap, 0);
-+ }
-+ return rc;
-+}
-+#endif
-+
-+static void ahci_postreset(struct ata_link *link, unsigned int *class)
-+{
-+ struct ata_port *ap = link->ap;
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ u32 new_tmp, tmp;
-+
-+ ata_std_postreset(link, class);
-+
-+ /* Make sure port's ATAPI bit is set appropriately */
-+ new_tmp = tmp = readl(port_mmio + PORT_CMD);
-+ if (*class == ATA_DEV_ATAPI)
-+ new_tmp |= PORT_CMD_ATAPI;
-+ else
-+ new_tmp &= ~PORT_CMD_ATAPI;
-+ if (new_tmp != tmp) {
-+ writel(new_tmp, port_mmio + PORT_CMD);
-+ readl(port_mmio + PORT_CMD); /* flush */
-+ }
-+}
-+
-+static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
-+{
-+ struct scatterlist *sg;
-+ struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
-+ unsigned int si;
-+
-+ VPRINTK("ENTER\n");
-+
-+ /*
-+ * Next, the S/G list.
-+ */
-+ for_each_sg(qc->sg, sg, qc->n_elem, si) {
-+ dma_addr_t addr = sg_dma_address(sg);
-+ u32 sg_len = sg_dma_len(sg);
-+
-+#if 0
-+ ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
-+ ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
-+ ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
-+#else
-+ ahci_sg[si].addr = addr & 0xffffffff;
-+ ahci_sg[si].addr_hi = (addr >> 16) >> 16;
-+ ahci_sg[si].flags_size = sg_len - 1;
-+#endif
-+ }
-+
-+ return si;
-+}
-+
-+static void ahci_qc_prep(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ int is_atapi = ata_is_atapi(qc->tf.protocol);
-+ void *cmd_tbl;
-+ u32 opts;
-+ const u32 cmd_fis_len = 5; /* five dwords */
-+ unsigned int n_elem;
-+
-+ /*
-+ * Fill in command table information. First, the header,
-+ * a SATA Register - Host to Device command FIS.
-+ */
-+ cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
-+
-+ ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl);
-+ if (is_atapi) {
-+ memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
-+ memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
-+ }
-+
-+ n_elem = 0;
-+ if (qc->flags & ATA_QCFLAG_DMAMAP)
-+ n_elem = ahci_fill_sg(qc, cmd_tbl);
-+
-+ /*
-+ * Fill in command slot information.
-+ */
-+ opts = cmd_fis_len | n_elem << 16 | (qc->dev->link->pmp << 12);
-+ if (qc->tf.flags & ATA_TFLAG_WRITE)
-+ opts |= AHCI_CMD_WRITE;
-+ if (is_atapi)
-+ opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
-+
-+ ahci_fill_cmd_slot(pp, qc->tag, opts);
-+}
-+
-+static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
-+{
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ struct ata_eh_info *host_ehi = &ap->link.eh_info;
-+ struct ata_link *link = NULL;
-+ struct ata_queued_cmd *active_qc;
-+ struct ata_eh_info *active_ehi;
-+ u32 serror;
-+
-+ /* determine active link */
-+ ata_for_each_link(link, ap, EDGE)
-+ if (ata_link_active(link))
-+ break;
-+ if (!link)
-+ link = &ap->link;
-+
-+ active_qc = ata_qc_from_tag(ap, link->active_tag);
-+ active_ehi = &link->eh_info;
-+
-+ /* record irq stat */
-+ ata_ehi_clear_desc(host_ehi);
-+ ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);
-+
-+ /* AHCI needs SError cleared; otherwise, it might lock up */
-+ ahci_scr_read(&ap->link, SCR_ERROR, &serror);
-+ ahci_scr_write(&ap->link, SCR_ERROR, serror);
-+ host_ehi->serror |= serror;
-+
-+ /* some controllers set IRQ_IF_ERR on device errors, ignore it */
-+ if (hpriv->flags & AHCI_HFLAG_IGN_IRQ_IF_ERR)
-+ irq_stat &= ~PORT_IRQ_IF_ERR;
-+
-+ if (irq_stat & PORT_IRQ_TF_ERR) {
-+ /* If qc is active, charge it; otherwise, the active
-+ * link. There's no active qc on NCQ errors. It will
-+ * be determined by EH by reading log page 10h.
-+ */
-+ if (active_qc)
-+ active_qc->err_mask |= AC_ERR_DEV;
-+ else
-+ active_ehi->err_mask |= AC_ERR_DEV;
-+
-+ if (hpriv->flags & AHCI_HFLAG_IGN_SERR_INTERNAL)
-+ host_ehi->serror &= ~SERR_INTERNAL;
-+ }
-+
-+ if (irq_stat & PORT_IRQ_UNK_FIS) {
-+ u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
-+
-+ active_ehi->err_mask |= AC_ERR_HSM;
-+ active_ehi->action |= ATA_EH_RESET;
-+ ata_ehi_push_desc(active_ehi,
-+ "unknown FIS %08x %08x %08x %08x" ,
-+ unk[0], unk[1], unk[2], unk[3]);
-+ }
-+
-+ if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
-+ active_ehi->err_mask |= AC_ERR_HSM;
-+ active_ehi->action |= ATA_EH_RESET;
-+ ata_ehi_push_desc(active_ehi, "incorrect PMP");
-+ }
-+
-+ if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
-+ host_ehi->err_mask |= AC_ERR_HOST_BUS;
-+ host_ehi->action |= ATA_EH_RESET;
-+ ata_ehi_push_desc(host_ehi, "host bus error");
-+ }
-+
-+ if (irq_stat & PORT_IRQ_IF_ERR) {
-+ host_ehi->err_mask |= AC_ERR_ATA_BUS;
-+ host_ehi->action |= ATA_EH_RESET;
-+ ata_ehi_push_desc(host_ehi, "interface fatal error");
-+ }
-+
-+ if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
-+ ata_ehi_hotplugged(host_ehi);
-+ ata_ehi_push_desc(host_ehi, "%s",
-+ irq_stat & PORT_IRQ_CONNECT ?
-+ "connection status changed" : "PHY RDY changed");
-+ }
-+
-+ /* okay, let's hand over to EH */
-+
-+ if (irq_stat & PORT_IRQ_FREEZE)
-+ ata_port_freeze(ap);
-+ else
-+ ata_port_abort(ap);
-+}
-+
-+static void ahci_port_intr(struct ata_port *ap)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ struct ata_eh_info *ehi = &ap->link.eh_info;
-+ struct ahci_port_priv *pp = ap->private_data;
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+ int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
-+ u32 status, qc_active;
-+ int rc;
-+
-+ status = readl(port_mmio + PORT_IRQ_STAT);
-+ writel(status, port_mmio + PORT_IRQ_STAT);
-+
-+ /* ignore BAD_PMP while resetting */
-+ if (unlikely(resetting))
-+ status &= ~PORT_IRQ_BAD_PMP;
-+
-+ /* If we are getting PhyRdy, this is
-+ * just a power state change, we should
-+ * clear out this, plus the PhyRdy/Comm
-+ * Wake bits from Serror
-+ */
-+ if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
-+ (status & PORT_IRQ_PHYRDY)) {
-+ status &= ~PORT_IRQ_PHYRDY;
-+ ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
-+ }
-+
-+ if (unlikely(status & PORT_IRQ_ERROR)) {
-+ ahci_error_intr(ap, status);
-+ return;
-+ }
-+
-+ if (status & PORT_IRQ_SDB_FIS) {
-+ /* If SNotification is available, leave notification
-+ * handling to sata_async_notification(). If not,
-+ * emulate it by snooping SDB FIS RX area.
-+ *
-+ * Snooping FIS RX area is probably cheaper than
-+ * poking SNotification but some constrollers which
-+ * implement SNotification, ICH9 for example, don't
-+ * store AN SDB FIS into receive area.
-+ */
-+ if (hpriv->cap & HOST_CAP_SNTF)
-+ sata_async_notification(ap);
-+ else {
-+ /* If the 'N' bit in word 0 of the FIS is set,
-+ * we just received asynchronous notification.
-+ * Tell libata about it.
-+ */
-+ const __le32 *f = pp->rx_fis + RX_FIS_SDB;
-+#if 0
-+ u32 f0 = le32_to_cpu(f[0]);
-+#else
-+ u32 f0 = f[0];
-+#endif
-+
-+ if (f0 & (1 << 15))
-+ sata_async_notification(ap);
-+ }
-+ }
-+
-+ /* pp->active_link is valid iff any command is in flight */
-+ if (ap->qc_active && pp->active_link->sactive)
-+ qc_active = readl(port_mmio + PORT_SCR_ACT);
-+ else
-+ qc_active = readl(port_mmio + PORT_CMD_ISSUE);
-+
-+ rc = ata_qc_complete_multiple(ap, qc_active);
-+
-+ /* while resetting, invalid completions are expected */
-+ if (unlikely(rc < 0 && !resetting)) {
-+ ehi->err_mask |= AC_ERR_HSM;
-+ ehi->action |= ATA_EH_RESET;
-+ ata_port_freeze(ap);
-+ }
-+}
-+
-+static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
-+{
-+ struct ata_host *host = dev_instance;
-+ struct ahci_host_priv *hpriv;
-+ unsigned int i, handled = 0;
-+ void __iomem *mmio;
-+ u32 irq_stat, irq_masked;
-+
-+ VPRINTK("ENTER\n");
-+
-+ hpriv = host->private_data;
-+#if 0
-+ mmio = host->iomap[AHCI_PCI_BAR];
-+#else
-+ mmio = (void __iomem *)host->iomap;//[AHCI_BAR];
-+#endif
-+
-+ /* sigh. 0xffffffff is a valid return from h/w */
-+ irq_stat = readl(mmio + HOST_IRQ_STAT);
-+ if (!irq_stat)
-+ return IRQ_NONE;
-+
-+ irq_masked = irq_stat & hpriv->port_map;
-+
-+ spin_lock(&host->lock);
-+
-+ for (i = 0; i < host->n_ports; i++) {
-+ struct ata_port *ap;
-+
-+ if (!(irq_masked & (1 << i)))
-+ continue;
-+
-+ ap = host->ports[i];
-+ if (ap) {
-+ ahci_port_intr(ap);
-+ VPRINTK("port %u\n", i);
-+ } else {
-+ VPRINTK("port %u (no irq)\n", i);
-+ if (ata_ratelimit())
-+ dev_printk(KERN_WARNING, host->dev,
-+ "interrupt on disabled port %u\n", i);
-+ }
-+
-+ handled = 1;
-+ }
-+
-+ /* HOST_IRQ_STAT behaves as level triggered latch meaning that
-+ * it should be cleared after all the port events are cleared;
-+ * otherwise, it will raise a spurious interrupt after each
-+ * valid one. Please read section 10.6.2 of ahci 1.1 for more
-+ * information.
-+ *
-+ * Also, use the unmasked value to clear interrupt as spurious
-+ * pending event on a dummy port might cause screaming IRQ.
-+ */
-+ writel(irq_stat, mmio + HOST_IRQ_STAT);
-+
-+ spin_unlock(&host->lock);
-+
-+ VPRINTK("EXIT\n");
-+
-+ return IRQ_RETVAL(handled);
-+}
-+
-+static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ struct ahci_port_priv *pp = ap->private_data;
-+
-+ /* Keep track of the currently active link. It will be used
-+ * in completion path to determine whether NCQ phase is in
-+ * progress.
-+ */
-+ pp->active_link = qc->dev->link;
-+
-+ if (qc->tf.protocol == ATA_PROT_NCQ)
-+ writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
-+ writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
-+
-+ ahci_sw_activity(qc->dev->link);
-+
-+ return 0;
-+}
-+
-+static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
-+{
-+ struct ahci_port_priv *pp = qc->ap->private_data;
-+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
-+
-+ ata_tf_from_fis(d2h_fis, &qc->result_tf);
-+ return true;
-+}
-+
-+static void ahci_freeze(struct ata_port *ap)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+
-+ /* turn IRQ off */
-+ writel(0, port_mmio + PORT_IRQ_MASK);
-+}
-+
-+static void ahci_thaw(struct ata_port *ap)
-+{
-+#if 0
-+ void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-+#else
-+ void __iomem *mmio = (void __iomem *)ap->host->iomap;//[AHCI_BAR];
-+#endif
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ u32 tmp;
-+ struct ahci_port_priv *pp = ap->private_data;
-+
-+ /* clear IRQ */
-+ tmp = readl(port_mmio + PORT_IRQ_STAT);
-+ writel(tmp, port_mmio + PORT_IRQ_STAT);
-+ writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
-+
-+ /* turn IRQ back on */
-+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
-+}
-+
-+static void ahci_error_handler(struct ata_port *ap)
-+{
-+ if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
-+ /* restart engine */
-+ ahci_stop_engine(ap);
-+ ahci_start_engine(ap);
-+ }
-+
-+ sata_pmp_error_handler(ap);
-+}
-+
-+static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+
-+ /* make DMA engine forget about the failed command */
-+ if (qc->flags & ATA_QCFLAG_FAILED)
-+ ahci_kick_engine(ap, 1);
-+}
-+
-+static void ahci_pmp_attach(struct ata_port *ap)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ struct ahci_port_priv *pp = ap->private_data;
-+ u32 cmd;
-+
-+ cmd = readl(port_mmio + PORT_CMD);
-+ cmd |= PORT_CMD_PMP;
-+ writel(cmd, port_mmio + PORT_CMD);
-+
-+ pp->intr_mask |= PORT_IRQ_BAD_PMP;
-+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
-+}
-+
-+static void ahci_pmp_detach(struct ata_port *ap)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ struct ahci_port_priv *pp = ap->private_data;
-+ u32 cmd;
-+
-+ cmd = readl(port_mmio + PORT_CMD);
-+ cmd &= ~PORT_CMD_PMP;
-+ writel(cmd, port_mmio + PORT_CMD);
-+
-+ pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
-+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
-+}
-+
-+static int ahci_port_resume(struct ata_port *ap)
-+{
-+ ahci_power_up(ap);
-+ ahci_start_port(ap);
-+
-+ if (sata_pmp_attached(ap))
-+ ahci_pmp_attach(ap);
-+ else
-+ ahci_pmp_detach(ap);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
-+{
-+ const char *emsg = NULL;
-+ int rc;
-+
-+ rc = ahci_deinit_port(ap, &emsg);
-+ if (rc == 0)
-+ ahci_power_down(ap);
-+ else {
-+ ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
-+ ahci_start_port(ap);
-+ }
-+
-+ return rc;
-+}
-+
-+static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
-+{
-+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
-+ struct ahci_host_priv *hpriv = host->private_data;
-+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-+ u32 ctl;
-+
-+ if (mesg.event & PM_EVENT_SUSPEND &&
-+ hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
-+ dev_printk(KERN_ERR, &pdev->dev,
-+ "BIOS update required for suspend/resume\n");
-+ return -EIO;
-+ }
-+
-+ if (mesg.event & PM_EVENT_SLEEP) {
-+ /* 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 *host = dev_get_drvdata(&pdev->dev);
-+ int rc;
-+
-+ rc = ata_pci_device_do_resume(pdev);
-+ if (rc)
-+ return rc;
-+
-+ if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-+ rc = ahci_reset_controller(host);
-+ if (rc)
-+ return rc;
-+
-+ ahci_init_controller(host);
-+ }
-+
-+ ata_host_resume(host);
-+
-+ return 0;
-+}
-+#endif
-+
-+static int ahci_port_start(struct ata_port *ap)
-+{
-+ struct device *dev = ap->host->dev;
-+ struct ahci_port_priv *pp;
-+ void *mem;
-+ dma_addr_t mem_dma;
-+
-+ pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
-+ if (!pp)
-+ return -ENOMEM;
-+
-+ mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
-+ GFP_KERNEL);
-+ if (!mem)
-+ 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;
-+
-+ /*
-+ * Save off initial list of interrupts to be enabled.
-+ * This could be changed later
-+ */
-+ pp->intr_mask = DEF_PORT_IRQ;
-+
-+ ap->private_data = pp;
-+
-+ /* engage engines, captain */
-+ return ahci_port_resume(ap);
-+}
-+
-+static void ahci_port_stop(struct ata_port *ap)
-+{
-+ const char *emsg = NULL;
-+ int rc;
-+
-+ /* de-initialize port */
-+ rc = ahci_deinit_port(ap, &emsg);
-+ if (rc)
-+ ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
-+}
-+
-+#if 0
-+static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
-+{
-+ int rc;
-+
-+ if (using_dac &&
-+ !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-+ rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
-+ if (rc) {
-+ rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-+ if (rc) {
-+ dev_printk(KERN_ERR, &pdev->dev,
-+ "64-bit DMA enable failed\n");
-+ return rc;
-+ }
-+ }
-+ } else {
-+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-+ if (rc) {
-+ dev_printk(KERN_ERR, &pdev->dev,
-+ "32-bit DMA enable failed\n");
-+ return rc;
-+ }
-+ rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-+ if (rc) {
-+ dev_printk(KERN_ERR, &pdev->dev,
-+ "32-bit consistent DMA enable failed\n");
-+ return rc;
-+ }
-+ }
-+ return 0;
-+}
-+#endif
-+
-+static void ahci_print_info(struct ata_host *host)
-+{
-+ struct ahci_host_priv *hpriv = host->private_data;
-+#if 0
-+ struct pci_dev *pdev = to_pci_dev(host->dev);
-+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-+#else
-+ struct platform_device *pdev = to_platform_device(host->dev);
-+ void __iomem *mmio = (void __iomem *)host->iomap;//[AHCI_BAR];
-+#endif
-+ u32 vers, cap, impl, speed;
-+ const char *speed_s;
-+#if 0
-+ u16 cc;
-+#endif
-+ const char *scc_s;
-+
-+ vers = readl(mmio + HOST_VERSION);
-+ cap = hpriv->cap;
-+ impl = hpriv->port_map;
-+
-+ speed = (cap >> 20) & 0xf;
-+ if (speed == 1)
-+ speed_s = "1.5";
-+ else if (speed == 2)
-+ speed_s = "3";
-+ else if (speed == 3)
-+ speed_s = "6";
-+ else
-+ speed_s = "?";
-+
-+#if 0
-+ pci_read_config_word(pdev, 0x0a, &cc);
-+ if (cc == PCI_CLASS_STORAGE_IDE)
-+ scc_s = "IDE";
-+ else if (cc == PCI_CLASS_STORAGE_SATA)
-+ scc_s = "SATA";
-+ else if (cc == PCI_CLASS_STORAGE_RAID)
-+ scc_s = "RAID";
-+ else
-+ scc_s = "unknown";
-+#else
-+ scc_s = "SATA";
-+#endif
-+
-+ dev_printk(KERN_INFO, &pdev->dev,
-+ "AHCI %02x%02x.%02x%02x "
-+ "%u slots %u ports %s Gbps 0x%x impl %s mode\n"
-+ ,
-+
-+ (vers >> 24) & 0xff,
-+ (vers >> 16) & 0xff,
-+ (vers >> 8) & 0xff,
-+ vers & 0xff,
-+
-+ ((cap >> 8) & 0x1f) + 1,
-+ (cap & 0x1f) + 1,
-+ speed_s,
-+ impl,
-+ scc_s);
-+
-+ dev_printk(KERN_INFO, &pdev->dev,
-+ "flags: "
-+ "%s%s%s%s%s%s%s"
-+ "%s%s%s%s%s%s%s"
-+ "%s\n"
-+ ,
-+
-+ cap & (1 << 31) ? "64bit " : "",
-+ cap & (1 << 30) ? "ncq " : "",
-+ cap & (1 << 29) ? "sntf " : "",
-+ cap & (1 << 28) ? "ilck " : "",
-+ cap & (1 << 27) ? "stag " : "",
-+ cap & (1 << 26) ? "pm " : "",
-+ cap & (1 << 25) ? "led " : "",
-+
-+ cap & (1 << 24) ? "clo " : "",
-+ cap & (1 << 19) ? "nz " : "",
-+ cap & (1 << 18) ? "only " : "",
-+ cap & (1 << 17) ? "pmp " : "",
-+ cap & (1 << 15) ? "pio " : "",
-+ cap & (1 << 14) ? "slum " : "",
-+ cap & (1 << 13) ? "part " : "",
-+ cap & (1 << 6) ? "ems ": ""
-+ );
-+}
-+
-+#if 0
-+/* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
-+ * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't
-+ * support PMP and the 4726 either directly exports the device
-+ * attached to the first downstream port or acts as a hardware storage
-+ * controller and emulate a single ATA device (can be RAID 0/1 or some
-+ * other configuration).
-+ *
-+ * When there's no device attached to the first downstream port of the
-+ * 4726, "Config Disk" appears, which is a pseudo ATA device to
-+ * configure the 4726. However, ATA emulation of the device is very
-+ * lame. It doesn't send signature D2H Reg FIS after the initial
-+ * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
-+ *
-+ * The following function works around the problem by always using
-+ * hardreset on the port and not depending on receiving signature FIS
-+ * afterward. If signature FIS isn't received soon, ATA class is
-+ * assumed without follow-up softreset.
-+ */
-+static void ahci_p5wdh_workaround(struct ata_host *host)
-+{
-+ static struct dmi_system_id sysids[] = {
-+ {
-+ .ident = "P5W DH Deluxe",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR,
-+ "ASUSTEK COMPUTER INC"),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
-+ },
-+ },
-+ { }
-+ };
-+ struct pci_dev *pdev = to_pci_dev(host->dev);
-+
-+ if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
-+ dmi_check_system(sysids)) {
-+ struct ata_port *ap = host->ports[1];
-+
-+ dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
-+ "Deluxe on-board SIMG4726 workaround\n");
-+
-+ ap->ops = &ahci_p5wdh_ops;
-+ ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
-+ }
-+}
-+
-+/*
-+ * SB600 ahci controller on ASUS M2A-VM can't do 64bit DMA with older
-+ * BIOS. The oldest version known to be broken is 0901 and working is
-+ * 1501 which was released on 2007-10-26. Force 32bit DMA on anything
-+ * older than 1501. Please read bko#9412 for more info.
-+ */
-+static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev)
-+{
-+ static const struct dmi_system_id sysids[] = {
-+ {
-+ .ident = "ASUS M2A-VM",
-+ .matches = {
-+ DMI_MATCH(DMI_BOARD_VENDOR,
-+ "ASUSTeK Computer INC."),
-+ DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
-+ },
-+ },
-+ { }
-+ };
-+ const char *cutoff_mmdd = "10/26";
-+ const char *date;
-+ int year;
-+
-+ if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
-+ !dmi_check_system(sysids))
-+ return false;
-+
-+ /*
-+ * Argh.... both version and date are free form strings.
-+ * Let's hope they're using the same date format across
-+ * different versions.
-+ */
-+ date = dmi_get_system_info(DMI_BIOS_DATE);
-+ year = dmi_get_year(DMI_BIOS_DATE);
-+ if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' &&
-+ (year > 2007 ||
-+ (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0)))
-+ return false;
-+
-+ dev_printk(KERN_WARNING, &pdev->dev, "ASUS M2A-VM: BIOS too old, "
-+ "forcing 32bit DMA, update BIOS\n");
-+
-+ return true;
-+}
-+
-+static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
-+{
-+ static const struct dmi_system_id broken_systems[] = {
-+ {
-+ .ident = "HP Compaq nx6310",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
-+ },
-+ /* PCI slot number of the controller */
-+ .driver_data = (void *)0x1FUL,
-+ },
-+ {
-+ .ident = "HP Compaq 6720s",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
-+ },
-+ /* PCI slot number of the controller */
-+ .driver_data = (void *)0x1FUL,
-+ },
-+
-+ { } /* terminate list */
-+ };
-+ const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
-+
-+ if (dmi) {
-+ unsigned long slot = (unsigned long)dmi->driver_data;
-+ /* apply the quirk only to on-board controllers */
-+ return slot == PCI_SLOT(pdev->devfn);
-+ }
-+
-+ return false;
-+}
-+
-+static bool ahci_broken_suspend(struct pci_dev *pdev)
-+{
-+ static const struct dmi_system_id sysids[] = {
-+ /*
-+ * On HP dv[4-6] and HDX18 with earlier BIOSen, link
-+ * to the harddisk doesn't become online after
-+ * resuming from STR. Warn and fail suspend.
-+ */
-+ {
-+ .ident = "dv4",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-+ DMI_MATCH(DMI_PRODUCT_NAME,
-+ "HP Pavilion dv4 Notebook PC"),
-+ },
-+ .driver_data = "F.30", /* cutoff BIOS version */
-+ },
-+ {
-+ .ident = "dv5",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-+ DMI_MATCH(DMI_PRODUCT_NAME,
-+ "HP Pavilion dv5 Notebook PC"),
-+ },
-+ .driver_data = "F.16", /* cutoff BIOS version */
-+ },
-+ {
-+ .ident = "dv6",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-+ DMI_MATCH(DMI_PRODUCT_NAME,
-+ "HP Pavilion dv6 Notebook PC"),
-+ },
-+ .driver_data = "F.21", /* cutoff BIOS version */
-+ },
-+ {
-+ .ident = "HDX18",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-+ DMI_MATCH(DMI_PRODUCT_NAME,
-+ "HP HDX18 Notebook PC"),
-+ },
-+ .driver_data = "F.23", /* cutoff BIOS version */
-+ },
-+ { } /* terminate list */
-+ };
-+ const struct dmi_system_id *dmi = dmi_first_match(sysids);
-+ const char *ver;
-+
-+ if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
-+ return false;
-+
-+ ver = dmi_get_system_info(DMI_BIOS_VERSION);
-+
-+ return !ver || strcmp(ver, dmi->driver_data) < 0;
-+}
-+
-+static bool ahci_broken_online(struct pci_dev *pdev)
-+{
-+#define ENCODE_BUSDEVFN(bus, slot, func) \
-+ (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
-+ static const struct dmi_system_id sysids[] = {
-+ /*
-+ * There are several gigabyte boards which use
-+ * SIMG5723s configured as hardware RAID. Certain
-+ * 5723 firmware revisions shipped there keep the link
-+ * online but fail to answer properly to SRST or
-+ * IDENTIFY when no device is attached downstream
-+ * causing libata to retry quite a few times leading
-+ * to excessive detection delay.
-+ *
-+ * As these firmwares respond to the second reset try
-+ * with invalid device signature, considering unknown
-+ * sig as offline works around the problem acceptably.
-+ */
-+ {
-+ .ident = "EP45-DQ6",
-+ .matches = {
-+ DMI_MATCH(DMI_BOARD_VENDOR,
-+ "Gigabyte Technology Co., Ltd."),
-+ DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
-+ },
-+ .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
-+ },
-+ {
-+ .ident = "EP45-DS5",
-+ .matches = {
-+ DMI_MATCH(DMI_BOARD_VENDOR,
-+ "Gigabyte Technology Co., Ltd."),
-+ DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
-+ },
-+ .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
-+ },
-+ { } /* terminate list */
-+ };
-+#undef ENCODE_BUSDEVFN
-+ const struct dmi_system_id *dmi = dmi_first_match(sysids);
-+ unsigned int val;
-+
-+ if (!dmi)
-+ return false;
-+
-+ val = (unsigned long)dmi->driver_data;
-+
-+ return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
-+}
-+
-+#endif
-+static int ahci_remove(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct ata_host *host = dev_get_drvdata(dev);
-+
-+ ata_host_detach(host);
-+ return 0;
-+}
-+
-+#if 0
-+static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-+#else
-+static int __init ahci_probe(struct platform_device *pdev)
-+#endif
-+{
-+ static int printed_version;
-+#if 0
-+ unsigned int board_id = ent->driver_data;
-+ struct ata_port_info pi = ahci_port_info[board_id];
-+#else
-+ struct ata_port_info pi = ahci_port_info[board_ahci];
-+#endif
-+ const struct ata_port_info *ppi[] = { &pi, NULL };
-+ struct device *dev = &pdev->dev;
-+ struct ahci_host_priv *hpriv;
-+ struct ata_host *host;
-+ int n_ports, i, rc;
-+ struct resource *res;
-+ u8 *base = NULL;
-+
-+ VPRINTK("ENTER\n");
-+
-+ WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
-+
-+ if (!printed_version++)
-+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
-+
-+#if 0
-+ /* The AHCI driver can only drive the SATA ports, the PATA driver
-+ can drive them all so if both drivers are selected make sure
-+ AHCI stays out of the way */
-+ if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
-+ return -ENODEV;
-+
-+ /* acquire resources */
-+ rc = pcim_enable_device(pdev);
-+ if (rc)
-+ return rc;
-+
-+ /* AHCI controllers often implement SFF compatible interface.
-+ * Grab all PCI BARs just in case.
-+ */
-+ rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
-+ if (rc == -EBUSY)
-+ pcim_pin_device(pdev);
-+ if (rc)
-+ return rc;
-+
-+ if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
-+ (pdev->device == 0x2652 || pdev->device == 0x2653)) {
-+ u8 map;
-+
-+ /* ICH6s share the same PCI ID for both piix and ahci
-+ * modes. Enabling ahci mode while MAP indicates
-+ * combined mode is a bad idea. Yield to ata_piix.
-+ */
-+ pci_read_config_byte(pdev, ICH_MAP, &map);
-+ if (map & 0x3) {
-+ dev_printk(KERN_INFO, &pdev->dev, "controller is in "
-+ "combined mode, can't enable AHCI mode\n");
-+ return -ENODEV;
-+ }
-+ }
-+#endif
-+
-+ hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
-+ if (!hpriv)
-+ return -ENOMEM;
-+ hpriv->flags |= (unsigned long)pi.private_data;
-+
-+#if 0
-+ /* MCP65 revision A1 and A2 can't do MSI */
-+ if (board_id == board_ahci_mcp65 &&
-+ (pdev->revision == 0xa1 || pdev->revision == 0xa2))
-+ hpriv->flags |= AHCI_HFLAG_NO_MSI;
-+
-+ /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
-+ if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
-+ hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
-+
-+ /* apply ASUS M2A_VM quirk */
-+ if (ahci_asus_m2a_vm_32bit_only(pdev))
-+ hpriv->flags |= AHCI_HFLAG_32BIT_ONLY;
-+
-+ if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
-+ pci_enable_msi(pdev);
-+#endif
-+
-+ /* Cavium CNS3XXX Initial */
-+ /* Get SATA register base address */
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ dev_err(&pdev->dev, "no reg addr\n");
-+ return -ENODEV;
-+ }
-+
-+ /* ioremap SATA registers */
-+ base = devm_ioremap(&pdev->dev, res->start, res->end - res->start + 1);
-+
-+ if (!base) {
-+ dev_err(&pdev->dev, "ioremap failed for 0x%x\n", res->start);
-+ return -ENODEV;
-+ }
-+
-+#if 0
-+ /* reset PHY test chip */
-+ printk("*** Reset PHY ***\n");
-+ CNS3XXX_MISC_REGISTER |= 0xF;
-+ mdelay(100);
-+
-+ printk("%s %d, base:0x%x\n",__FUNCTION__,__LINE__,(u32)base);
-+
-+ /* set PI first */
-+ printk("*** Manually set PI ***\n");
-+ writel(0x1, (void __iomem *)base + HOST_PORTS_IMPL);
-+ printk("*** Now PI is: 0x%x ***\n",readl((void __iomem *)base + HOST_PORTS_IMPL));
-+#endif
-+
-+
-+
-+
-+ /* save initial config */
-+#if 0
-+ ahci_save_initial_config(pdev, hpriv);
-+#else
-+ ahci_save_initial_config(pdev, hpriv, base);
-+#endif
-+
-+ /* prepare host */
-+ if (hpriv->cap & HOST_CAP_NCQ)
-+ pi.flags |= ATA_FLAG_NCQ;
-+
-+ if (hpriv->cap & HOST_CAP_PMP)
-+ pi.flags |= ATA_FLAG_PMP;
-+
-+ if (ahci_em_messages && (hpriv->cap & HOST_CAP_EMS)) {
-+ u8 messages;
-+#if 0
-+ void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
-+#else
-+ void __iomem *mmio = (void __iomem *)base;
-+#endif
-+ u32 em_loc = readl(mmio + HOST_EM_LOC);
-+ u32 em_ctl = readl(mmio + HOST_EM_CTL);
-+
-+ messages = (em_ctl & EM_CTRL_MSG_TYPE) >> 16;
-+
-+ /* we only support LED message type right now */
-+ if ((messages & 0x01) && (ahci_em_messages == 1)) {
-+ /* store em_loc */
-+ hpriv->em_loc = ((em_loc >> 16) * 4);
-+ pi.flags |= ATA_FLAG_EM;
-+ if (!(em_ctl & EM_CTL_ALHD))
-+ pi.flags |= ATA_FLAG_SW_ACTIVITY;
-+ }
-+ }
-+
-+#if 0
-+ if (ahci_broken_system_poweroff(pdev)) {
-+ pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
-+ dev_info(&pdev->dev,
-+ "quirky BIOS, skipping spindown on poweroff\n");
-+ }
-+
-+ if (ahci_broken_suspend(pdev)) {
-+ hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
-+ dev_printk(KERN_WARNING, &pdev->dev,
-+ "BIOS update required for suspend/resume\n");
-+ }
-+
-+ if (ahci_broken_online(pdev)) {
-+ hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
-+ dev_info(&pdev->dev,
-+ "online status unreliable, applying workaround\n");
-+ }
-+#endif
-+
-+ /* CAP.NP sometimes indicate the index of the last enabled
-+ * port, at other times, that of the last possible port, so
-+ * determining the maximum port number requires looking at
-+ * both CAP.NP and port_map.
-+ */
-+ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
-+
-+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
-+ if (!host)
-+ return -ENOMEM;
-+#if 0
-+ host->iomap = pcim_iomap_table(pdev);
-+#else
-+ host->iomap = (void __iomem *)base;
-+#endif
-+ host->private_data = hpriv;
-+
-+ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
-+ host->flags |= ATA_HOST_PARALLEL_SCAN;
-+ else
-+ printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
-+
-+ if (pi.flags & ATA_FLAG_EM)
-+ ahci_reset_em(host);
-+
-+ for (i = 0; i < host->n_ports; i++) {
-+ struct ata_port *ap = host->ports[i];
-+
-+#if 0
-+ ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
-+ ata_port_pbar_desc(ap, AHCI_PCI_BAR,
-+ 0x100 + ap->port_no * 0x80, "port");
-+#else
-+ ata_port_desc(ap, "%s %s%llu@0x%llx", "ahci bar", "m",
-+ (long long)(res->end - res->start) + 1, (long long)res->start);
-+ ata_port_desc(ap, "%s 0x%llx", "port",
-+ (long long)res->start + 0x100 + ap->port_no * 0x80);
-+#endif
-+
-+ /* set initial link pm policy */
-+ ap->pm_policy = NOT_AVAILABLE;
-+
-+ /* set enclosure management message type */
-+ if (ap->flags & ATA_FLAG_EM)
-+ ap->em_message_type = ahci_em_messages;
-+
-+
-+ /* disabled/not-implemented port */
-+ if (!(hpriv->port_map & (1 << i)))
-+ ap->ops = &ata_dummy_port_ops;
-+ }
-+
-+#if 0
-+ /* apply workaround for ASUS P5W DH Deluxe mainboard */
-+ ahci_p5wdh_workaround(host);
-+
-+ /* initialize adapter */
-+ rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
-+ if (rc)
-+ return rc;
-+#endif
-+
-+ rc = ahci_reset_controller(host);
-+ if (rc)
-+ return rc;
-+
-+ ahci_init_controller(host);
-+ ahci_print_info(host);
-+
-+#if 0
-+ pci_set_master(pdev);
-+#endif
-+
-+
-+
-+#if 0
-+ return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
-+ &ahci_sht);
-+#else
-+ /* Get SATA port interrupt number */
-+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+ if (!res) {
-+ dev_err(&pdev->dev, "no SATA irq\n");
-+ return -ENODEV;
-+ }
-+
-+ return ata_host_activate(host, res->start, ahci_interrupt, IRQF_SHARED,
-+ &ahci_sht);
-+
-+
-+#endif
-+}
-+
-+
-+#if defined(CONFIG_CNS3XXX_SILICON) || defined(CONFIG_SILICON)
-+static void ahci_phy_init(void){
-+
-+ u32 u32tmp;
-+
-+
-+ u32tmp = MISC_SATA_POWER_MODE;
-+ u32tmp |= 0x1<< 16; // Disable SATA PHY 0 from SLUMBER Mode
-+ u32tmp |= 0x1<< 17; // Disable SATA PHY 1 from SLUMBER Mode
-+ MISC_SATA_POWER_MODE = u32tmp;
-+
-+ /* Enable SATA PHY */
-+ cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY0);
-+ cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY1);
-+
-+ /* Enable SATA Clock */
-+ cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_SATA);
-+
-+ /* De-Asscer SATA Reset */
-+ u32tmp = PM_SOFT_RST_REG;
-+ u32tmp |= 0x1 << PM_SOFT_RST_REG_OFFST_SATA;
-+ PM_SOFT_RST_REG = u32tmp;
-+}
-+#endif
-+
-+
-+
-+static int __init ahci_init(void)
-+{
-+#if 0
-+ return pci_register_driver(&ahci_pci_driver);
-+#else
-+ printk("CNS3XXX AHCI SATA low-level driver\n");
-+#if defined(CONFIG_CNS3XXX_SILICON) || defined(CONFIG_SILICON)
-+ ahci_phy_init();
-+#endif
-+ return platform_driver_register(&ahci_driver);
-+#endif
-+}
-+
-+static void __exit ahci_exit(void)
-+{
-+#if 0
-+ pci_unregister_driver(&ahci_pci_driver);
-+#else
-+ platform_driver_unregister(&ahci_driver);
-+#endif
-+}
-+
-+
-+MODULE_AUTHOR("Jeff Garzik");
-+MODULE_DESCRIPTION("AHCI SATA low-level driver");
-+MODULE_LICENSE("GPL");
-+#if 0
-+MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
-+#endif
-+MODULE_VERSION(DRV_VERSION);
-+
-+module_init(ahci_init);
-+module_exit(ahci_exit);
---- a/drivers/ata/Kconfig
-+++ b/drivers/ata/Kconfig
-@@ -47,6 +47,14 @@ config SATA_PMP
- This option adds support for SATA Port Multipliers
- (the SATA version of an ethernet hub, or SAS expander).
-
-+config SATA_CNS3XXX_AHCI
-+ tristate "Cavium CNS3XXX AHCI SATA support"
-+ help
-+ This option enables support for AHCI Serial ATA support for Cavium CNS3XXX.
-+
-+ If unsure, say N.
-+
-+
- config SATA_AHCI
- tristate "AHCI SATA support"
- depends on PCI
---- a/drivers/ata/libata-scsi.c
-+++ b/drivers/ata/libata-scsi.c
-@@ -3096,12 +3096,22 @@ int ata_scsi_queuecmd(struct scsi_cmnd *
- struct scsi_device *scsidev = cmd->device;
- struct Scsi_Host *shost = scsidev->host;
- int rc = 0;
--
-+#ifdef CONFIG_SMP
-+ u32 flags;
-+ local_save_flags(flags);
-+#endif
- ap = ata_shost_to_port(shost);
-
- spin_unlock(shost->host_lock);
-+#ifndef CONFIG_SMP
- spin_lock(ap->lock);
--
-+#else
-+ while(!spin_trylock(ap->lock)){
-+ if(!irqs_disabled()) continue;
-+ local_irq_enable();
-+ local_irq_restore(flags);
-+ }
-+#endif
- ata_scsi_dump_cdb(ap, cmd);
-
- dev = ata_scsi_find_dev(ap, scsidev);
---- a/drivers/ata/libata-sff.c
-+++ b/drivers/ata/libata-sff.c
-@@ -893,6 +893,9 @@ static void ata_pio_sector(struct ata_qu
- do_write);
- }
-
-+ if (!do_write)
-+ flush_dcache_page(page);
-+
- qc->curbytes += qc->sect_size;
- qc->cursg_ofs += qc->sect_size;
-
---- a/drivers/ata/Makefile
-+++ b/drivers/ata/Makefile
-@@ -1,6 +1,7 @@
-
- obj-$(CONFIG_ATA) += libata.o
-
-+obj-$(CONFIG_SATA_CNS3XXX_AHCI) += cns3xxx_ahci.o
- obj-$(CONFIG_SATA_AHCI) += ahci.o
- obj-$(CONFIG_SATA_SVW) += sata_svw.o
- obj-$(CONFIG_ATA_PIIX) += ata_piix.o