svn commit: r215509 - in stable/8/sys/dev: ahci ata siis

Alexander Motin mav at FreeBSD.org
Fri Nov 19 09:14:53 UTC 2010


Author: mav
Date: Fri Nov 19 09:14:53 2010
New Revision: 215509
URL: http://svn.freebsd.org/changeset/base/215509

Log:
  MFC r214988:
  Teach ahci(4), siis(4) and ATA_CAM ata(4) wrapper report to CAM residual
  I/O length on underruns, that often happens for some SCSI commands.

Modified:
  stable/8/sys/dev/ahci/ahci.c
  stable/8/sys/dev/ata/ata-all.c
  stable/8/sys/dev/siis/siis.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/dev/ahci/ahci.c
==============================================================================
--- stable/8/sys/dev/ahci/ahci.c	Fri Nov 19 04:30:33 2010	(r215508)
+++ stable/8/sys/dev/ahci/ahci.c	Fri Nov 19 09:14:53 2010	(r215509)
@@ -1619,12 +1619,13 @@ ahci_execute_transaction(struct ahci_slo
 	/* Setup the command list entry */
 	clp = (struct ahci_cmd_list *)
 	    (ch->dma.work + AHCI_CL_OFFSET + (AHCI_CL_SIZE * slot->slot));
-	clp->prd_length = slot->dma.nsegs;
-	clp->cmd_flags = (ccb->ccb_h.flags & CAM_DIR_OUT ? AHCI_CMD_WRITE : 0) |
-		     (ccb->ccb_h.func_code == XPT_SCSI_IO ?
-		      (AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH) : 0) |
-		     (fis_size / sizeof(u_int32_t)) |
-		     (port << 12);
+	clp->cmd_flags = htole16(
+		    (ccb->ccb_h.flags & CAM_DIR_OUT ? AHCI_CMD_WRITE : 0) |
+		    (ccb->ccb_h.func_code == XPT_SCSI_IO ?
+		     (AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH) : 0) |
+		    (fis_size / sizeof(u_int32_t)) |
+		    (port << 12));
+	clp->prd_length = htole16(slot->dma.nsegs);
 	/* Special handling for Soft Reset command. */
 	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
 	    (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL)) {
@@ -1644,7 +1645,7 @@ ahci_execute_transaction(struct ahci_slo
 	clp->cmd_table_phys = htole64(ch->dma.work_bus + AHCI_CT_OFFSET +
 				  (AHCI_CT_SIZE * slot->slot));
 	bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
-	    BUS_DMASYNC_PREWRITE);
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 	bus_dmamap_sync(ch->dma.rfis_tag, ch->dma.rfis_map,
 	    BUS_DMASYNC_PREREAD);
 	/* Set ACTIVE bit for NCQ commands. */
@@ -1849,10 +1850,13 @@ ahci_end_transaction(struct ahci_slot *s
 	device_t dev = slot->dev;
 	struct ahci_channel *ch = device_get_softc(dev);
 	union ccb *ccb = slot->ccb;
+	struct ahci_cmd_list *clp;
 	int lastto;
 
 	bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
-	    BUS_DMASYNC_POSTWRITE);
+	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+	clp = (struct ahci_cmd_list *)
+	    (ch->dma.work + AHCI_CL_OFFSET + (AHCI_CL_SIZE * slot->slot));
 	/* Read result registers to the result struct
 	 * May be incorrect if several commands finished same time,
 	 * so read only when sure or have to.
@@ -1887,6 +1891,16 @@ ahci_end_transaction(struct ahci_slot *s
 			res->sector_count_exp = fis[13];
 		} else
 			bzero(res, sizeof(*res));
+		if ((ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) == 0 &&
+		    (ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+			ccb->ataio.resid =
+			    ccb->ataio.dxfer_len - le32toh(clp->bytecount);
+		}
+	} else {
+		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+			ccb->csio.resid =
+			    ccb->csio.dxfer_len - le32toh(clp->bytecount);
+		}
 	}
 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
 		bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map,

Modified: stable/8/sys/dev/ata/ata-all.c
==============================================================================
--- stable/8/sys/dev/ata/ata-all.c	Fri Nov 19 04:30:33 2010	(r215508)
+++ stable/8/sys/dev/ata/ata-all.c	Fri Nov 19 09:14:53 2010	(r215509)
@@ -1516,6 +1516,15 @@ ata_cam_end_transaction(device_t dev, st
 		res->sector_count = request->u.ata.count;
 		res->sector_count_exp = request->u.ata.count >> 8;
 	}
+	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+		if (ccb->ccb_h.func_code == XPT_ATA_IO) {
+			ccb->ataio.resid =
+			    ccb->ataio.dxfer_len - request->donecount;
+		} else {
+			ccb->csio.resid =
+			    ccb->csio.dxfer_len - request->donecount;
+		}
+	}
 	ata_free_request(request);
 	xpt_done(ccb);
 	/* Do error recovery if needed. */

Modified: stable/8/sys/dev/siis/siis.c
==============================================================================
--- stable/8/sys/dev/siis/siis.c	Fri Nov 19 04:30:33 2010	(r215508)
+++ stable/8/sys/dev/siis/siis.c	Fri Nov 19 09:14:53 2010	(r215509)
@@ -1208,6 +1208,17 @@ siis_end_transaction(struct siis_slot *s
 			res->sector_count_exp = ATA_INB(ch->r_mem, offs + 13);
 		} else
 			bzero(res, sizeof(*res));
+		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN &&
+		    ch->numrslots == 1) {
+			ccb->ataio.resid = ccb->ataio.dxfer_len -
+			    ATA_INL(ch->r_mem, SIIS_P_LRAM_SLOT(slot->slot) + 4);
+		}
+	} else {
+		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN &&
+		    ch->numrslots == 1) {
+			ccb->csio.resid = ccb->csio.dxfer_len -
+			    ATA_INL(ch->r_mem, SIIS_P_LRAM_SLOT(slot->slot) + 4);
+		}
 	}
 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
 		bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map,


More information about the svn-src-all mailing list