From owner-svn-src-all@FreeBSD.ORG Wed Oct 20 07:47:31 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 573CC1065675; Wed, 20 Oct 2010 07:47:31 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 45A1F8FC18; Wed, 20 Oct 2010 07:47:31 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o9K7lVLI041770; Wed, 20 Oct 2010 07:47:31 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o9K7lV22041768; Wed, 20 Oct 2010 07:47:31 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201010200747.o9K7lV22041768@svn.freebsd.org> From: Alexander Motin Date: Wed, 20 Oct 2010 07:47:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r214102 - head/sys/dev/mvs X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Oct 2010 07:47:31 -0000 Author: mav Date: Wed Oct 20 07:47:31 2010 New Revision: 214102 URL: http://svn.freebsd.org/changeset/base/214102 Log: 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: head/sys/dev/mvs/mvs.c Modified: head/sys/dev/mvs/mvs.c ============================================================================== --- head/sys/dev/mvs/mvs.c Wed Oct 20 07:40:23 2010 (r214101) +++ head/sys/dev/mvs/mvs.c Wed Oct 20 07:47:31 2010 (r214102) @@ -455,7 +455,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); @@ -980,38 +980,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,