Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Nov 2010 09:05:40 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r214666 - stable/8/sys/dev/mvs
Message-ID:  <201011020905.oA295ear031503@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Tue Nov  2 09:05:40 2010
New Revision: 214666
URL: http://svn.freebsd.org/changeset/base/214666

Log:
  MFC r214102:
  Workaround strange situation when EDMA_RESQIP register returns zero instead
  of proper value. It caused bunch of "EMPTY CRPB" messages and potentially
  may cause premature requests completion, which could cause data corruption.
  For most cases it seems enough to just reread register to get proper value.
  To protect against worse cases - erase processed queue entries with
  impossible values and ignore them if problem still happen.

Modified:
  stable/8/sys/dev/mvs/mvs.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/mvs/mvs.c
==============================================================================
--- stable/8/sys/dev/mvs/mvs.c	Tue Nov  2 09:04:18 2010	(r214665)
+++ stable/8/sys/dev/mvs/mvs.c	Tue Nov  2 09:05:40 2010	(r214666)
@@ -454,7 +454,7 @@ mvs_setup_edma_queues(device_t dev)
 	bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map,
 	    BUS_DMASYNC_PREWRITE);
 	/* Reponses queue. */
-	bzero(ch->dma.workrp, 256);
+	memset(ch->dma.workrp, 0xff, MVS_WORKRP_SIZE);
 	work = ch->dma.workrp_bus;
 	ATA_OUTL(ch->r_mem, EDMA_RESQBAH, work >> 32);
 	ATA_OUTL(ch->r_mem, EDMA_RESQIP, work & 0xffffffff);
@@ -979,38 +979,54 @@ mvs_crbq_intr(device_t dev)
 	struct mvs_channel *ch = device_get_softc(dev);
 	struct mvs_crpb *crpb;
 	union ccb *ccb;
-	int in_idx, cin_idx, slot;
+	int in_idx, fin_idx, cin_idx, slot;
+	uint32_t val;
 	uint16_t flags;
 
-	in_idx = (ATA_INL(ch->r_mem, EDMA_RESQIP) & EDMA_RESQP_ERPQP_MASK) >>
+	val = ATA_INL(ch->r_mem, EDMA_RESQIP);
+	if (val == 0)
+		val = ATA_INL(ch->r_mem, EDMA_RESQIP);
+	in_idx = (val & EDMA_RESQP_ERPQP_MASK) >>
 	    EDMA_RESQP_ERPQP_SHIFT;
 	bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map,
 	    BUS_DMASYNC_POSTREAD);
-	cin_idx = ch->in_idx;
+	fin_idx = cin_idx = ch->in_idx;
 	ch->in_idx = in_idx;
 	while (in_idx != cin_idx) {
 		crpb = (struct mvs_crpb *)
-		    (ch->dma.workrp + MVS_CRPB_OFFSET + (MVS_CRPB_SIZE * cin_idx));
+		    (ch->dma.workrp + MVS_CRPB_OFFSET +
+		    (MVS_CRPB_SIZE * cin_idx));
 		slot = le16toh(crpb->id) & MVS_CRPB_TAG_MASK;
 		flags = le16toh(crpb->rspflg);
-//device_printf(dev, "CRPB %d %d %04x\n", cin_idx, slot, flags);
 		/*
 		 * Handle only successfull completions here.
 		 * Errors will be handled by main intr handler.
 		 */
-		if (ch->numtslots != 0 || (flags & EDMA_IE_EDEVERR) == 0) {
-if ((flags >> 8) & ATA_S_ERROR)
-device_printf(dev, "ERROR STATUS CRPB %d %d %04x\n", cin_idx, slot, flags);
+		if (crpb->id == 0xffff && crpb->rspflg == 0xffff) {
+			device_printf(dev, "Unfilled CRPB "
+			    "%d (%d->%d) tag %d flags %04x rs %08x\n",
+			    cin_idx, fin_idx, in_idx, slot, flags, ch->rslots);
+		} else if (ch->numtslots != 0 ||
+		    (flags & EDMA_IE_EDEVERR) == 0) {
+			crpb->id = 0xffff;
+			crpb->rspflg = 0xffff;
 			if (ch->slot[slot].state >= MVS_SLOT_RUNNING) {
 				ccb = ch->slot[slot].ccb;
-				ccb->ataio.res.status = (flags & MVS_CRPB_ATASTS_MASK) >>
+				ccb->ataio.res.status =
+				    (flags & MVS_CRPB_ATASTS_MASK) >>
 				    MVS_CRPB_ATASTS_SHIFT;
 				mvs_end_transaction(&ch->slot[slot], MVS_ERR_NONE);
-			} else 
-device_printf(dev, "EMPTY CRPB %d (->%d) %d %04x\n", cin_idx, in_idx, slot, flags);
-		} else
-device_printf(dev, "ERROR FLAGS CRPB %d %d %04x\n", cin_idx, slot, flags);
-
+			} else {
+				device_printf(dev, "Unused tag in CRPB "
+				    "%d (%d->%d) tag %d flags %04x rs %08x\n",
+				    cin_idx, fin_idx, in_idx, slot, flags,
+				    ch->rslots);
+			}
+		} else {
+			device_printf(dev,
+			    "CRPB with error %d tag %d flags %04x\n",
+			    cin_idx, slot, flags);
+		}
 		cin_idx = (cin_idx + 1) & (MVS_MAX_SLOTS - 1);
 	}
 	bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201011020905.oA295ear031503>