diff options
Diffstat (limited to 'drivers/ata/sata_nv.c')
-rw-r--r-- | drivers/ata/sata_nv.c | 57 |
1 files changed, 13 insertions, 44 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index cb89ef8d99d9..7254e255fd78 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
@@ -873,29 +873,11 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) | |||
873 | ata_port_freeze(ap); | 873 | ata_port_freeze(ap); |
874 | else | 874 | else |
875 | ata_port_abort(ap); | 875 | ata_port_abort(ap); |
876 | return 1; | 876 | return -1; |
877 | } | 877 | } |
878 | 878 | ||
879 | if (likely(flags & NV_CPB_RESP_DONE)) { | 879 | if (likely(flags & NV_CPB_RESP_DONE)) |
880 | struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num); | 880 | return 1; |
881 | VPRINTK("CPB flags done, flags=0x%x\n", flags); | ||
882 | if (likely(qc)) { | ||
883 | DPRINTK("Completing qc from tag %d\n", cpb_num); | ||
884 | ata_qc_complete(qc); | ||
885 | } else { | ||
886 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
887 | /* Notifier bits set without a command may indicate the drive | ||
888 | is misbehaving. Raise host state machine violation on this | ||
889 | condition. */ | ||
890 | ata_port_printk(ap, KERN_ERR, | ||
891 | "notifier for tag %d with no cmd?\n", | ||
892 | cpb_num); | ||
893 | ehi->err_mask |= AC_ERR_HSM; | ||
894 | ehi->action |= ATA_EH_RESET; | ||
895 | ata_port_freeze(ap); | ||
896 | return 1; | ||
897 | } | ||
898 | } | ||
899 | return 0; | 881 | return 0; |
900 | } | 882 | } |
901 | 883 | ||
@@ -1018,6 +1000,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) | |||
1018 | NV_ADMA_STAT_CPBERR | | 1000 | NV_ADMA_STAT_CPBERR | |
1019 | NV_ADMA_STAT_CMD_COMPLETE)) { | 1001 | NV_ADMA_STAT_CMD_COMPLETE)) { |
1020 | u32 check_commands = notifier_clears[i]; | 1002 | u32 check_commands = notifier_clears[i]; |
1003 | u32 done_mask = 0; | ||
1021 | int pos, rc; | 1004 | int pos, rc; |
1022 | 1005 | ||
1023 | if (status & NV_ADMA_STAT_CPBERR) { | 1006 | if (status & NV_ADMA_STAT_CPBERR) { |
@@ -1034,10 +1017,13 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) | |||
1034 | pos--; | 1017 | pos--; |
1035 | rc = nv_adma_check_cpb(ap, pos, | 1018 | rc = nv_adma_check_cpb(ap, pos, |
1036 | notifier_error & (1 << pos)); | 1019 | notifier_error & (1 << pos)); |
1037 | if (unlikely(rc)) | 1020 | if (rc > 0) |
1021 | done_mask |= 1 << pos; | ||
1022 | else if (unlikely(rc < 0)) | ||
1038 | check_commands = 0; | 1023 | check_commands = 0; |
1039 | check_commands &= ~(1 << pos); | 1024 | check_commands &= ~(1 << pos); |
1040 | } | 1025 | } |
1026 | ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask); | ||
1041 | } | 1027 | } |
1042 | } | 1028 | } |
1043 | 1029 | ||
@@ -2132,7 +2118,6 @@ static int nv_swncq_sdbfis(struct ata_port *ap) | |||
2132 | struct ata_eh_info *ehi = &ap->link.eh_info; | 2118 | struct ata_eh_info *ehi = &ap->link.eh_info; |
2133 | u32 sactive; | 2119 | u32 sactive; |
2134 | u32 done_mask; | 2120 | u32 done_mask; |
2135 | int i; | ||
2136 | u8 host_stat; | 2121 | u8 host_stat; |
2137 | u8 lack_dhfis = 0; | 2122 | u8 lack_dhfis = 0; |
2138 | 2123 | ||
@@ -2152,27 +2137,11 @@ static int nv_swncq_sdbfis(struct ata_port *ap) | |||
2152 | sactive = readl(pp->sactive_block); | 2137 | sactive = readl(pp->sactive_block); |
2153 | done_mask = pp->qc_active ^ sactive; | 2138 | done_mask = pp->qc_active ^ sactive; |
2154 | 2139 | ||
2155 | if (unlikely(done_mask & sactive)) { | 2140 | pp->qc_active &= ~done_mask; |
2156 | ata_ehi_clear_desc(ehi); | 2141 | pp->dhfis_bits &= ~done_mask; |
2157 | ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition" | 2142 | pp->dmafis_bits &= ~done_mask; |
2158 | "(%08x->%08x)", pp->qc_active, sactive); | 2143 | pp->sdbfis_bits |= done_mask; |
2159 | ehi->err_mask |= AC_ERR_HSM; | 2144 | ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask); |
2160 | ehi->action |= ATA_EH_RESET; | ||
2161 | return -EINVAL; | ||
2162 | } | ||
2163 | for (i = 0; i < ATA_MAX_QUEUE; i++) { | ||
2164 | if (!(done_mask & (1 << i))) | ||
2165 | continue; | ||
2166 | |||
2167 | qc = ata_qc_from_tag(ap, i); | ||
2168 | if (qc) { | ||
2169 | ata_qc_complete(qc); | ||
2170 | pp->qc_active &= ~(1 << i); | ||
2171 | pp->dhfis_bits &= ~(1 << i); | ||
2172 | pp->dmafis_bits &= ~(1 << i); | ||
2173 | pp->sdbfis_bits |= (1 << i); | ||
2174 | } | ||
2175 | } | ||
2176 | 2145 | ||
2177 | if (!ap->qc_active) { | 2146 | if (!ap->qc_active) { |
2178 | DPRINTK("over\n"); | 2147 | DPRINTK("over\n"); |