diff options
Diffstat (limited to 'sys/dev/aac/aac.c')
-rw-r--r-- | sys/dev/aac/aac.c | 89 |
1 files changed, 50 insertions, 39 deletions
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c index 42587dd..046fa19 100644 --- a/sys/dev/aac/aac.c +++ b/sys/dev/aac/aac.c @@ -624,45 +624,43 @@ aac_intr(void *arg) { struct aac_softc *sc; u_int16_t reason; + u_int32_t *resp_queue; debug_called(2); sc = (struct aac_softc *)arg; - reason = AAC_GET_ISTATUS(sc); + /* + * Optimize the common case of adapter response interrupts. + * We must read from the card prior to processing the responses + * to ensure the clear is flushed prior to accessing the queues. + * Reading the queues from local memory might save us a PCI read. + */ + resp_queue = sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE]; + if (resp_queue[AAC_PRODUCER_INDEX] != resp_queue[AAC_CONSUMER_INDEX]) + reason = AAC_DB_RESPONSE_READY; + else + reason = AAC_GET_ISTATUS(sc); + AAC_CLEAR_ISTATUS(sc, reason); + (void)AAC_GET_ISTATUS(sc); + + /* It's not ok to return here because of races with the previous step */ + if (reason & AAC_DB_RESPONSE_READY) + aac_host_response(sc); /* controller wants to talk to the log */ - if (reason & AAC_DB_PRINTF) { - AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF); + if (reason & AAC_DB_PRINTF) aac_print_printf(sc); - } /* controller has a message for us? */ if (reason & AAC_DB_COMMAND_READY) { - AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY); /* XXX What happens if the thread is already awake? */ if (sc->aifflags & AAC_AIFFLAGS_RUNNING) { sc->aifflags |= AAC_AIFFLAGS_PENDING; wakeup(sc->aifthread); } } - - /* controller has a response for us? */ - if (reason & AAC_DB_RESPONSE_READY) { - AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY); - aac_host_response(sc); - } - - /* - * spurious interrupts that we don't use - reset the mask and clear the - * interrupts - */ - if (reason & (AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL)) { - AAC_UNMASK_INTERRUPTS(sc); - AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_NOT_FULL | - AAC_DB_RESPONSE_NOT_FULL); - } -}; +} /* * Command Processing @@ -729,7 +727,6 @@ aac_start(struct aac_command *cm) /* save a pointer to the command for speedy reverse-lookup */ cm->cm_fib->Header.SenderData = (u_int32_t)cm; /* XXX 64-bit physical * address issue */ - /* put the FIB on the outbound queue */ error = aac_enqueue_fib(sc, cm->cm_queue, cm); return(error); @@ -928,11 +925,14 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp) /* build the FIB */ fib = cm->cm_fib; fib->Header.XferState = - AAC_FIBSTATE_HOSTOWNED | - AAC_FIBSTATE_INITIALISED | - AAC_FIBSTATE_FROMHOST | - AAC_FIBSTATE_REXPECTED | - AAC_FIBSTATE_NORM; + AAC_FIBSTATE_HOSTOWNED | + AAC_FIBSTATE_INITIALISED | + AAC_FIBSTATE_EMPTY | + AAC_FIBSTATE_FROMHOST | + AAC_FIBSTATE_REXPECTED | + AAC_FIBSTATE_NORM | + AAC_FIBSTATE_ASYNC | + AAC_FIBSTATE_FAST_RESPONSE; fib->Header.Command = ContainerCommand; fib->Header.Size = sizeof(struct aac_fib_header); @@ -1081,7 +1081,8 @@ aac_release_command(struct aac_command *cm) * initialised here for debugging purposes only. */ cm->cm_fib->Header.SenderFibAddress = (u_int32_t)cm->cm_fib; - cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys; + cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys; + cm->cm_fib->Header.SenderData = 0; aac_enqueue_free(cm); } @@ -1121,7 +1122,7 @@ aac_alloc_commands(struct aac_softc *sc) bus_dmamap_load(sc->aac_fib_dmat, sc->aac_fibmap, sc->aac_fibs, AAC_FIB_COUNT * sizeof(struct aac_fib), aac_map_command_helper, sc, 0); - + bzero(sc->aac_fibs, AAC_FIB_COUNT * sizeof(struct aac_fib)); /* initialise constant fields in the command structure */ for (i = 0; i < AAC_FIB_COUNT; i++) { cm = &sc->aac_command[i]; @@ -1206,12 +1207,12 @@ aac_map_command(struct aac_command *cm) cm->cm_data, cm->cm_datalen, aac_map_command_sg, cm, 0); - if (cm->cm_flags & AAC_CMD_DATAIN) - bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, - BUS_DMASYNC_PREREAD); - if (cm->cm_flags & AAC_CMD_DATAOUT) - bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, - BUS_DMASYNC_PREWRITE); + if (cm->cm_flags & AAC_CMD_DATAIN) + bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, + BUS_DMASYNC_PREREAD); + if (cm->cm_flags & AAC_CMD_DATAOUT) + bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, + BUS_DMASYNC_PREWRITE); } cm->cm_flags |= AAC_CMD_MAPPED; } @@ -1362,10 +1363,11 @@ aac_init(struct aac_softc *sc) */ ip = &sc->aac_common->ac_init; ip->InitStructRevision = AAC_INIT_STRUCT_REVISION; + ip->MiniPortRevision = AAC_INIT_STRUCT_MINIPORT_REVISION; ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr + offsetof(struct aac_common, ac_fibs); - ip->AdapterFibsVirtualAddress = &sc->aac_common->ac_fibs[0]; + ip->AdapterFibsVirtualAddress = (u_int32_t)&sc->aac_common->ac_fibs[0]; ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib); ip->AdapterFibAlign = sizeof(struct aac_fib); @@ -1373,7 +1375,8 @@ aac_init(struct aac_softc *sc) offsetof(struct aac_common, ac_printf); ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE; - ip->HostPhysMemPages = 0; /* not used? */ + /* The adapter assumes that pages are 4K in size */ + ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE; ip->HostElapsedSeconds = time_second; /* reset later if invalid */ /* @@ -1398,7 +1401,6 @@ aac_init(struct aac_softc *sc) ip->CommHeaderAddress = sc->aac_common_busaddr + ((u_int32_t)sc->aac_queues - (u_int32_t)sc->aac_common); - bzero(sc->aac_queues, sizeof(struct aac_queue_table)); sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = AAC_HOST_NORM_CMD_ENTRIES; @@ -1704,6 +1706,15 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, *fib_addr = (struct aac_fib *)(sc->aac_qentries[queue] + ci)->aq_fib_addr; + /* + * Is this a fast response? If it is, update the fib fields in + * local memory so the whole fib doesn't have to be DMA'd back up. + */ + if (*(uintptr_t *)fib_addr & 0x01) { + *(uintptr_t *)fib_addr &= ~0x01; + (*fib_addr)->Header.XferState |= AAC_FIBSTATE_DONEADAP; + *((u_int32_t*)((*fib_addr)->data)) = AAC_ERROR_NORMAL; + } /* update consumer index */ sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1; |