Loading drivers/ata/sata_sx4.c +121 −45 Original line number Diff line number Diff line Loading @@ -213,8 +213,9 @@ struct pdc_host_priv { static int pdc_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static void pdc_eng_timeout(struct ata_port *ap); static void pdc_20621_phy_reset(struct ata_port *ap); static void pdc_error_handler(struct ata_port *ap); static void pdc_freeze(struct ata_port *ap); static void pdc_thaw(struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); static void pdc20621_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); Loading @@ -233,6 +234,10 @@ static void pdc20621_put_to_dimm(struct ata_host *host, void *psource, u32 offset, u32 size); static void pdc20621_irq_clear(struct ata_port *ap); static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc); static int pdc_softreset(struct ata_link *link, unsigned int *class, unsigned long deadline); static void pdc_post_internal_cmd(struct ata_queued_cmd *qc); static int pdc_check_atapi_dma(struct ata_queued_cmd *qc); static struct scsi_host_template pdc_sata_sht = { Loading @@ -243,20 +248,24 @@ static struct scsi_host_template pdc_sata_sht = { /* TODO: inherit from base port_ops after converting to new EH */ static struct ata_port_operations pdc_20621_ops = { .sff_tf_load = pdc_tf_load_mmio, .sff_tf_read = ata_sff_tf_read, .sff_check_status = ata_sff_check_status, .sff_exec_command = pdc_exec_command_mmio, .sff_dev_select = ata_sff_dev_select, .phy_reset = pdc_20621_phy_reset, .inherits = &ata_sff_port_ops, .check_atapi_dma = pdc_check_atapi_dma, .qc_prep = pdc20621_qc_prep, .qc_issue = pdc20621_qc_issue, .qc_fill_rtf = ata_sff_qc_fill_rtf, .sff_data_xfer = ata_sff_data_xfer, .eng_timeout = pdc_eng_timeout, .sff_irq_clear = pdc20621_irq_clear, .sff_irq_on = ata_sff_irq_on, .freeze = pdc_freeze, .thaw = pdc_thaw, .softreset = pdc_softreset, .error_handler = pdc_error_handler, .lost_interrupt = ATA_OP_NULL, .post_internal_cmd = pdc_post_internal_cmd, .port_start = pdc_port_start, .sff_tf_load = pdc_tf_load_mmio, .sff_exec_command = pdc_exec_command_mmio, .sff_irq_clear = pdc20621_irq_clear, }; static const struct ata_port_info pdc_port_info[] = { Loading Loading @@ -310,14 +319,6 @@ static int pdc_port_start(struct ata_port *ap) return 0; } static void pdc_20621_phy_reset(struct ata_port *ap) { VPRINTK("ENTER\n"); ap->cbl = ATA_CBL_SATA; ata_port_probe(ap); ata_bus_reset(ap); } static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, unsigned int portno, unsigned int total_len) Loading Loading @@ -859,40 +860,115 @@ static irqreturn_t pdc20621_interrupt(int irq, void *dev_instance) return IRQ_RETVAL(handled); } static void pdc_eng_timeout(struct ata_port *ap) static void pdc_freeze(struct ata_port *ap) { u8 drv_stat; struct ata_host *host = ap->host; struct ata_queued_cmd *qc; unsigned long flags; void __iomem *mmio = ap->ioaddr.cmd_addr; u32 tmp; DPRINTK("ENTER\n"); /* FIXME: if all 4 ATA engines are stopped, also stop HDMA engine */ spin_lock_irqsave(&host->lock, flags); tmp = readl(mmio + PDC_CTLSTAT); tmp |= PDC_MASK_INT; tmp &= ~PDC_DMA_ENABLE; writel(tmp, mmio + PDC_CTLSTAT); readl(mmio + PDC_CTLSTAT); /* flush */ } qc = ata_qc_from_tag(ap, ap->link.active_tag); static void pdc_thaw(struct ata_port *ap) { void __iomem *mmio = ap->ioaddr.cmd_addr; void __iomem *mmio_base; u32 tmp; switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: ata_port_printk(ap, KERN_ERR, "command timeout\n"); qc->err_mask |= __ac_err_mask(ata_wait_idle(ap)); break; /* FIXME: start HDMA engine, if zero ATA engines running */ default: drv_stat = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); /* reading SEQ mask register clears IRQ */ mmio_base = ap->host->iomap[PDC_MMIO_BAR] + PDC_CHIP0_OFS; readl(mmio_base + PDC_20621_SEQMASK); /* turn IRQ back on */ tmp = readl(mmio + PDC_CTLSTAT); tmp &= ~PDC_MASK_INT; writel(tmp, mmio + PDC_CTLSTAT); readl(mmio + PDC_CTLSTAT); /* flush */ } static void pdc_reset_port(struct ata_port *ap) { void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT; unsigned int i; u32 tmp; ata_port_printk(ap, KERN_ERR, "unknown timeout, cmd 0x%x stat 0x%x\n", qc->tf.command, drv_stat); /* FIXME: handle HDMA copy engine */ qc->err_mask |= ac_err_mask(drv_stat); for (i = 11; i > 0; i--) { tmp = readl(mmio); if (tmp & PDC_RESET) break; udelay(100); tmp |= PDC_RESET; writel(tmp, mmio); } tmp &= ~PDC_RESET; writel(tmp, mmio); readl(mmio); /* flush */ } spin_unlock_irqrestore(&host->lock, flags); ata_eh_qc_complete(qc); DPRINTK("EXIT\n"); static int pdc_softreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { pdc_reset_port(link->ap); return ata_sff_softreset(link, class, deadline); } static void pdc_error_handler(struct ata_port *ap) { 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) { struct ata_port *ap = qc->ap; /* make DMA engine forget about the failed command */ if (qc->flags & ATA_QCFLAG_FAILED) pdc_reset_port(ap); } static int pdc_check_atapi_dma(struct ata_queued_cmd *qc) { u8 *scsicmd = qc->scsicmd->cmnd; int pio = 1; /* atapi dma off by default */ /* Whitelist commands that may use DMA. */ switch (scsicmd[0]) { case WRITE_12: case WRITE_10: case WRITE_6: case READ_12: case READ_10: case READ_6: case 0xad: /* READ_DVD_STRUCTURE */ case 0xbe: /* READ_CD */ pio = 0; } /* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */ if (scsicmd[0] == WRITE_10) { unsigned int lba = (scsicmd[2] << 24) | (scsicmd[3] << 16) | (scsicmd[4] << 8) | scsicmd[5]; if (lba >= 0xFFFF4FA2) pio = 1; } return pio; } static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) Loading Loading
drivers/ata/sata_sx4.c +121 −45 Original line number Diff line number Diff line Loading @@ -213,8 +213,9 @@ struct pdc_host_priv { static int pdc_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static void pdc_eng_timeout(struct ata_port *ap); static void pdc_20621_phy_reset(struct ata_port *ap); static void pdc_error_handler(struct ata_port *ap); static void pdc_freeze(struct ata_port *ap); static void pdc_thaw(struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); static void pdc20621_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); Loading @@ -233,6 +234,10 @@ static void pdc20621_put_to_dimm(struct ata_host *host, void *psource, u32 offset, u32 size); static void pdc20621_irq_clear(struct ata_port *ap); static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc); static int pdc_softreset(struct ata_link *link, unsigned int *class, unsigned long deadline); static void pdc_post_internal_cmd(struct ata_queued_cmd *qc); static int pdc_check_atapi_dma(struct ata_queued_cmd *qc); static struct scsi_host_template pdc_sata_sht = { Loading @@ -243,20 +248,24 @@ static struct scsi_host_template pdc_sata_sht = { /* TODO: inherit from base port_ops after converting to new EH */ static struct ata_port_operations pdc_20621_ops = { .sff_tf_load = pdc_tf_load_mmio, .sff_tf_read = ata_sff_tf_read, .sff_check_status = ata_sff_check_status, .sff_exec_command = pdc_exec_command_mmio, .sff_dev_select = ata_sff_dev_select, .phy_reset = pdc_20621_phy_reset, .inherits = &ata_sff_port_ops, .check_atapi_dma = pdc_check_atapi_dma, .qc_prep = pdc20621_qc_prep, .qc_issue = pdc20621_qc_issue, .qc_fill_rtf = ata_sff_qc_fill_rtf, .sff_data_xfer = ata_sff_data_xfer, .eng_timeout = pdc_eng_timeout, .sff_irq_clear = pdc20621_irq_clear, .sff_irq_on = ata_sff_irq_on, .freeze = pdc_freeze, .thaw = pdc_thaw, .softreset = pdc_softreset, .error_handler = pdc_error_handler, .lost_interrupt = ATA_OP_NULL, .post_internal_cmd = pdc_post_internal_cmd, .port_start = pdc_port_start, .sff_tf_load = pdc_tf_load_mmio, .sff_exec_command = pdc_exec_command_mmio, .sff_irq_clear = pdc20621_irq_clear, }; static const struct ata_port_info pdc_port_info[] = { Loading Loading @@ -310,14 +319,6 @@ static int pdc_port_start(struct ata_port *ap) return 0; } static void pdc_20621_phy_reset(struct ata_port *ap) { VPRINTK("ENTER\n"); ap->cbl = ATA_CBL_SATA; ata_port_probe(ap); ata_bus_reset(ap); } static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, unsigned int portno, unsigned int total_len) Loading Loading @@ -859,40 +860,115 @@ static irqreturn_t pdc20621_interrupt(int irq, void *dev_instance) return IRQ_RETVAL(handled); } static void pdc_eng_timeout(struct ata_port *ap) static void pdc_freeze(struct ata_port *ap) { u8 drv_stat; struct ata_host *host = ap->host; struct ata_queued_cmd *qc; unsigned long flags; void __iomem *mmio = ap->ioaddr.cmd_addr; u32 tmp; DPRINTK("ENTER\n"); /* FIXME: if all 4 ATA engines are stopped, also stop HDMA engine */ spin_lock_irqsave(&host->lock, flags); tmp = readl(mmio + PDC_CTLSTAT); tmp |= PDC_MASK_INT; tmp &= ~PDC_DMA_ENABLE; writel(tmp, mmio + PDC_CTLSTAT); readl(mmio + PDC_CTLSTAT); /* flush */ } qc = ata_qc_from_tag(ap, ap->link.active_tag); static void pdc_thaw(struct ata_port *ap) { void __iomem *mmio = ap->ioaddr.cmd_addr; void __iomem *mmio_base; u32 tmp; switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: ata_port_printk(ap, KERN_ERR, "command timeout\n"); qc->err_mask |= __ac_err_mask(ata_wait_idle(ap)); break; /* FIXME: start HDMA engine, if zero ATA engines running */ default: drv_stat = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); /* reading SEQ mask register clears IRQ */ mmio_base = ap->host->iomap[PDC_MMIO_BAR] + PDC_CHIP0_OFS; readl(mmio_base + PDC_20621_SEQMASK); /* turn IRQ back on */ tmp = readl(mmio + PDC_CTLSTAT); tmp &= ~PDC_MASK_INT; writel(tmp, mmio + PDC_CTLSTAT); readl(mmio + PDC_CTLSTAT); /* flush */ } static void pdc_reset_port(struct ata_port *ap) { void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT; unsigned int i; u32 tmp; ata_port_printk(ap, KERN_ERR, "unknown timeout, cmd 0x%x stat 0x%x\n", qc->tf.command, drv_stat); /* FIXME: handle HDMA copy engine */ qc->err_mask |= ac_err_mask(drv_stat); for (i = 11; i > 0; i--) { tmp = readl(mmio); if (tmp & PDC_RESET) break; udelay(100); tmp |= PDC_RESET; writel(tmp, mmio); } tmp &= ~PDC_RESET; writel(tmp, mmio); readl(mmio); /* flush */ } spin_unlock_irqrestore(&host->lock, flags); ata_eh_qc_complete(qc); DPRINTK("EXIT\n"); static int pdc_softreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { pdc_reset_port(link->ap); return ata_sff_softreset(link, class, deadline); } static void pdc_error_handler(struct ata_port *ap) { 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) { struct ata_port *ap = qc->ap; /* make DMA engine forget about the failed command */ if (qc->flags & ATA_QCFLAG_FAILED) pdc_reset_port(ap); } static int pdc_check_atapi_dma(struct ata_queued_cmd *qc) { u8 *scsicmd = qc->scsicmd->cmnd; int pio = 1; /* atapi dma off by default */ /* Whitelist commands that may use DMA. */ switch (scsicmd[0]) { case WRITE_12: case WRITE_10: case WRITE_6: case READ_12: case READ_10: case READ_6: case 0xad: /* READ_DVD_STRUCTURE */ case 0xbe: /* READ_CD */ pio = 0; } /* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */ if (scsicmd[0] == WRITE_10) { unsigned int lba = (scsicmd[2] << 24) | (scsicmd[3] << 16) | (scsicmd[4] << 8) | scsicmd[5]; if (lba >= 0xFFFF4FA2) pio = 1; } return pio; } static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) Loading