aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/sata_mv.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 2770005324b4..33e387354388 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -915,7 +915,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
915 915
916 pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); 916 pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
917 pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); 917 pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
918 pp->sg_tbl[i].flags_size = cpu_to_le32(len); 918 pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff);
919 919
920 sg_len -= len; 920 sg_len -= len;
921 addr += len; 921 addr += len;
@@ -1187,7 +1187,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
1187{ 1187{
1188 void __iomem *mmio = host_set->mmio_base; 1188 void __iomem *mmio = host_set->mmio_base;
1189 void __iomem *hc_mmio = mv_hc_base(mmio, hc); 1189 void __iomem *hc_mmio = mv_hc_base(mmio, hc);
1190 struct ata_port *ap;
1191 struct ata_queued_cmd *qc; 1190 struct ata_queued_cmd *qc;
1192 u32 hc_irq_cause; 1191 u32 hc_irq_cause;
1193 int shift, port, port0, hard_port, handled; 1192 int shift, port, port0, hard_port, handled;
@@ -1210,25 +1209,31 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
1210 hc,relevant,hc_irq_cause); 1209 hc,relevant,hc_irq_cause);
1211 1210
1212 for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { 1211 for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
1213 ap = host_set->ports[port]; 1212 struct ata_port *ap = host_set->ports[port];
1213 struct mv_port_priv *pp = ap->private_data;
1214 hard_port = port & MV_PORT_MASK; /* range 0-3 */ 1214 hard_port = port & MV_PORT_MASK; /* range 0-3 */
1215 handled = 0; /* ensure ata_status is set if handled++ */ 1215 handled = 0; /* ensure ata_status is set if handled++ */
1216 1216
1217 if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { 1217 /* Note that DEV_IRQ might happen spuriously during EDMA,
1218 /* new CRPB on the queue; just one at a time until NCQ 1218 * and should be ignored in such cases. We could mask it,
1219 */ 1219 * but it's pretty rare and may not be worth the overhead.
1220 ata_status = mv_get_crpb_status(ap); 1220 */
1221 handled++; 1221 if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
1222 } else if ((DEV_IRQ << hard_port) & hc_irq_cause) { 1222 /* EDMA: check for response queue interrupt */
1223 /* received ATA IRQ; read the status reg to clear INTRQ 1223 if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
1224 */ 1224 ata_status = mv_get_crpb_status(ap);
1225 ata_status = readb((void __iomem *) 1225 handled = 1;
1226 }
1227 } else {
1228 /* PIO: check for device (drive) interrupt */
1229 if ((DEV_IRQ << hard_port) & hc_irq_cause) {
1230 ata_status = readb((void __iomem *)
1226 ap->ioaddr.status_addr); 1231 ap->ioaddr.status_addr);
1227 handled++; 1232 handled = 1;
1233 }
1228 } 1234 }
1229 1235
1230 if (ap && 1236 if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
1231 (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))
1232 continue; 1237 continue;
1233 1238
1234 err_mask = ac_err_mask(ata_status); 1239 err_mask = ac_err_mask(ata_status);
@@ -1240,12 +1245,12 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
1240 if ((PORT0_ERR << shift) & relevant) { 1245 if ((PORT0_ERR << shift) & relevant) {
1241 mv_err_intr(ap); 1246 mv_err_intr(ap);
1242 err_mask |= AC_ERR_OTHER; 1247 err_mask |= AC_ERR_OTHER;
1243 handled++; 1248 handled = 1;
1244 } 1249 }
1245 1250
1246 if (handled && ap) { 1251 if (handled) {
1247 qc = ata_qc_from_tag(ap, ap->active_tag); 1252 qc = ata_qc_from_tag(ap, ap->active_tag);
1248 if (NULL != qc) { 1253 if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
1249 VPRINTK("port %u IRQ found for qc, " 1254 VPRINTK("port %u IRQ found for qc, "
1250 "ata_status 0x%x\n", port,ata_status); 1255 "ata_status 0x%x\n", port,ata_status);
1251 /* mark qc status appropriately */ 1256 /* mark qc status appropriately */