aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-05-15 08:03:56 -0400
committerTejun Heo <htejun@gmail.com>2006-05-15 08:03:56 -0400
commitaee10a03eb3e240bfd1a6f91e06ce82df47c5c58 (patch)
tree103a12557c6dc042bc555781ce8eece045fccae2 /drivers
parent12fad3f965830d71f6454f02b2af002a64cec4d3 (diff)
[PATCH] sata_sil24: implement NCQ support
Implement NCQ support. Sil24 has 31 command slots and all of them are used for NCQ command queueing. libata guarantees that no other command is in progress when it issues an internal command, so always use tag 0 for internal commands. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/sata_sil24.c68
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
444static int sil24_tag(int tag)
445{
446 if (unlikely(ata_tag_internal(tag)))
447 return 0;
448 return tag;
449}
450
440static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) 451static 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)
694static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) 708static 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
828static 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
812static inline void sil24_host_intr(struct ata_port *ap) 834static 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
842static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs) 868static 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
904static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev) 930static 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