]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/ahci.c
[PATCH] IB: Minor cleanup during MAD startup and shutdown
[linux-2.6-omap-h63xx.git] / drivers / scsi / ahci.c
index ee53b227c01ee6fad0a6064af7062514db2321da..c5623694d10f56a25ddc1c6f6073deaa3f250232 100644 (file)
@@ -39,7 +39,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ahci"
-#define DRV_VERSION    "1.00"
+#define DRV_VERSION    "1.01"
 
 
 enum {
@@ -50,6 +50,7 @@ enum {
        AHCI_CMD_SLOT_SZ        = 32 * 32,
        AHCI_RX_FIS_SZ          = 256,
        AHCI_CMD_TBL_HDR        = 0x80,
+       AHCI_CMD_TBL_CDB        = 0x40,
        AHCI_CMD_TBL_SZ         = AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16),
        AHCI_PORT_PRIV_DMA_SZ   = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ +
                                  AHCI_RX_FIS_SZ,
@@ -134,6 +135,9 @@ enum {
        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_FLAG_MSI           = (1 << 0),
 };
 
 struct ahci_cmd_hdr {
@@ -153,7 +157,6 @@ struct ahci_sg {
 
 struct ahci_host_priv {
        unsigned long           flags;
-       unsigned int            have_msi; /* is PCI MSI enabled? */
        u32                     cap;    /* cache of HOST_CAP register */
        u32                     port_map; /* cache of HOST_PORTS_IMPL reg */
 };
@@ -301,26 +304,19 @@ static int ahci_port_start(struct ata_port *ap)
        struct device *dev = ap->host_set->dev;
        struct ahci_host_priv *hpriv = ap->host_set->private_data;
        struct ahci_port_priv *pp;
-       int rc;
        void *mem, *mmio = ap->host_set->mmio_base;
        void *port_mmio = ahci_port_base(mmio, ap->port_no);
        dma_addr_t mem_dma;
 
-       rc = ata_port_start(ap);
-       if (rc)
-               return rc;
-
        pp = kmalloc(sizeof(*pp), GFP_KERNEL);
-       if (!pp) {
-               rc = -ENOMEM;
-               goto err_out;
-       }
+       if (!pp)
+               return -ENOMEM;
        memset(pp, 0, sizeof(*pp));
 
        mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
        if (!mem) {
-               rc = -ENOMEM;
-               goto err_out_kfree;
+               kfree(pp);
+               return -ENOMEM;
        }
        memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
 
@@ -370,12 +366,6 @@ static int ahci_port_start(struct ata_port *ap)
        readl(port_mmio + PORT_CMD); /* flush */
 
        return 0;
-
-err_out_kfree:
-       kfree(pp);
-err_out:
-       ata_port_stop(ap);
-       return rc;
 }
 
 
@@ -401,7 +391,6 @@ static void ahci_port_stop(struct ata_port *ap)
        dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
                          pp->cmd_slot, pp->cmd_slot_dma);
        kfree(pp);
-       ata_port_stop(ap);
 }
 
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
@@ -508,7 +497,8 @@ static void ahci_fill_sg(struct ata_queued_cmd *qc)
 
 static void ahci_qc_prep(struct ata_queued_cmd *qc)
 {
-       struct ahci_port_priv *pp = qc->ap->private_data;
+       struct ata_port *ap = qc->ap;
+       struct ahci_port_priv *pp = ap->private_data;
        u32 opts;
        const u32 cmd_fis_len = 5; /* five dwords */
 
@@ -520,18 +510,8 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
        opts = (qc->n_elem << 16) | cmd_fis_len;
        if (qc->tf.flags & ATA_TFLAG_WRITE)
                opts |= AHCI_CMD_WRITE;
-
-       switch (qc->tf.protocol) {
-       case ATA_PROT_ATAPI:
-       case ATA_PROT_ATAPI_NODATA:
-       case ATA_PROT_ATAPI_DMA:
+       if (is_atapi_taskfile(&qc->tf))
                opts |= AHCI_CMD_ATAPI;
-               break;
-
-       default:
-               /* do nothing */
-               break;
-       }
 
        pp->cmd_slot[0].opts = cpu_to_le32(opts);
        pp->cmd_slot[0].status = 0;
@@ -543,6 +523,10 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
         * a SATA Register - Host to Device command FIS.
         */
        ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0);
+       if (opts & AHCI_CMD_ATAPI) {
+               memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
+               memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len);
+       }
 
        if (!(qc->flags & ATA_QCFLAG_DMAMAP))
                return;
@@ -797,8 +781,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
                                return rc;
                        }
                }
-
-               hpriv->flags |= HOST_CAP_64;
        } else {
                rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
                if (rc) {
@@ -1036,7 +1018,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        probe_ent->mmio_base = mmio_base;
        probe_ent->private_data = hpriv;
 
-       hpriv->have_msi = have_msi;
+       if (have_msi)
+               hpriv->flags |= AHCI_FLAG_MSI;
 
        /* initialize adapter */
        rc = ahci_host_init(probe_ent);
@@ -1084,10 +1067,8 @@ static void ahci_remove_one (struct pci_dev *pdev)
                scsi_remove_host(ap->host);
        }
 
-       have_msi = hpriv->have_msi;
+       have_msi = hpriv->flags & AHCI_FLAG_MSI;
        free_irq(host_set->irq, host_set);
-       host_set->ops->host_stop(host_set);
-       iounmap(host_set->mmio_base);
 
        for (i = 0; i < host_set->n_ports; i++) {
                ap = host_set->ports[i];
@@ -1096,12 +1077,14 @@ static void ahci_remove_one (struct pci_dev *pdev)
                scsi_host_put(ap->host);
        }
 
+       host_set->ops->host_stop(host_set);
+       kfree(host_set);
+
        if (have_msi)
                pci_disable_msi(pdev);
        else
                pci_intx(pdev, 0);
        pci_release_regions(pdev);
-       kfree(host_set);
        pci_disable_device(pdev);
        dev_set_drvdata(dev, NULL);
 }