diff options
| -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 | ||
