]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ata/sata_promise.c
libata: separate PMP support code from core code
[linux-2.6-omap-h63xx.git] / drivers / ata / sata_promise.c
index a07d319f6e8cc1d6e2b42d12c5d7d3c6105e7d4a..5a10dc5048ad3f8e88f748775f220b209e584056 100644 (file)
@@ -46,7 +46,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME       "sata_promise"
-#define DRV_VERSION    "2.11"
+#define DRV_VERSION    "2.12"
 
 enum {
        PDC_MAX_PORTS           = 4,
@@ -143,101 +143,57 @@ static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile
 static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);
 static int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc);
 static void pdc_irq_clear(struct ata_port *ap);
-static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
+static unsigned int pdc_qc_issue(struct ata_queued_cmd *qc);
 static void pdc_freeze(struct ata_port *ap);
+static void pdc_sata_freeze(struct ata_port *ap);
 static void pdc_thaw(struct ata_port *ap);
-static void pdc_pata_error_handler(struct ata_port *ap);
-static void pdc_sata_error_handler(struct ata_port *ap);
+static void pdc_sata_thaw(struct ata_port *ap);
+static void pdc_error_handler(struct ata_port *ap);
 static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
 static int pdc_pata_cable_detect(struct ata_port *ap);
 static int pdc_sata_cable_detect(struct ata_port *ap);
 
 static struct scsi_host_template pdc_ata_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
+       ATA_BASE_SHT(DRV_NAME),
        .sg_tablesize           = PDC_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
        .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
 };
 
-static const struct ata_port_operations pdc_sata_ops = {
-       .tf_load                = pdc_tf_load_mmio,
-       .tf_read                = ata_tf_read,
-       .check_status           = ata_check_status,
-       .exec_command           = pdc_exec_command_mmio,
-       .dev_select             = ata_std_dev_select,
-       .check_atapi_dma        = pdc_check_atapi_dma,
+static const struct ata_port_operations pdc_common_ops = {
+       .inherits               = &ata_sff_port_ops,
 
+       .sff_tf_load            = pdc_tf_load_mmio,
+       .sff_exec_command       = pdc_exec_command_mmio,
+       .check_atapi_dma        = pdc_check_atapi_dma,
        .qc_prep                = pdc_qc_prep,
-       .qc_issue               = pdc_qc_issue_prot,
-       .freeze                 = pdc_freeze,
-       .thaw                   = pdc_thaw,
-       .error_handler          = pdc_sata_error_handler,
+       .qc_issue               = pdc_qc_issue,
+       .sff_irq_clear          = pdc_irq_clear,
+
        .post_internal_cmd      = pdc_post_internal_cmd,
-       .cable_detect           = pdc_sata_cable_detect,
-       .data_xfer              = ata_data_xfer,
-       .irq_clear              = pdc_irq_clear,
-       .irq_on                 = ata_irq_on,
+       .error_handler          = pdc_error_handler,
+};
 
+static struct ata_port_operations pdc_sata_ops = {
+       .inherits               = &pdc_common_ops,
+       .cable_detect           = pdc_sata_cable_detect,
+       .freeze                 = pdc_sata_freeze,
+       .thaw                   = pdc_sata_thaw,
        .scr_read               = pdc_sata_scr_read,
        .scr_write              = pdc_sata_scr_write,
        .port_start             = pdc_sata_port_start,
 };
 
 /* First-generation chips need a more restrictive ->check_atapi_dma op */
-static const struct ata_port_operations pdc_old_sata_ops = {
-       .tf_load                = pdc_tf_load_mmio,
-       .tf_read                = ata_tf_read,
-       .check_status           = ata_check_status,
-       .exec_command           = pdc_exec_command_mmio,
-       .dev_select             = ata_std_dev_select,
+static struct ata_port_operations pdc_old_sata_ops = {
+       .inherits               = &pdc_sata_ops,
        .check_atapi_dma        = pdc_old_sata_check_atapi_dma,
-
-       .qc_prep                = pdc_qc_prep,
-       .qc_issue               = pdc_qc_issue_prot,
-       .freeze                 = pdc_freeze,
-       .thaw                   = pdc_thaw,
-       .error_handler          = pdc_sata_error_handler,
-       .post_internal_cmd      = pdc_post_internal_cmd,
-       .cable_detect           = pdc_sata_cable_detect,
-       .data_xfer              = ata_data_xfer,
-       .irq_clear              = pdc_irq_clear,
-       .irq_on                 = ata_irq_on,
-
-       .scr_read               = pdc_sata_scr_read,
-       .scr_write              = pdc_sata_scr_write,
-       .port_start             = pdc_sata_port_start,
 };
 
-static const struct ata_port_operations pdc_pata_ops = {
-       .tf_load                = pdc_tf_load_mmio,
-       .tf_read                = ata_tf_read,
-       .check_status           = ata_check_status,
-       .exec_command           = pdc_exec_command_mmio,
-       .dev_select             = ata_std_dev_select,
-       .check_atapi_dma        = pdc_check_atapi_dma,
-
-       .qc_prep                = pdc_qc_prep,
-       .qc_issue               = pdc_qc_issue_prot,
+static struct ata_port_operations pdc_pata_ops = {
+       .inherits               = &pdc_common_ops,
+       .cable_detect           = pdc_pata_cable_detect,
        .freeze                 = pdc_freeze,
        .thaw                   = pdc_thaw,
-       .error_handler          = pdc_pata_error_handler,
-       .post_internal_cmd      = pdc_post_internal_cmd,
-       .cable_detect           = pdc_pata_cable_detect,
-       .data_xfer              = ata_data_xfer,
-       .irq_clear              = pdc_irq_clear,
-       .irq_on                 = ata_irq_on,
-
        .port_start             = pdc_common_port_start,
 };
 
@@ -449,7 +405,7 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
        u8 *cdb = qc->cdb;
        struct pdc_port_priv *pp = ap->private_data;
        u8 *buf = pp->pkt;
-       u32 *buf32 = (u32 *) buf;
+       __le32 *buf32 = (__le32 *) buf;
        unsigned int dev_sel, feature;
 
        /* set control bits (byte 0), zero delay seq id (byte 3),
@@ -543,7 +499,7 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc)
        idx = 0;
        for_each_sg(qc->sg, sg, qc->n_elem, si) {
                u32 addr, offset;
-               u32 sg_len, len;
+               u32 sg_len;
 
                /* determine if physical DMA addr spans 64K boundary.
                 * Note h/w doesn't support 64-bit, so we unconditionally
@@ -631,6 +587,41 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
        }
 }
 
+static int pdc_is_sataii_tx4(unsigned long flags)
+{
+       const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
+       return (flags & mask) == mask;
+}
+
+static unsigned int pdc_port_no_to_ata_no(unsigned int port_no,
+                                         int is_sataii_tx4)
+{
+       static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
+       return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
+}
+
+static unsigned int pdc_sata_nr_ports(const struct ata_port *ap)
+{
+       return (ap->flags & PDC_FLAG_4_PORTS) ? 4 : 2;
+}
+
+static unsigned int pdc_sata_ata_port_to_ata_no(const struct ata_port *ap)
+{
+       const struct ata_host *host = ap->host;
+       unsigned int nr_ports = pdc_sata_nr_ports(ap);
+       unsigned int i;
+
+       for(i = 0; i < nr_ports && host->ports[i] != ap; ++i)
+               ;
+       BUG_ON(i >= nr_ports);
+       return pdc_port_no_to_ata_no(i, pdc_is_sataii_tx4(ap->flags));
+}
+
+static unsigned int pdc_sata_hotplug_offset(const struct ata_port *ap)
+{
+       return (ap->flags & PDC_FLAG_GEN_II) ? PDC2_SATA_PLUG_CSR : PDC_SATA_PLUG_CSR;
+}
+
 static void pdc_freeze(struct ata_port *ap)
 {
        void __iomem *mmio = ap->ioaddr.cmd_addr;
@@ -643,6 +634,29 @@ static void pdc_freeze(struct ata_port *ap)
        readl(mmio + PDC_CTLSTAT); /* flush */
 }
 
+static void pdc_sata_freeze(struct ata_port *ap)
+{
+       struct ata_host *host = ap->host;
+       void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR];
+       unsigned int hotplug_offset = pdc_sata_hotplug_offset(ap);
+       unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap);
+       u32 hotplug_status;
+
+       /* Disable hotplug events on this port.
+        *
+        * Locking:
+        * 1) hotplug register accesses must be serialised via host->lock
+        * 2) ap->lock == &ap->host->lock
+        * 3) ->freeze() and ->thaw() are called with ap->lock held
+        */
+       hotplug_status = readl(host_mmio + hotplug_offset);
+       hotplug_status |= 0x11 << (ata_no + 16);
+       writel(hotplug_status, host_mmio + hotplug_offset);
+       readl(host_mmio + hotplug_offset); /* flush */
+
+       pdc_freeze(ap);
+}
+
 static void pdc_thaw(struct ata_port *ap)
 {
        void __iomem *mmio = ap->ioaddr.cmd_addr;
@@ -658,24 +672,32 @@ static void pdc_thaw(struct ata_port *ap)
        readl(mmio + PDC_CTLSTAT); /* flush */
 }
 
-static void pdc_common_error_handler(struct ata_port *ap, ata_reset_fn_t hardreset)
+static void pdc_sata_thaw(struct ata_port *ap)
 {
-       if (!(ap->pflags & ATA_PFLAG_FROZEN))
-               pdc_reset_port(ap);
+       struct ata_host *host = ap->host;
+       void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR];
+       unsigned int hotplug_offset = pdc_sata_hotplug_offset(ap);
+       unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap);
+       u32 hotplug_status;
 
-       /* perform recovery */
-       ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
-                 ata_std_postreset);
-}
+       pdc_thaw(ap);
 
-static void pdc_pata_error_handler(struct ata_port *ap)
-{
-       pdc_common_error_handler(ap, NULL);
+       /* Enable hotplug events on this port.
+        * Locking: see pdc_sata_freeze().
+        */
+       hotplug_status = readl(host_mmio + hotplug_offset);
+       hotplug_status |= 0x11 << ata_no;
+       hotplug_status &= ~(0x11 << (ata_no + 16));
+       writel(hotplug_status, host_mmio + hotplug_offset);
+       readl(host_mmio + hotplug_offset); /* flush */
 }
 
-static void pdc_sata_error_handler(struct ata_port *ap)
+static void pdc_error_handler(struct ata_port *ap)
 {
-       pdc_common_error_handler(ap, sata_std_hardreset);
+       if (!(ap->pflags & ATA_PFLAG_FROZEN))
+               pdc_reset_port(ap);
+
+       ata_std_error_handler(ap);
 }
 
 static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
@@ -765,19 +787,6 @@ static void pdc_irq_clear(struct ata_port *ap)
        readl(mmio + PDC_INT_SEQMASK);
 }
 
-static int pdc_is_sataii_tx4(unsigned long flags)
-{
-       const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
-       return (flags & mask) == mask;
-}
-
-static unsigned int pdc_port_no_to_ata_no(unsigned int port_no,
-                                         int is_sataii_tx4)
-{
-       static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
-       return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
-}
-
 static irqreturn_t pdc_interrupt(int irq, void *dev_instance)
 {
        struct ata_host *host = dev_instance;
@@ -799,6 +808,8 @@ static irqreturn_t pdc_interrupt(int irq, void *dev_instance)
 
        mmio_base = host->iomap[PDC_MMIO_BAR];
 
+       spin_lock(&host->lock);
+
        /* read and clear hotplug flags for all ports */
        if (host->ports[0]->flags & PDC_FLAG_GEN_II)
                hotplug_offset = PDC2_SATA_PLUG_CSR;
@@ -814,11 +825,9 @@ static irqreturn_t pdc_interrupt(int irq, void *dev_instance)
 
        if (mask == 0xffffffff && hotplug_status == 0) {
                VPRINTK("QUICK EXIT 2\n");
-               return IRQ_NONE;
+               goto done_irq;
        }
 
-       spin_lock(&host->lock);
-
        mask &= 0xffff;         /* only 16 tags possible */
        if (mask == 0 && hotplug_status == 0) {
                VPRINTK("QUICK EXIT 3\n");
@@ -885,7 +894,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
        readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
 }
 
-static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
+static unsigned int pdc_qc_issue(struct ata_queued_cmd *qc)
 {
        switch (qc->tf.protocol) {
        case ATAPI_PROT_NODATA:
@@ -905,20 +914,20 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
                break;
        }
 
-       return ata_qc_issue_prot(qc);
+       return ata_sff_qc_issue(qc);
 }
 
 static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
        WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
-       ata_tf_load(ap, tf);
+       ata_sff_tf_load(ap, tf);
 }
 
 static void pdc_exec_command_mmio(struct ata_port *ap,
                                  const struct ata_taskfile *tf)
 {
        WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
-       ata_exec_command(ap, tf);
+       ata_sff_exec_command(ap, tf);
 }
 
 static int pdc_check_atapi_dma(struct ata_queued_cmd *qc)