From 6016d1505d6da6a688dda60cc49a2d9c250cdd53 Mon Sep 17 00:00:00 2001 From: sos Date: Thu, 5 Aug 2004 21:13:41 +0000 Subject: [PATCH] Try to narrow down the race window on HW that does not have ways to poll for which channel actually pulled the irq line. --- sys/dev/ata/ata-all.c | 14 +++----------- sys/dev/ata/ata-all.h | 5 +++-- sys/dev/ata/ata-chipset.c | 14 +++++++++----- sys/dev/ata/ata-dma.c | 6 ++---- sys/dev/ata/ata-lowlevel.c | 26 +++++++++++++------------- sys/dev/ata/ata-pci.c | 2 ++ sys/dev/ata/ata-queue.c | 28 ++++++++++++++-------------- 7 files changed, 46 insertions(+), 49 deletions(-) diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 3028a8890c16..6b87979b8ef6 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -231,7 +231,6 @@ ata_detach(device_t dev) int ata_reinit(struct ata_channel *ch) { - struct ata_request *request = ch->running; int devices, misdev, newdev; if (!ch->r_irq) @@ -242,10 +241,8 @@ ata_reinit(struct ata_channel *ch) 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"); @@ -254,10 +251,6 @@ ata_reinit(struct ata_channel *ch) 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); @@ -265,10 +258,6 @@ ata_reinit(struct ata_channel *ch) } 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); @@ -276,6 +265,9 @@ ata_reinit(struct ata_channel *ch) } } + ch->running = NULL; + ATA_UNLOCK_CH(ch); + /* identify what is present on the channel now */ ata_identify_devices(ch); diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 7e78c2fb86dd..60698dfae907 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -297,8 +297,9 @@ struct ata_dma { 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); diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c index 394667c2620a..69ecee52ce1e 100644 --- a/sys/dev/ata/ata-chipset.c +++ b/sys/dev/ata/ata-chipset.c @@ -1278,16 +1278,16 @@ ata_promise_chipinit(device_t dev) break; case PRMIO: - if (ctlr->r_res1) - bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1); +// if (ctlr->r_res1) +// bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1); ctlr->r_type1 = SYS_RES_MEMORY; - ctlr->r_rid1 = 0x20; + ctlr->r_rid1 = PCIR_BAR(4); if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, &ctlr->r_rid1, RF_ACTIVE))) return ENXIO; ctlr->r_type2 = SYS_RES_MEMORY; - ctlr->r_rid2 = 0x1c; + ctlr->r_rid2 = PCIR_BAR(3); if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, &ctlr->r_rid2, RF_ACTIVE))) return ENXIO; @@ -1433,12 +1433,14 @@ ata_promise_sx4_intr(void *data) 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; } @@ -1777,6 +1779,7 @@ ata_promise_new_dmastart(struct ata_channel *ch) 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; } @@ -1795,6 +1798,7 @@ ata_promise_new_dmastop(struct ata_channel *ch) 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; } @@ -2057,7 +2061,7 @@ ata_sii_chipinit(device_t dev) } ctlr->r_type2 = SYS_RES_MEMORY; - ctlr->r_rid2 = 0x24; + ctlr->r_rid2 = PCIR_BAR(5); if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, &ctlr->r_rid2, RF_ACTIVE))) return ENXIO; diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index d140d7d012fe..910ffddca72d 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -265,8 +265,7 @@ ata_dmaload(struct ata_device *atadev, caddr_t data, int32_t count, int dir) 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; } @@ -281,7 +280,6 @@ ata_dmaunload(struct ata_channel *ch) 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; } diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c index 29a95ad2e5b6..e305085f03e2 100644 --- a/sys/dev/ata/ata-lowlevel.c +++ b/sys/dev/ata/ata-lowlevel.c @@ -80,9 +80,6 @@ ata_generic_transaction(struct ata_request *request) 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 */ @@ -120,10 +117,8 @@ ata_generic_transaction(struct ata_request *request) 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; } @@ -139,7 +134,8 @@ ata_generic_transaction(struct ata_request *request) } } - /* 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 */ @@ -168,7 +164,8 @@ ata_generic_transaction(struct ata_request *request) 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 */ @@ -192,8 +189,10 @@ ata_generic_transaction(struct ata_request *request) } /* 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 */ { @@ -224,7 +223,8 @@ ata_generic_transaction(struct ata_request *request) (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: @@ -289,14 +289,14 @@ ata_generic_transaction(struct ata_request *request) 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; } diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index 16ac6f452cb6..24691488c2ad 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -454,6 +454,7 @@ ata_pci_dmastart(struct ata_channel *ch) (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; } @@ -465,6 +466,7 @@ ata_pci_dmastop(struct ata_channel *ch) 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; } diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c index 8b2b318cfaf6..34edd2dd759e 100644 --- a/sys/dev/ata/ata-queue.c +++ b/sys/dev/ata/ata-queue.c @@ -160,15 +160,8 @@ ata_start(struct ata_channel *ch) 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) @@ -177,7 +170,15 @@ ata_start(struct ata_channel *ch) 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); @@ -192,15 +193,14 @@ ata_start(struct ata_channel *ch) /* 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); }