Try to narrow down the race window on HW that does not have ways to
poll for which channel actually pulled the irq line.
This commit is contained in:
parent
54e7375090
commit
6016d1505d
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user