Daniel Eriksson wrote: > Ville-Pertti Keinonen wrote: > > >>The attached patch should enable serialization for the >>controller, which is the only completely reliable fix >>(without chipset documentation) according to Søren. >>Obviously it reduces performance since it doesn't >>allow both channels to operate simultaneously. > > > After applying the patch to sources cvsuped 2004.08.04.01.00.00, everything > seems to be working correctly. I've run a few stress-tests successfully, and > I also started smartd (/usr/ports/sysutils/smartmontools/) which previously > always managed to lock up one of the SATA channels. > > I am going to run some more stress-tests later today, but it looks pretty > promising. OK, but that seriously hurts performance which I'd like to avoid if possible. Could you try the attached patch and let me know how that works out ? I does solve the problem here in a simulated setup, but as we all know simulated is just that :) -- -Søren Index: ata-all.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/ata-all.c,v retrieving revision 1.217 diff -u -r1.217 ata-all.c --- ata-all.c 1 Aug 2004 12:31:38 -0000 1.217 +++ ata-all.c 3 Aug 2004 10:28:47 -0000 _at__at_ -231,7 +231,6 _at__at_ int ata_reinit(struct ata_channel *ch) { - struct ata_request *request = ch->running; int devices, misdev, newdev; if (!ch->r_irq) _at__at_ -242,10 +241,8 _at__at_ ata_printf(ch, -1, "reiniting channel ..\n"); ATA_FORCELOCK_CH(ch); ch->flags |= ATA_IMMEDIATE_MODE; - ch->running = NULL; devices = ch->devices; ch->hw.reset(ch); - ATA_UNLOCK_CH(ch); if (bootverbose) ata_printf(ch, -1, "resetting done ..\n"); _at__at_ -254,10 +251,6 _at__at_ if ((misdev = devices & ~ch->devices)) { if ((misdev & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) && ch->device[MASTER].detach) { - if (request && (request->device == &ch->device[MASTER])) { - request->result = ENXIO; - request->retries = 0; - } ch->device[MASTER].detach(&ch->device[MASTER]); ata_fail_requests(ch, &ch->device[MASTER]); free(ch->device[MASTER].param, M_ATA); _at__at_ -265,10 +258,6 _at__at_ } if ((misdev & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) && ch->device[SLAVE].detach) { - if (request && (request->device == &ch->device[SLAVE])) { - request->result = ENXIO; - request->retries = 0; - } ch->device[SLAVE].detach(&ch->device[SLAVE]); ata_fail_requests(ch, &ch->device[SLAVE]); free(ch->device[SLAVE].param, M_ATA); _at__at_ -276,6 +265,9 _at__at_ } } + ch->running = NULL; + ATA_UNLOCK_CH(ch); + /* identify what is present on the channel now */ ata_identify_devices(ch); Index: ata-all.h =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/ata-all.h,v retrieving revision 1.79 diff -u -r1.79 ata-all.h --- ata-all.h 30 Apr 2004 16:21:34 -0000 1.79 +++ ata-all.h 3 Aug 2004 18:27:52 -0000 _at__at_ -297,8 +297,9 _at__at_ u_int32_t max_iosize; /* DMA engine max IO size */ u_int32_t cur_iosize; /* DMA engine current IO size */ int flags; -#define ATA_DMA_ACTIVE 0x01 /* DMA transfer in progress */ -#define ATA_DMA_READ 0x02 /* transaction is a read */ +#define ATA_DMA_READ 0x01 /* transaction is a read */ +#define ATA_DMA_LOADED 0x02 /* DMA tables etc loaded */ +#define ATA_DMA_ACTIVE 0x04 /* DMA transfer in progress */ void (*alloc)(struct ata_channel *ch); void (*free)(struct ata_channel *ch); Index: ata-chipset.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/ata-chipset.c,v retrieving revision 1.77 diff -u -r1.77 ata-chipset.c --- ata-chipset.c 30 Jul 2004 13:33:09 -0000 1.77 +++ ata-chipset.c 4 Aug 2004 15:12:22 -0000 _at__at_ -1433,12 +1433,14 _at__at_ static int ata_promise_mio_dmastart(struct ata_channel *ch) { + ch->flags |= ATA_DMA_ACTIVE; return 0; } static int ata_promise_mio_dmastop(struct ata_channel *ch) { + ch->flags &= ~ATA_DMA_ACTIVE; /* get status XXX SOS */ return 0; } _at__at_ -1777,6 +1779,7 _at__at_ ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, ((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) | ATA_BMCMD_START_STOP); + ch->flags |= ATA_DMA_ACTIVE; return 0; } _at__at_ -1795,6 +1798,7 _at__at_ error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT); ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); + ch->flags &= ~ATA_DMA_ACTIVE; ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); return error; } Index: ata-dma.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/ata-dma.c,v retrieving revision 1.126 diff -u -r1.126 ata-dma.c --- ata-dma.c 13 Apr 2004 09:44:20 -0000 1.126 +++ ata-dma.c 3 Aug 2004 18:25:11 -0000 _at__at_ -265,8 +265,7 _at__at_ dir ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); ch->dma->cur_iosize = count; - ch->dma->flags = dir ? (ATA_DMA_ACTIVE | ATA_DMA_READ) : ATA_DMA_ACTIVE; - + ch->dma->flags = dir ? (ATA_DMA_LOADED | ATA_DMA_READ) : ATA_DMA_LOADED; return 0; } _at__at_ -281,7 +280,6 _at__at_ bus_dmamap_unload(ch->dma->ddmatag, ch->dma->ddmamap); ch->dma->cur_iosize = 0; - ch->dma->flags = 0; - + ch->dma->flags &= ~ATA_DMA_LOADED; return 0; } Index: ata-lowlevel.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/ata-lowlevel.c,v retrieving revision 1.40 diff -u -r1.40 ata-lowlevel.c --- ata-lowlevel.c 24 Jul 2004 19:03:28 -0000 1.40 +++ ata-lowlevel.c 3 Aug 2004 18:29:23 -0000 _at__at_ -80,9 +80,6 _at__at_ return ATA_OP_FINISHED; } - /* record the request as running */ - ch->running = request; - ATA_DEBUG_RQ(request, "transaction"); /* disable ATAPI DMA writes if HW doesn't support it */ _at__at_ -120,10 +117,8 _at__at_ else printf("ATAPI_RESET timeout\n"); - if (request->status & ATA_S_ERROR) { + if (request->status & ATA_S_ERROR) request->error = ATA_IDX_INB(ch, ATA_ERROR); - //request->result = EIO; - } break; } _at__at_ -139,7 +134,8 _at__at_ } } - /* return and wait for interrupt */ + /* record the request as running and return for interrupt */ + ch->running = request; return ATA_OP_CONTINUES; /* ATA DMA data transfer commands */ _at__at_ -168,7 +164,8 _at__at_ break; } - /* return and wait for interrupt */ + /* record the request as running and return for interrupt */ + ch->running = request; return ATA_OP_CONTINUES; /* ATAPI PIO commands */ _at__at_ -192,8 +189,10 _at__at_ } /* command interrupt device ? just return and wait for interrupt */ - if ((request->device->param->config & ATA_DRQ_MASK) == ATA_DRQ_INTR) + if ((request->device->param->config & ATA_DRQ_MASK) == ATA_DRQ_INTR) { + ch->running = request; return ATA_OP_CONTINUES; + } /* wait for ready to write ATAPI command block */ { _at__at_ -224,7 +223,8 _at__at_ (request->device->param->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12 ? 6 : 8); - /* return and wait for interrupt */ + /* record the request as running and return for interrupt */ + ch->running = request; return ATA_OP_CONTINUES; case ATA_R_ATAPI|ATA_R_DMA: _at__at_ -289,14 +289,14 _at__at_ break; } - /* return and wait for interrupt */ + /* record the request as running and return for interrupt */ + ch->running = request; return ATA_OP_CONTINUES; } /* request finish here */ - if (ch->dma->flags & ATA_DMA_ACTIVE) + if (ch->dma->flags & ATA_DMA_LOADED) ch->dma->unload(ch); - ch->running = NULL; return ATA_OP_FINISHED; } Index: ata-pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/ata-pci.c,v retrieving revision 1.85 diff -u -r1.85 ata-pci.c --- ata-pci.c 15 Jun 2004 11:02:09 -0000 1.85 +++ ata-pci.c 3 Aug 2004 18:21:50 -0000 _at__at_ -454,6 +454,7 _at__at_ (ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_WRITE_READ) | ((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) | ATA_BMCMD_START_STOP); + ch->dma->flags |= ATA_DMA_ACTIVE; return 0; } _at__at_ -465,6 +466,7 _at__at_ error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); + ch->dma->flags &= ~ATA_DMA_ACTIVE; ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); return error; } Index: ata-queue.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/ata-queue.c,v retrieving revision 1.29 diff -u -r1.29 ata-queue.c --- ata-queue.c 1 Jun 2004 12:26:08 -0000 1.29 +++ ata-queue.c 1 Aug 2004 15:56:07 -0000 _at__at_ -160,15 +160,8 _at__at_ if (ch->flags & ATA_IMMEDIATE_MODE) return; - /* lock the ATA HW for this request */ - mtx_lock(&ch->queue_mtx); - ch->locking(ch, ATA_LF_LOCK); - if (!ATA_LOCK_CH(ch)) { - mtx_unlock(&ch->queue_mtx); - return; - } - /* if we dont have any work, ask the subdriver(s) */ + mtx_lock(&ch->queue_mtx); if (TAILQ_EMPTY(&ch->ata_queue)) { mtx_unlock(&ch->queue_mtx); if (ch->device[MASTER].start) _at__at_ -177,7 +170,15 _at__at_ ch->device[SLAVE].start(&ch->device[SLAVE]); mtx_lock(&ch->queue_mtx); } + + /* if we have work todo, try to lock the ATA HW and start transaction */ if ((request = TAILQ_FIRST(&ch->ata_queue))) { + ch->locking(ch, ATA_LF_LOCK); + if (!ATA_LOCK_CH(ch)) { + mtx_unlock(&ch->queue_mtx); + return; + } + TAILQ_REMOVE(&ch->ata_queue, request, chain); mtx_unlock(&ch->queue_mtx); _at__at_ -192,15 +193,14 _at__at_ /* kick HW into action and wait for interrupt if it flies*/ if (ch->hw.transaction(request) == ATA_OP_CONTINUES) return; - } - /* unlock ATA channel HW */ - ATA_UNLOCK_CH(ch); - ch->locking(ch, ATA_LF_UNLOCK); + /* unlock ATA channel HW */ + ATA_UNLOCK_CH(ch); + ch->locking(ch, ATA_LF_UNLOCK); - /* if we have a request here it failed and should be completed */ - if (request) + /* finish up this (failed) request */ ata_finish(request); + } else mtx_unlock(&ch->queue_mtx); }Received on Wed Aug 04 2004 - 11:33:44 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:04 UTC