diff options
Diffstat (limited to 'drivers/ata/sata_qstor.c')
-rw-r--r-- | drivers/ata/sata_qstor.c | 138 |
1 files changed, 49 insertions, 89 deletions
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 710909d..bfa35ed 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -37,13 +37,14 @@ #include <linux/sched.h> #include <linux/device.h> #include <scsi/scsi_host.h> -#include <asm/io.h> #include <linux/libata.h> #define DRV_NAME "sata_qstor" #define DRV_VERSION "0.06" enum { + QS_MMIO_BAR = 4, + QS_PORTS = 4, QS_MAX_PRD = LIBATA_MAX_PRD, QS_CPB_ORDER = 6, @@ -117,7 +118,6 @@ static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *en static irqreturn_t qs_intr (int irq, void *dev_instance); static int qs_port_start(struct ata_port *ap); static void qs_host_stop(struct ata_host *host); -static void qs_port_stop(struct ata_port *ap); static void qs_phy_reset(struct ata_port *ap); static void qs_qc_prep(struct ata_queued_cmd *qc); static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); @@ -157,14 +157,15 @@ static const struct ata_port_operations qs_ata_ops = { .phy_reset = qs_phy_reset, .qc_prep = qs_qc_prep, .qc_issue = qs_qc_issue, - .data_xfer = ata_mmio_data_xfer, + .data_xfer = ata_data_xfer, .eng_timeout = qs_eng_timeout, .irq_handler = qs_intr, .irq_clear = qs_irq_clear, + .irq_on = ata_irq_on, + .irq_ack = ata_irq_ack, .scr_read = qs_scr_read, .scr_write = qs_scr_write, .port_start = qs_port_start, - .port_stop = qs_port_stop, .host_stop = qs_host_stop, .bmdma_stop = qs_bmdma_stop, .bmdma_status = qs_bmdma_status, @@ -197,6 +198,11 @@ static struct pci_driver qs_ata_pci_driver = { .remove = ata_pci_remove_one, }; +static void __iomem *qs_mmio_base(struct ata_host *host) +{ + return host->iomap[QS_MMIO_BAR]; +} + static int qs_check_atapi_dma(struct ata_queued_cmd *qc) { return 1; /* ATAPI DMA not supported */ @@ -219,7 +225,7 @@ static void qs_irq_clear(struct ata_port *ap) static inline void qs_enter_reg_mode(struct ata_port *ap) { - u8 __iomem *chan = ap->host->mmio_base + (ap->port_no * 0x4000); + u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000); writeb(QS_CTR0_REG, chan + QS_CCT_CTR0); readb(chan + QS_CCT_CTR0); /* flush */ @@ -227,7 +233,7 @@ static inline void qs_enter_reg_mode(struct ata_port *ap) static inline void qs_reset_channel_logic(struct ata_port *ap) { - u8 __iomem *chan = ap->host->mmio_base + (ap->port_no * 0x4000); + u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000); writeb(QS_CTR1_RCHN, chan + QS_CCT_CTR1); readb(chan + QS_CCT_CTR0); /* flush */ @@ -257,14 +263,14 @@ static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg) { if (sc_reg > SCR_CONTROL) return ~0U; - return readl((void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8))); + return readl(ap->ioaddr.scr_addr + (sc_reg * 8)); } static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) return; - writel(val, (void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8))); + writel(val, ap->ioaddr.scr_addr + (sc_reg * 8)); } static unsigned int qs_fill_sg(struct ata_queued_cmd *qc) @@ -325,7 +331,7 @@ static void qs_qc_prep(struct ata_queued_cmd *qc) /* host control block (HCB) */ buf[ 0] = QS_HCB_HDR; buf[ 1] = hflags; - *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE); + *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nbytes); *(__le32 *)(&buf[ 8]) = cpu_to_le32(nelem); addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES; *(__le64 *)(&buf[16]) = cpu_to_le64(addr); @@ -341,7 +347,7 @@ static void qs_qc_prep(struct ata_queued_cmd *qc) static inline void qs_packet_start(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - u8 __iomem *chan = ap->host->mmio_base + (ap->port_no * 0x4000); + u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000); VPRINTK("ENTER, ap %p\n", ap); @@ -378,7 +384,7 @@ static inline unsigned int qs_intr_pkt(struct ata_host *host) { unsigned int handled = 0; u8 sFFE; - u8 __iomem *mmio_base = host->mmio_base; + u8 __iomem *mmio_base = qs_mmio_base(host); do { u32 sff0 = readl(mmio_base + QS_HST_SFF); @@ -470,7 +476,7 @@ static irqreturn_t qs_intr(int irq, void *dev_instance) return IRQ_RETVAL(handled); } -static void qs_ata_setup_port(struct ata_ioports *port, unsigned long base) +static void qs_ata_setup_port(struct ata_ioports *port, void __iomem *base) { port->cmd_addr = port->data_addr = base + 0x400; @@ -492,7 +498,7 @@ static int qs_port_start(struct ata_port *ap) { struct device *dev = ap->host->dev; struct qs_port_priv *pp; - void __iomem *mmio_base = ap->host->mmio_base; + void __iomem *mmio_base = qs_mmio_base(ap->host); void __iomem *chan = mmio_base + (ap->port_no * 0x4000); u64 addr; int rc; @@ -501,17 +507,13 @@ static int qs_port_start(struct ata_port *ap) if (rc) return rc; qs_enter_reg_mode(ap); - pp = kzalloc(sizeof(*pp), GFP_KERNEL); - if (!pp) { - rc = -ENOMEM; - goto err_out; - } - pp->pkt = dma_alloc_coherent(dev, QS_PKT_BYTES, &pp->pkt_dma, - GFP_KERNEL); - if (!pp->pkt) { - rc = -ENOMEM; - goto err_out_kfree; - } + pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); + if (!pp) + return -ENOMEM; + pp->pkt = dmam_alloc_coherent(dev, QS_PKT_BYTES, &pp->pkt_dma, + GFP_KERNEL); + if (!pp->pkt) + return -ENOMEM; memset(pp->pkt, 0, QS_PKT_BYTES); ap->private_data = pp; @@ -519,43 +521,19 @@ static int qs_port_start(struct ata_port *ap) writel((u32) addr, chan + QS_CCF_CPBA); writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4); return 0; - -err_out_kfree: - kfree(pp); -err_out: - ata_port_stop(ap); - return rc; -} - -static void qs_port_stop(struct ata_port *ap) -{ - struct device *dev = ap->host->dev; - struct qs_port_priv *pp = ap->private_data; - - if (pp != NULL) { - ap->private_data = NULL; - if (pp->pkt != NULL) - dma_free_coherent(dev, QS_PKT_BYTES, pp->pkt, - pp->pkt_dma); - kfree(pp); - } - ata_port_stop(ap); } static void qs_host_stop(struct ata_host *host) { - void __iomem *mmio_base = host->mmio_base; - struct pci_dev *pdev = to_pci_dev(host->dev); + void __iomem *mmio_base = qs_mmio_base(host); writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */ - - pci_iounmap(pdev, mmio_base); } static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe) { - void __iomem *mmio_base = pe->mmio_base; + void __iomem *mmio_base = pe->iomap[QS_MMIO_BAR]; unsigned int port_no; writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ @@ -630,44 +608,34 @@ static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - struct ata_probe_ent *probe_ent = NULL; - void __iomem *mmio_base; + struct ata_probe_ent *probe_ent; + void __iomem * const *iomap; unsigned int board_idx = (unsigned int) ent->driver_data; int rc, port_no; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - rc = pci_enable_device(pdev); + rc = pcim_enable_device(pdev); if (rc) return rc; - rc = pci_request_regions(pdev, DRV_NAME); - if (rc) - goto err_out; - - if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) { - rc = -ENODEV; - goto err_out_regions; - } + if ((pci_resource_flags(pdev, QS_MMIO_BAR) & IORESOURCE_MEM) == 0) + return -ENODEV; - mmio_base = pci_iomap(pdev, 4, 0); - if (mmio_base == NULL) { - rc = -ENOMEM; - goto err_out_regions; - } + rc = pcim_iomap_regions(pdev, 1 << QS_MMIO_BAR, DRV_NAME); + if (rc) + return rc; + iomap = pcim_iomap_table(pdev); - rc = qs_set_dma_masks(pdev, mmio_base); + rc = qs_set_dma_masks(pdev, iomap[QS_MMIO_BAR]); if (rc) - goto err_out_iounmap; + return rc; - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); - if (probe_ent == NULL) { - rc = -ENOMEM; - goto err_out_iounmap; - } + probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL); + if (probe_ent == NULL) + return -ENOMEM; - memset(probe_ent, 0, sizeof(*probe_ent)); probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); @@ -680,12 +648,12 @@ static int qs_ata_init_one(struct pci_dev *pdev, probe_ent->irq = pdev->irq; probe_ent->irq_flags = IRQF_SHARED; - probe_ent->mmio_base = mmio_base; + probe_ent->iomap = iomap; probe_ent->n_ports = QS_PORTS; for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) { - unsigned long chan = (unsigned long)mmio_base + - (port_no * 0x4000); + void __iomem *chan = + probe_ent->iomap[QS_MMIO_BAR] + (port_no * 0x4000); qs_ata_setup_port(&probe_ent->port[port_no], chan); } @@ -694,19 +662,11 @@ static int qs_ata_init_one(struct pci_dev *pdev, /* initialize adapter */ qs_host_init(board_idx, probe_ent); - rc = ata_device_add(probe_ent); - kfree(probe_ent); - if (rc != QS_PORTS) - goto err_out_iounmap; - return 0; + if (ata_device_add(probe_ent) != QS_PORTS) + return -EIO; -err_out_iounmap: - pci_iounmap(pdev, mmio_base); -err_out_regions: - pci_release_regions(pdev); -err_out: - pci_disable_device(pdev); - return rc; + devm_kfree(&pdev->dev, probe_ent); + return 0; } static int __init qs_ata_init(void) |