diff options
Diffstat (limited to 'drivers/ata/sata_nv.c')
-rw-r--r-- | drivers/ata/sata_nv.c | 226 |
1 files changed, 103 insertions, 123 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index ab92f208dae2..30eed12b3631 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
@@ -219,6 +219,7 @@ struct nv_adma_port_priv { | |||
219 | void __iomem * gen_block; | 219 | void __iomem * gen_block; |
220 | void __iomem * notifier_clear_block; | 220 | void __iomem * notifier_clear_block; |
221 | u8 flags; | 221 | u8 flags; |
222 | int last_issue_ncq; | ||
222 | }; | 223 | }; |
223 | 224 | ||
224 | struct nv_host_priv { | 225 | struct nv_host_priv { |
@@ -254,10 +255,7 @@ static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg); | |||
254 | static int nv_adma_port_resume(struct ata_port *ap); | 255 | static int nv_adma_port_resume(struct ata_port *ap); |
255 | static void nv_adma_error_handler(struct ata_port *ap); | 256 | static void nv_adma_error_handler(struct ata_port *ap); |
256 | static void nv_adma_host_stop(struct ata_host *host); | 257 | static void nv_adma_host_stop(struct ata_host *host); |
257 | static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc); | 258 | static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc); |
258 | static void nv_adma_bmdma_start(struct ata_queued_cmd *qc); | ||
259 | static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc); | ||
260 | static u8 nv_adma_bmdma_status(struct ata_port *ap); | ||
261 | 259 | ||
262 | enum nv_host_type | 260 | enum nv_host_type |
263 | { | 261 | { |
@@ -432,16 +430,16 @@ static const struct ata_port_operations nv_adma_ops = { | |||
432 | .exec_command = ata_exec_command, | 430 | .exec_command = ata_exec_command, |
433 | .check_status = ata_check_status, | 431 | .check_status = ata_check_status, |
434 | .dev_select = ata_std_dev_select, | 432 | .dev_select = ata_std_dev_select, |
435 | .bmdma_setup = nv_adma_bmdma_setup, | 433 | .bmdma_setup = ata_bmdma_setup, |
436 | .bmdma_start = nv_adma_bmdma_start, | 434 | .bmdma_start = ata_bmdma_start, |
437 | .bmdma_stop = nv_adma_bmdma_stop, | 435 | .bmdma_stop = ata_bmdma_stop, |
438 | .bmdma_status = nv_adma_bmdma_status, | 436 | .bmdma_status = ata_bmdma_status, |
439 | .qc_prep = nv_adma_qc_prep, | 437 | .qc_prep = nv_adma_qc_prep, |
440 | .qc_issue = nv_adma_qc_issue, | 438 | .qc_issue = nv_adma_qc_issue, |
441 | .freeze = nv_ck804_freeze, | 439 | .freeze = nv_ck804_freeze, |
442 | .thaw = nv_ck804_thaw, | 440 | .thaw = nv_ck804_thaw, |
443 | .error_handler = nv_adma_error_handler, | 441 | .error_handler = nv_adma_error_handler, |
444 | .post_internal_cmd = nv_adma_bmdma_stop, | 442 | .post_internal_cmd = nv_adma_post_internal_cmd, |
445 | .data_xfer = ata_data_xfer, | 443 | .data_xfer = ata_data_xfer, |
446 | .irq_handler = nv_adma_interrupt, | 444 | .irq_handler = nv_adma_interrupt, |
447 | .irq_clear = nv_adma_irq_clear, | 445 | .irq_clear = nv_adma_irq_clear, |
@@ -661,30 +659,31 @@ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb) | |||
661 | { | 659 | { |
662 | unsigned int idx = 0; | 660 | unsigned int idx = 0; |
663 | 661 | ||
664 | cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device | WNB); | 662 | if(tf->flags & ATA_TFLAG_ISADDR) { |
665 | 663 | if (tf->flags & ATA_TFLAG_LBA48) { | |
666 | if ((tf->flags & ATA_TFLAG_LBA48) == 0) { | 664 | cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->hob_feature | WNB); |
667 | cpb[idx++] = cpu_to_le16(IGN); | 665 | cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect); |
668 | cpb[idx++] = cpu_to_le16(IGN); | 666 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->hob_lbal); |
669 | cpb[idx++] = cpu_to_le16(IGN); | 667 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->hob_lbam); |
670 | cpb[idx++] = cpu_to_le16(IGN); | 668 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->hob_lbah); |
671 | cpb[idx++] = cpu_to_le16(IGN); | 669 | cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->feature); |
672 | } | 670 | } else |
673 | else { | 671 | cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->feature | WNB); |
674 | cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->hob_feature); | 672 | |
675 | cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect); | 673 | cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->nsect); |
676 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->hob_lbal); | 674 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->lbal); |
677 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->hob_lbam); | 675 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->lbam); |
678 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->hob_lbah); | 676 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->lbah); |
679 | } | 677 | } |
680 | cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->feature); | 678 | |
681 | cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->nsect); | 679 | if(tf->flags & ATA_TFLAG_DEVICE) |
682 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->lbal); | 680 | cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device); |
683 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->lbam); | ||
684 | cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->lbah); | ||
685 | 681 | ||
686 | cpb[idx++] = cpu_to_le16((ATA_REG_CMD << 8) | tf->command | CMDEND); | 682 | cpb[idx++] = cpu_to_le16((ATA_REG_CMD << 8) | tf->command | CMDEND); |
687 | 683 | ||
684 | while(idx < 12) | ||
685 | cpb[idx++] = cpu_to_le16(IGN); | ||
686 | |||
688 | return idx; | 687 | return idx; |
689 | } | 688 | } |
690 | 689 | ||
@@ -741,6 +740,17 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) | |||
741 | DPRINTK("Completing qc from tag %d with err_mask %u\n",cpb_num, | 740 | DPRINTK("Completing qc from tag %d with err_mask %u\n",cpb_num, |
742 | qc->err_mask); | 741 | qc->err_mask); |
743 | ata_qc_complete(qc); | 742 | ata_qc_complete(qc); |
743 | } else { | ||
744 | struct ata_eh_info *ehi = &ap->eh_info; | ||
745 | /* Notifier bits set without a command may indicate the drive | ||
746 | is misbehaving. Raise host state machine violation on this | ||
747 | condition. */ | ||
748 | ata_port_printk(ap, KERN_ERR, "notifier for tag %d with no command?\n", | ||
749 | cpb_num); | ||
750 | ehi->err_mask |= AC_ERR_HSM; | ||
751 | ehi->action |= ATA_EH_SOFTRESET; | ||
752 | ata_port_freeze(ap); | ||
753 | return 1; | ||
744 | } | 754 | } |
745 | } | 755 | } |
746 | return 0; | 756 | return 0; |
@@ -852,22 +862,14 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) | |||
852 | 862 | ||
853 | if (status & (NV_ADMA_STAT_DONE | | 863 | if (status & (NV_ADMA_STAT_DONE | |
854 | NV_ADMA_STAT_CPBERR)) { | 864 | NV_ADMA_STAT_CPBERR)) { |
865 | u32 check_commands = notifier | notifier_error; | ||
866 | int pos, error = 0; | ||
855 | /** Check CPBs for completed commands */ | 867 | /** Check CPBs for completed commands */ |
856 | 868 | while ((pos = ffs(check_commands)) && !error) { | |
857 | if (ata_tag_valid(ap->active_tag)) { | 869 | pos--; |
858 | /* Non-NCQ command */ | 870 | error = nv_adma_check_cpb(ap, pos, |
859 | nv_adma_check_cpb(ap, ap->active_tag, | 871 | notifier_error & (1 << pos) ); |
860 | notifier_error & (1 << ap->active_tag)); | 872 | check_commands &= ~(1 << pos ); |
861 | } else { | ||
862 | int pos, error = 0; | ||
863 | u32 active = ap->sactive; | ||
864 | |||
865 | while ((pos = ffs(active)) && !error) { | ||
866 | pos--; | ||
867 | error = nv_adma_check_cpb(ap, pos, | ||
868 | notifier_error & (1 << pos) ); | ||
869 | active &= ~(1 << pos ); | ||
870 | } | ||
871 | } | 873 | } |
872 | } | 874 | } |
873 | } | 875 | } |
@@ -905,73 +907,12 @@ static void nv_adma_irq_clear(struct ata_port *ap) | |||
905 | iowrite8(ioread8(dma_stat_addr), dma_stat_addr); | 907 | iowrite8(ioread8(dma_stat_addr), dma_stat_addr); |
906 | } | 908 | } |
907 | 909 | ||
908 | static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc) | 910 | static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc) |
909 | { | ||
910 | struct ata_port *ap = qc->ap; | ||
911 | unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); | ||
912 | struct nv_adma_port_priv *pp = ap->private_data; | ||
913 | u8 dmactl; | ||
914 | |||
915 | if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { | ||
916 | WARN_ON(1); | ||
917 | return; | ||
918 | } | ||
919 | |||
920 | /* load PRD table addr. */ | ||
921 | iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); | ||
922 | |||
923 | /* specify data direction, triple-check start bit is clear */ | ||
924 | dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
925 | dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); | ||
926 | if (!rw) | ||
927 | dmactl |= ATA_DMA_WR; | ||
928 | |||
929 | iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
930 | |||
931 | /* issue r/w command */ | ||
932 | ata_exec_command(ap, &qc->tf); | ||
933 | } | ||
934 | |||
935 | static void nv_adma_bmdma_start(struct ata_queued_cmd *qc) | ||
936 | { | ||
937 | struct ata_port *ap = qc->ap; | ||
938 | struct nv_adma_port_priv *pp = ap->private_data; | ||
939 | u8 dmactl; | ||
940 | |||
941 | if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { | ||
942 | WARN_ON(1); | ||
943 | return; | ||
944 | } | ||
945 | |||
946 | /* start host DMA transaction */ | ||
947 | dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
948 | iowrite8(dmactl | ATA_DMA_START, | ||
949 | ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
950 | } | ||
951 | |||
952 | static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc) | ||
953 | { | ||
954 | struct ata_port *ap = qc->ap; | ||
955 | struct nv_adma_port_priv *pp = ap->private_data; | ||
956 | |||
957 | if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) | ||
958 | return; | ||
959 | |||
960 | /* clear start/stop bit */ | ||
961 | iowrite8(ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, | ||
962 | ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
963 | |||
964 | /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ | ||
965 | ata_altstatus(ap); /* dummy read */ | ||
966 | } | ||
967 | |||
968 | static u8 nv_adma_bmdma_status(struct ata_port *ap) | ||
969 | { | 911 | { |
970 | struct nv_adma_port_priv *pp = ap->private_data; | 912 | struct nv_adma_port_priv *pp = qc->ap->private_data; |
971 | |||
972 | WARN_ON(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)); | ||
973 | 913 | ||
974 | return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | 914 | if(pp->flags & NV_ADMA_PORT_REGISTER_MODE) |
915 | ata_bmdma_post_internal_cmd(qc); | ||
975 | } | 916 | } |
976 | 917 | ||
977 | static int nv_adma_port_start(struct ata_port *ap) | 918 | static int nv_adma_port_start(struct ata_port *ap) |
@@ -1040,14 +981,15 @@ static int nv_adma_port_start(struct ata_port *ap) | |||
1040 | 981 | ||
1041 | /* clear GO for register mode, enable interrupt */ | 982 | /* clear GO for register mode, enable interrupt */ |
1042 | tmp = readw(mmio + NV_ADMA_CTL); | 983 | tmp = readw(mmio + NV_ADMA_CTL); |
1043 | writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); | 984 | writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | |
985 | NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); | ||
1044 | 986 | ||
1045 | tmp = readw(mmio + NV_ADMA_CTL); | 987 | tmp = readw(mmio + NV_ADMA_CTL); |
1046 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | 988 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); |
1047 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | 989 | readw( mmio + NV_ADMA_CTL ); /* flush posted write */ |
1048 | udelay(1); | 990 | udelay(1); |
1049 | writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | 991 | writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); |
1050 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | 992 | readw( mmio + NV_ADMA_CTL ); /* flush posted write */ |
1051 | 993 | ||
1052 | return 0; | 994 | return 0; |
1053 | } | 995 | } |
@@ -1099,14 +1041,15 @@ static int nv_adma_port_resume(struct ata_port *ap) | |||
1099 | 1041 | ||
1100 | /* clear GO for register mode, enable interrupt */ | 1042 | /* clear GO for register mode, enable interrupt */ |
1101 | tmp = readw(mmio + NV_ADMA_CTL); | 1043 | tmp = readw(mmio + NV_ADMA_CTL); |
1102 | writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); | 1044 | writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN | |
1045 | NV_ADMA_CTL_HOTPLUG_IEN, mmio + NV_ADMA_CTL); | ||
1103 | 1046 | ||
1104 | tmp = readw(mmio + NV_ADMA_CTL); | 1047 | tmp = readw(mmio + NV_ADMA_CTL); |
1105 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | 1048 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); |
1106 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | 1049 | readw( mmio + NV_ADMA_CTL ); /* flush posted write */ |
1107 | udelay(1); | 1050 | udelay(1); |
1108 | writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | 1051 | writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); |
1109 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | 1052 | readw( mmio + NV_ADMA_CTL ); /* flush posted write */ |
1110 | 1053 | ||
1111 | return 0; | 1054 | return 0; |
1112 | } | 1055 | } |
@@ -1163,11 +1106,7 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc, | |||
1163 | int idx, | 1106 | int idx, |
1164 | struct nv_adma_prd *aprd) | 1107 | struct nv_adma_prd *aprd) |
1165 | { | 1108 | { |
1166 | u8 flags; | 1109 | u8 flags = 0; |
1167 | |||
1168 | memset(aprd, 0, sizeof(struct nv_adma_prd)); | ||
1169 | |||
1170 | flags = 0; | ||
1171 | if (qc->tf.flags & ATA_TFLAG_WRITE) | 1110 | if (qc->tf.flags & ATA_TFLAG_WRITE) |
1172 | flags |= NV_APRD_WRITE; | 1111 | flags |= NV_APRD_WRITE; |
1173 | if (idx == qc->n_elem - 1) | 1112 | if (idx == qc->n_elem - 1) |
@@ -1178,6 +1117,7 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc, | |||
1178 | aprd->addr = cpu_to_le64(((u64)sg_dma_address(sg))); | 1117 | aprd->addr = cpu_to_le64(((u64)sg_dma_address(sg))); |
1179 | aprd->len = cpu_to_le32(((u32)sg_dma_len(sg))); /* len in bytes */ | 1118 | aprd->len = cpu_to_le32(((u32)sg_dma_len(sg))); /* len in bytes */ |
1180 | aprd->flags = flags; | 1119 | aprd->flags = flags; |
1120 | aprd->packet_len = 0; | ||
1181 | } | 1121 | } |
1182 | 1122 | ||
1183 | static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb) | 1123 | static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb) |
@@ -1198,6 +1138,8 @@ static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb) | |||
1198 | } | 1138 | } |
1199 | if (idx > 5) | 1139 | if (idx > 5) |
1200 | cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag))); | 1140 | cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag))); |
1141 | else | ||
1142 | cpb->next_aprd = cpu_to_le64(0); | ||
1201 | } | 1143 | } |
1202 | 1144 | ||
1203 | static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc) | 1145 | static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc) |
@@ -1230,7 +1172,10 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) | |||
1230 | return; | 1172 | return; |
1231 | } | 1173 | } |
1232 | 1174 | ||
1233 | memset(cpb, 0, sizeof(struct nv_adma_cpb)); | 1175 | cpb->resp_flags = NV_CPB_RESP_DONE; |
1176 | wmb(); | ||
1177 | cpb->ctl_flags = 0; | ||
1178 | wmb(); | ||
1234 | 1179 | ||
1235 | cpb->len = 3; | 1180 | cpb->len = 3; |
1236 | cpb->tag = qc->tag; | 1181 | cpb->tag = qc->tag; |
@@ -1254,12 +1199,15 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) | |||
1254 | finished filling in all of the contents */ | 1199 | finished filling in all of the contents */ |
1255 | wmb(); | 1200 | wmb(); |
1256 | cpb->ctl_flags = ctl_flags; | 1201 | cpb->ctl_flags = ctl_flags; |
1202 | wmb(); | ||
1203 | cpb->resp_flags = 0; | ||
1257 | } | 1204 | } |
1258 | 1205 | ||
1259 | static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) | 1206 | static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) |
1260 | { | 1207 | { |
1261 | struct nv_adma_port_priv *pp = qc->ap->private_data; | 1208 | struct nv_adma_port_priv *pp = qc->ap->private_data; |
1262 | void __iomem *mmio = pp->ctl_block; | 1209 | void __iomem *mmio = pp->ctl_block; |
1210 | int curr_ncq = (qc->tf.protocol == ATA_PROT_NCQ); | ||
1263 | 1211 | ||
1264 | VPRINTK("ENTER\n"); | 1212 | VPRINTK("ENTER\n"); |
1265 | 1213 | ||
@@ -1274,6 +1222,14 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) | |||
1274 | /* write append register, command tag in lower 8 bits | 1222 | /* write append register, command tag in lower 8 bits |
1275 | and (number of cpbs to append -1) in top 8 bits */ | 1223 | and (number of cpbs to append -1) in top 8 bits */ |
1276 | wmb(); | 1224 | wmb(); |
1225 | |||
1226 | if(curr_ncq != pp->last_issue_ncq) { | ||
1227 | /* Seems to need some delay before switching between NCQ and non-NCQ | ||
1228 | commands, else we get command timeouts and such. */ | ||
1229 | udelay(20); | ||
1230 | pp->last_issue_ncq = curr_ncq; | ||
1231 | } | ||
1232 | |||
1277 | writew(qc->tag, mmio + NV_ADMA_APPEND); | 1233 | writew(qc->tag, mmio + NV_ADMA_APPEND); |
1278 | 1234 | ||
1279 | DPRINTK("Issued tag %u\n",qc->tag); | 1235 | DPRINTK("Issued tag %u\n",qc->tag); |
@@ -1447,6 +1403,30 @@ static void nv_adma_error_handler(struct ata_port *ap) | |||
1447 | int i; | 1403 | int i; |
1448 | u16 tmp; | 1404 | u16 tmp; |
1449 | 1405 | ||
1406 | if(ata_tag_valid(ap->active_tag) || ap->sactive) { | ||
1407 | u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); | ||
1408 | u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); | ||
1409 | u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); | ||
1410 | u32 status = readw(mmio + NV_ADMA_STAT); | ||
1411 | u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT); | ||
1412 | u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX); | ||
1413 | |||
1414 | ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X " | ||
1415 | "notifier_error 0x%X gen_ctl 0x%X status 0x%X " | ||
1416 | "next cpb count 0x%X next cpb idx 0x%x\n", | ||
1417 | notifier, notifier_error, gen_ctl, status, | ||
1418 | cpb_count, next_cpb_idx); | ||
1419 | |||
1420 | for( i=0;i<NV_ADMA_MAX_CPBS;i++) { | ||
1421 | struct nv_adma_cpb *cpb = &pp->cpb[i]; | ||
1422 | if( (ata_tag_valid(ap->active_tag) && i == ap->active_tag) || | ||
1423 | ap->sactive & (1 << i) ) | ||
1424 | ata_port_printk(ap, KERN_ERR, | ||
1425 | "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n", | ||
1426 | i, cpb->ctl_flags, cpb->resp_flags); | ||
1427 | } | ||
1428 | } | ||
1429 | |||
1450 | /* Push us back into port register mode for error handling. */ | 1430 | /* Push us back into port register mode for error handling. */ |
1451 | nv_adma_register_mode(ap); | 1431 | nv_adma_register_mode(ap); |
1452 | 1432 | ||
@@ -1460,10 +1440,10 @@ static void nv_adma_error_handler(struct ata_port *ap) | |||
1460 | /* Reset channel */ | 1440 | /* Reset channel */ |
1461 | tmp = readw(mmio + NV_ADMA_CTL); | 1441 | tmp = readw(mmio + NV_ADMA_CTL); |
1462 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | 1442 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); |
1463 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | 1443 | readw( mmio + NV_ADMA_CTL ); /* flush posted write */ |
1464 | udelay(1); | 1444 | udelay(1); |
1465 | writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | 1445 | writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); |
1466 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | 1446 | readw( mmio + NV_ADMA_CTL ); /* flush posted write */ |
1467 | } | 1447 | } |
1468 | 1448 | ||
1469 | ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, | 1449 | ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, |