diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/sata_sil24.c | 68 |
1 files changed, 47 insertions, 21 deletions
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 6e7728cfaf6b..4c76f05d9b65 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c | |||
@@ -216,6 +216,8 @@ enum { | |||
216 | SGE_DRD = (1 << 29), /* discard data read (/dev/null) | 216 | SGE_DRD = (1 << 29), /* discard data read (/dev/null) |
217 | data address ignored */ | 217 | data address ignored */ |
218 | 218 | ||
219 | SIL24_MAX_CMDS = 31, | ||
220 | |||
219 | /* board id */ | 221 | /* board id */ |
220 | BID_SIL3124 = 0, | 222 | BID_SIL3124 = 0, |
221 | BID_SIL3132 = 1, | 223 | BID_SIL3132 = 1, |
@@ -223,7 +225,8 @@ enum { | |||
223 | 225 | ||
224 | /* host flags */ | 226 | /* host flags */ |
225 | SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 227 | SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
226 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, | 228 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | |
229 | ATA_FLAG_NCQ, | ||
227 | SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ | 230 | SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ |
228 | 231 | ||
229 | IRQ_STAT_4PORTS = 0xf, | 232 | IRQ_STAT_4PORTS = 0xf, |
@@ -355,7 +358,8 @@ static struct scsi_host_template sil24_sht = { | |||
355 | .name = DRV_NAME, | 358 | .name = DRV_NAME, |
356 | .ioctl = ata_scsi_ioctl, | 359 | .ioctl = ata_scsi_ioctl, |
357 | .queuecommand = ata_scsi_queuecmd, | 360 | .queuecommand = ata_scsi_queuecmd, |
358 | .can_queue = ATA_DEF_QUEUE, | 361 | .change_queue_depth = ata_scsi_change_queue_depth, |
362 | .can_queue = SIL24_MAX_CMDS, | ||
359 | .this_id = ATA_SHT_THIS_ID, | 363 | .this_id = ATA_SHT_THIS_ID, |
360 | .sg_tablesize = LIBATA_MAX_PRD, | 364 | .sg_tablesize = LIBATA_MAX_PRD, |
361 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 365 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
@@ -437,6 +441,13 @@ static struct ata_port_info sil24_port_info[] = { | |||
437 | }, | 441 | }, |
438 | }; | 442 | }; |
439 | 443 | ||
444 | static int sil24_tag(int tag) | ||
445 | { | ||
446 | if (unlikely(ata_tag_internal(tag))) | ||
447 | return 0; | ||
448 | return tag; | ||
449 | } | ||
450 | |||
440 | static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) | 451 | static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) |
441 | { | 452 | { |
442 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; | 453 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; |
@@ -649,14 +660,17 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) | |||
649 | { | 660 | { |
650 | struct ata_port *ap = qc->ap; | 661 | struct ata_port *ap = qc->ap; |
651 | struct sil24_port_priv *pp = ap->private_data; | 662 | struct sil24_port_priv *pp = ap->private_data; |
652 | union sil24_cmd_block *cb = pp->cmd_block + qc->tag; | 663 | union sil24_cmd_block *cb; |
653 | struct sil24_prb *prb; | 664 | struct sil24_prb *prb; |
654 | struct sil24_sge *sge; | 665 | struct sil24_sge *sge; |
655 | u16 ctrl = 0; | 666 | u16 ctrl = 0; |
656 | 667 | ||
668 | cb = &pp->cmd_block[sil24_tag(qc->tag)]; | ||
669 | |||
657 | switch (qc->tf.protocol) { | 670 | switch (qc->tf.protocol) { |
658 | case ATA_PROT_PIO: | 671 | case ATA_PROT_PIO: |
659 | case ATA_PROT_DMA: | 672 | case ATA_PROT_DMA: |
673 | case ATA_PROT_NCQ: | ||
660 | case ATA_PROT_NODATA: | 674 | case ATA_PROT_NODATA: |
661 | prb = &cb->ata.prb; | 675 | prb = &cb->ata.prb; |
662 | sge = cb->ata.sge; | 676 | sge = cb->ata.sge; |
@@ -694,12 +708,17 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) | |||
694 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) | 708 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) |
695 | { | 709 | { |
696 | struct ata_port *ap = qc->ap; | 710 | struct ata_port *ap = qc->ap; |
697 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; | ||
698 | struct sil24_port_priv *pp = ap->private_data; | 711 | struct sil24_port_priv *pp = ap->private_data; |
699 | dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block); | 712 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; |
713 | unsigned int tag = sil24_tag(qc->tag); | ||
714 | dma_addr_t paddr; | ||
715 | void __iomem *activate; | ||
700 | 716 | ||
701 | writel((u32)paddr, port + PORT_CMD_ACTIVATE); | 717 | paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block); |
702 | writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); | 718 | activate = port + PORT_CMD_ACTIVATE + tag * 8; |
719 | |||
720 | writel((u32)paddr, activate); | ||
721 | writel((u64)paddr >> 32, activate + 4); | ||
703 | 722 | ||
704 | return 0; | 723 | return 0; |
705 | } | 724 | } |
@@ -791,9 +810,6 @@ static void sil24_error_intr(struct ata_port *ap) | |||
791 | /* record error info */ | 810 | /* record error info */ |
792 | qc = ata_qc_from_tag(ap, ap->active_tag); | 811 | qc = ata_qc_from_tag(ap, ap->active_tag); |
793 | if (qc) { | 812 | if (qc) { |
794 | int tag = qc->tag; | ||
795 | if (unlikely(ata_tag_internal(tag))) | ||
796 | tag = 0; | ||
797 | sil24_update_tf(ap); | 813 | sil24_update_tf(ap); |
798 | qc->err_mask |= err_mask; | 814 | qc->err_mask |= err_mask; |
799 | } else | 815 | } else |
@@ -809,11 +825,17 @@ static void sil24_error_intr(struct ata_port *ap) | |||
809 | ata_port_abort(ap); | 825 | ata_port_abort(ap); |
810 | } | 826 | } |
811 | 827 | ||
828 | static void sil24_finish_qc(struct ata_queued_cmd *qc) | ||
829 | { | ||
830 | if (qc->flags & ATA_QCFLAG_RESULT_TF) | ||
831 | sil24_update_tf(qc->ap); | ||
832 | } | ||
833 | |||
812 | static inline void sil24_host_intr(struct ata_port *ap) | 834 | static inline void sil24_host_intr(struct ata_port *ap) |
813 | { | 835 | { |
814 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; | 836 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; |
815 | struct ata_queued_cmd *qc; | 837 | u32 slot_stat, qc_active; |
816 | u32 slot_stat; | 838 | int rc; |
817 | 839 | ||
818 | slot_stat = readl(port + PORT_SLOT_STAT); | 840 | slot_stat = readl(port + PORT_SLOT_STAT); |
819 | 841 | ||
@@ -825,18 +847,22 @@ static inline void sil24_host_intr(struct ata_port *ap) | |||
825 | if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) | 847 | if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) |
826 | writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); | 848 | writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); |
827 | 849 | ||
828 | qc = ata_qc_from_tag(ap, ap->active_tag); | 850 | qc_active = slot_stat & ~HOST_SSTAT_ATTN; |
829 | if (qc) { | 851 | rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc); |
830 | if (qc->flags & ATA_QCFLAG_RESULT_TF) | 852 | if (rc > 0) |
831 | sil24_update_tf(ap); | 853 | return; |
832 | ata_qc_complete(qc); | 854 | if (rc < 0) { |
855 | struct ata_eh_info *ehi = &ap->eh_info; | ||
856 | ehi->err_mask |= AC_ERR_HSM; | ||
857 | ehi->action |= ATA_EH_SOFTRESET; | ||
858 | ata_port_freeze(ap); | ||
833 | return; | 859 | return; |
834 | } | 860 | } |
835 | 861 | ||
836 | if (ata_ratelimit()) | 862 | if (ata_ratelimit()) |
837 | ata_port_printk(ap, KERN_INFO, "spurious interrupt " | 863 | ata_port_printk(ap, KERN_INFO, "spurious interrupt " |
838 | "(slot_stat 0x%x active_tag %d)\n", | 864 | "(slot_stat 0x%x active_tag %d sactive 0x%x)\n", |
839 | slot_stat, ap->active_tag); | 865 | slot_stat, ap->active_tag, ap->sactive); |
840 | } | 866 | } |
841 | 867 | ||
842 | static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs) | 868 | static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs) |
@@ -903,7 +929,7 @@ static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) | |||
903 | 929 | ||
904 | static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev) | 930 | static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev) |
905 | { | 931 | { |
906 | const size_t cb_size = sizeof(*pp->cmd_block); | 932 | const size_t cb_size = sizeof(*pp->cmd_block) * SIL24_MAX_CMDS; |
907 | 933 | ||
908 | dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma); | 934 | dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma); |
909 | } | 935 | } |
@@ -913,7 +939,7 @@ static int sil24_port_start(struct ata_port *ap) | |||
913 | struct device *dev = ap->host_set->dev; | 939 | struct device *dev = ap->host_set->dev; |
914 | struct sil24_port_priv *pp; | 940 | struct sil24_port_priv *pp; |
915 | union sil24_cmd_block *cb; | 941 | union sil24_cmd_block *cb; |
916 | size_t cb_size = sizeof(*cb); | 942 | size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS; |
917 | dma_addr_t cb_dma; | 943 | dma_addr_t cb_dma; |
918 | int rc = -ENOMEM; | 944 | int rc = -ENOMEM; |
919 | 945 | ||