diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c index 1bb4ac7dab8f..a9c6ea3aee8e 100644 --- a/sys/dev/aac/aac.c +++ b/sys/dev/aac/aac.c @@ -73,7 +73,7 @@ static void aac_startup(void *arg); static void aac_add_container(struct aac_softc *sc, - struct aac_mntinforesponse *mir, int f); + struct aac_mntinforesp *mir, int f); /* Command Processing */ static void aac_startio(struct aac_softc *sc); @@ -105,10 +105,6 @@ static int aac_init(struct aac_softc *sc); static int aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp); -static int aac_sync_fib(struct aac_softc *sc, u_int32_t command, - u_int32_t xferstate, void *data, - u_int16_t datasize, void *result, - u_int16_t *resultsize); static int aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm); static int aac_dequeue_fib(struct aac_softc *sc, int queue, @@ -271,6 +267,9 @@ aac_attach(struct aac_softc *sc) if ((error = aac_alloc_commands(sc)) != 0) return(error); + /* Init the sync fib lock */ + AAC_LOCK_INIT(&sc->aac_sync_lock, "AAC sync FIB lock"); + /* * Initialise the adapter. */ @@ -338,9 +337,9 @@ static void aac_startup(void *arg) { struct aac_softc *sc; - struct aac_mntinfo mi; - struct aac_mntinforesponse mir; - u_int16_t rsize; + struct aac_fib *fib; + struct aac_mntinfo *mi; + struct aac_mntinforesp *mir = NULL; int i = 0; debug_called(1); @@ -350,28 +349,28 @@ aac_startup(void *arg) /* disconnect ourselves from the intrhook chain */ config_intrhook_disestablish(&sc->aac_ich); + aac_get_sync_fib(sc, &fib, 0); + mi = (struct aac_mntinfo *)&fib->data[0]; + /* loop over possible containers */ - mi.Command = VM_NameServe; - mi.MntType = FT_FILESYS; + mi->Command = VM_NameServe; + mi->MntType = FT_FILESYS; do { /* request information on this container */ - mi.MntCount = i; - rsize = sizeof(mir); - if (aac_sync_fib(sc, ContainerCommand, 0, &mi, - sizeof(struct aac_mntinfo), &mir, &rsize)) { + mi->MntCount = i; + if (aac_sync_fib(sc, ContainerCommand, 0, fib, + sizeof(struct aac_mntinfo))) { debug(2, "error probing container %d", i); continue; } /* check response size */ - if (rsize != sizeof(mir)) { - debug(2, "container info response wrong size " - "(%d should be %d)", rsize, sizeof(mir)); - continue; - } - aac_add_container(sc, &mir, 0); + mir = (struct aac_mntinforesp *)&fib->data[0]; + aac_add_container(sc, mir, 0); i++; - } while ((i < mir.MntRespCount) && (i < AAC_MAX_CONTAINERS)); + } while ((i < mir->MntRespCount) && (i < AAC_MAX_CONTAINERS)); + + aac_release_sync_fib(sc); /* poke the bus to actually attach the child devices */ if (bus_generic_attach(sc->aac_dev)) @@ -391,7 +390,7 @@ aac_startup(void *arg) * Create a device to respresent a new container */ static void -aac_add_container(struct aac_softc *sc, struct aac_mntinforesponse *mir, int f) +aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f) { struct aac_container *co; device_t child; @@ -527,8 +526,9 @@ int aac_shutdown(device_t dev) { struct aac_softc *sc; - struct aac_close_command cc; - int s, i; + struct aac_fib *fib; + struct aac_close_command *cc; + int s; debug_called(1); @@ -545,20 +545,24 @@ aac_shutdown(device_t dev) */ device_printf(sc->aac_dev, "shutting down controller..."); - cc.Command = VM_CloseAll; - cc.ContainerId = 0xffffffff; - if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc), NULL, NULL)) + aac_get_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE); + cc = (struct aac_close_command *)&fib->data[0]; + + cc->Command = VM_CloseAll; + cc->ContainerId = 0xffffffff; + if (aac_sync_fib(sc, ContainerCommand, 0, fib, + sizeof(struct aac_close_command))) printf("FAILED.\n"); else { - i = 0; + fib->data[0] = 0; /* * XXX Issuing this command to the controller makes it shut down * but also keeps it from coming back up without a reset of the * PCI bus. This is not desirable if you are just unloading the * driver module with the intent to reload it later. */ - if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, &i, - sizeof(i), NULL, NULL)) { + if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, + fib, 1)) { printf("FAILED.\n"); } else { printf("done.\n"); @@ -999,102 +1003,6 @@ aac_bio_complete(struct aac_command *cm) aac_biodone(bp); } -/* - * Dump a block of data to the controller. If the queue is full, tell the - * caller to hold off and wait for the queue to drain. - */ -int -aac_dump_enqueue(struct aac_disk *ad, u_int32_t lba, void *data, int dumppages) -{ - struct aac_softc *sc; - struct aac_command *cm; - struct aac_fib *fib; - struct aac_blockwrite *bw; - - sc = ad->ad_controller; - cm = NULL; - - if (aac_alloc_command(sc, &cm)) - return (EBUSY); - - /* fill out the command */ - cm->cm_data = data; - cm->cm_datalen = dumppages * PAGE_SIZE; - cm->cm_complete = NULL; - cm->cm_private = NULL; - cm->cm_timestamp = time_second; - cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; - - /* 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; - fib->Header.Command = ContainerCommand; - fib->Header.Size = sizeof(struct aac_fib_header); - - bw = (struct aac_blockwrite *)&fib->data[0]; - bw->Command = VM_CtBlockWrite; - bw->ContainerId = ad->ad_container->co_mntobj.ObjectId; - bw->BlockNumber = lba; - bw->ByteCount = dumppages * PAGE_SIZE; - bw->Stable = CUNSTABLE; /* XXX what's appropriate here? */ - fib->Header.Size += sizeof(struct aac_blockwrite); - cm->cm_flags |= AAC_CMD_DATAOUT; - cm->cm_sgtable = &bw->SgMap; - - return (aac_start(cm)); -} - -/* - * Wait for the card's queue to drain when dumping. Also check for monitor - * printf's - */ -void -aac_dump_complete(struct aac_softc *sc) -{ - struct aac_fib *fib; - struct aac_command *cm; - u_int16_t reason; - u_int32_t pi, ci, fib_size; - - do { - reason = AAC_GET_ISTATUS(sc); - if (reason & AAC_DB_RESPONSE_READY) { - AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY); - for (;;) { - if (aac_dequeue_fib(sc, - AAC_HOST_NORM_RESP_QUEUE, - &fib_size, &fib)) - break; - cm = (struct aac_command *) - fib->Header.SenderData; - if (cm == NULL) - AAC_PRINT_FIB(sc, fib); - else { - aac_remove_busy(cm); - aac_unmap_command(cm); - aac_enqueue_complete(cm); - aac_release_command(cm); - } - } - } - if (reason & AAC_DB_PRINTF) { - AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF); - aac_print_printf(sc); - } - pi = sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][ - AAC_PRODUCER_INDEX]; - ci = sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][ - AAC_CONSUMER_INDEX]; - } while (ci != pi); - - return; -} - /* * Submit a command to the controller, return when it completes. * XXX This is very dangerous! If the card has gone out to lunch, we could @@ -1603,20 +1511,44 @@ aac_sync_command(struct aac_softc *sc, u_int32_t command, return(0); } +/* + * Grab the sync fib area. + */ +int +aac_get_sync_fib(struct aac_softc *sc, struct aac_fib **fib, int flags) +{ + + /* + * If the force flag is set, the system is shutting down, or in + * trouble. Ignore the mutex. + */ + if (!(flags & AAC_SYNC_LOCK_FORCE)) + AAC_LOCK_ACQUIRE(&sc->aac_sync_lock); + + *fib = &sc->aac_common->ac_sync_fib; + + return (1); +} + +/* + * Release the sync fib area. + */ +void +aac_release_sync_fib(struct aac_softc *sc) +{ + + AAC_LOCK_RELEASE(&sc->aac_sync_lock); +} + /* * Send a synchronous FIB to the controller and wait for a result. */ -static int +int aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, - void *data, u_int16_t datasize, - void *result, u_int16_t *resultsize) + struct aac_fib *fib, u_int16_t datasize) { - struct aac_fib *fib; - debug_called(3); - fib = &sc->aac_common->ac_sync_fib; - if (datasize > AAC_FIB_DATASIZE) return(EINVAL); @@ -1636,17 +1568,6 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, offsetof(struct aac_common, ac_sync_fib); - /* - * Copy in data. - */ - if (data != NULL) { - KASSERT(datasize <= sizeof(fib->data), - ("aac_sync_fib: datasize to large")); - bcopy(data, fib->data, datasize); - fib->Header.XferState |= AAC_FIBSTATE_FROMHOST | - AAC_FIBSTATE_NORM; - } - /* * Give the FIB to the controller, wait for a response. */ @@ -1656,19 +1577,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, return(EIO); } - /* - * Copy out the result - */ - if (result != NULL) { - u_int copysize; - - copysize = fib->Header.Size - sizeof(struct aac_fib_header); - if (copysize > *resultsize) - copysize = *resultsize; - *resultsize = fib->Header.Size - sizeof(struct aac_fib_header); - bcopy(fib->data, result, copysize); - } - return(0); + return (0); } /* @@ -2156,28 +2065,19 @@ aac_fa_set_interrupts(struct aac_softc *sc, int enable) static void aac_describe_controller(struct aac_softc *sc) { - u_int8_t buf[AAC_FIB_DATASIZE]; /* XXX really a bit big - * for the stack */ - u_int16_t bufsize; + struct aac_fib *fib; struct aac_adapter_info *info; - u_int8_t arg; debug_called(2); - arg = 0; - bufsize = sizeof(buf); - if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &buf, - &bufsize)) { + aac_get_sync_fib(sc, &fib, 0); + + fib->data[0] = 0; + if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) { device_printf(sc->aac_dev, "RequestAdapterInfo failed\n"); return; } - if (bufsize != sizeof(*info)) { - device_printf(sc->aac_dev, - "RequestAdapterInfo returned wrong data size " - "(%d != %d)\n", bufsize, sizeof(*info)); - /*return;*/ - } - info = (struct aac_adapter_info *)&buf[0]; + info = (struct aac_adapter_info *)&fib->data[0]; device_printf(sc->aac_dev, "%s %dMHz, %dMB cache memory, %s\n", aac_describe_code(aac_cpu_variant, info->CpuVariant), @@ -2444,8 +2344,8 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) { struct aac_aif_command *aif; struct aac_container *co, *co_next; - struct aac_mntinfo mi; - struct aac_mntinforesponse mir; + struct aac_mntinfo *mi; + struct aac_mntinforesp *mir = NULL; u_int16_t rsize; int next, found; int added = 0, i = 0; @@ -2466,8 +2366,10 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) * doesn't tell us anything else! Re-enumerate the * containers and sort things out. */ - mi.Command = VM_NameServe; - mi.MntType = FT_FILESYS; + aac_get_sync_fib(sc, &fib, 0); + mi = (struct aac_mntinfo *)&fib->data[0]; + mi->Command = VM_NameServe; + mi->MntType = FT_FILESYS; do { /* * Ask the controller for its containers one at @@ -2476,32 +2378,28 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) * midway through this enumaration? * XXX This should be done async. */ - mi.MntCount = i; + mi->MntCount = i; rsize = sizeof(mir); - if (aac_sync_fib(sc, ContainerCommand, 0, &mi, - sizeof(mi), &mir, &rsize)) { + if (aac_sync_fib(sc, ContainerCommand, 0, fib, + sizeof(struct aac_mntinfo))) { debug(2, "Error probing container %d\n", i); continue; } - if (rsize != sizeof(mir)) { - debug(2, "Container response size too " - "large\n"); - continue; - } + mir = (struct aac_mntinforesp *)&fib->data[0]; /* * Check the container against our list. * co->co_found was already set to 0 in a * previous run. */ - if ((mir.Status == ST_OK) && - (mir.MntTable[0].VolType != CT_NONE)) { + if ((mir->Status == ST_OK) && + (mir->MntTable[0].VolType != CT_NONE)) { found = 0; TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) { if (co->co_mntobj.ObjectId == - mir.MntTable[0].ObjectId) { + mir->MntTable[0].ObjectId) { co->co_found = 1; found = 1; break; @@ -2519,12 +2417,13 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) /* * This is a new container. Do all the * appropriate things to set it up. */ - aac_add_container(sc, &mir, 1); + aac_add_container(sc, mir, 1); added = 1; } i++; - } while ((i < mir.MntRespCount) && + } while ((i < mir->MntRespCount) && (i < AAC_MAX_CONTAINERS)); + aac_release_sync_fib(sc); /* * Go through our list of containers and see which ones diff --git a/sys/dev/aac/aac_disk.c b/sys/dev/aac/aac_disk.c index d76006d13fb4..7aeb37ddfc52 100644 --- a/sys/dev/aac/aac_disk.c +++ b/sys/dev/aac/aac_disk.c @@ -108,18 +108,18 @@ static driver_t aac_disk_driver = { sizeof(struct aac_disk) }; +#define AAC_MAXIO 65536 + DRIVER_MODULE(aacd, aac, aac_disk_driver, aac_disk_devclass, 0, 0); /* sysctl tunables */ -static unsigned int aac_iosize_max = 65536; /* due to limits of the card */ +static unsigned int aac_iosize_max = AAC_MAXIO; /* due to limits of the card */ TUNABLE_INT("hw.aac.iosize_max", &aac_iosize_max); SYSCTL_DECL(_hw_aac); SYSCTL_UINT(_hw_aac, OID_AUTO, iosize_max, CTLFLAG_RD, &aac_iosize_max, 0, "Max I/O size per transfer to an array"); -#define AAC_MAXIO 65536 - /* * Handle open from generic layer. * @@ -212,89 +212,90 @@ aac_disk_strategy(struct bio *bp) return; } +/* + * Map the S/G elements for doing a dump. + */ +static void +aac_dump_map_sg(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct aac_fib *fib; + struct aac_blockwrite *bw; + struct aac_sg_table *sg; + int i; + + fib = (struct aac_fib *)arg; + bw = (struct aac_blockwrite *)&fib->data[0]; + sg = &bw->SgMap; + + if (sg != NULL) { + sg->SgCount = nsegs; + for (i = 0; i < nsegs; i++) { + sg->SgEntry[i].SgAddress = segs[i].ds_addr; + sg->SgEntry[i].SgByteCount = segs[i].ds_len; + } + fib->Header.Size = nsegs * sizeof(struct aac_sg_entry); + } +} + /* * Dump memory out to an array * - * This queues blocks of memory of size AAC_MAXIO to the controller and waits - * for the controller to complete the requests. + * Send out one command at a time with up to AAC_MAXIO of data. */ static int aac_disk_dump(dev_t dev, void *virtual, vm_offset_t physical, off_t offset, size_t length) { - - /* XXX: This needs modified for the new dump API */ - return (ENXIO); -#if 0 struct aac_disk *ad; struct aac_softc *sc; - vm_offset_t addr; - long blkcnt; - unsigned int count, blkno, secsize; - int dumppages; - int i, error; + struct aac_fib *fib; + struct aac_blockwrite *bw; + size_t len; + int size; + static bus_dmamap_t dump_datamap; + static int first = 0; ad = dev->si_drv1; - addr = 0; - dumppages = AAC_MAXIO / PAGE_SIZE; - - if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize))) - return (error); if (ad == NULL) - return (ENXIO); + return (EINVAL); sc= ad->ad_controller; - blkcnt = howmany(PAGE_SIZE, secsize); - - while (count > 0) { - caddr_t va = NULL; - - if ((count / blkcnt) < dumppages) - dumppages = count / blkcnt; - - for (i = 0; i < dumppages; ++i) { - vm_offset_t a = addr + (i * PAGE_SIZE); - if (is_physical_memory(a)) { - va = pmap_kenter_temporary(trunc_page(a), i); - } else { - va = pmap_kenter_temporary(trunc_page(0), i); - } + if (!first) { + first = 1; + if (bus_dmamap_create(sc->aac_buffer_dmat, 0, &dump_datamap)) { + printf("bus_dmamap_create failed\n"); + return (ENOMEM); } + } -retry: - /* - * Queue the block to the controller. If the queue is full, - * EBUSY will be returned. - */ - error = aac_dump_enqueue(ad, blkno, va, dumppages); - if (error && (error != EBUSY)) - return (error); + aac_get_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE); + bw = (struct aac_blockwrite *)&fib->data[0]; - if (!error) { - if (dumpstatus(addr, (off_t)(count * DEV_BSIZE)) < 0) - return (EINTR); + while (length > 0) { + len = (length > AAC_MAXIO) ? AAC_MAXIO : length; + bw->Command = VM_CtBlockWrite; + bw->ContainerId = ad->ad_container->co_mntobj.ObjectId; + bw->BlockNumber = offset / AAC_BLOCK_SIZE; + bw->ByteCount = len; + bw->Stable = CUNSTABLE; + bus_dmamap_load(sc->aac_buffer_dmat, dump_datamap, virtual, + len, aac_dump_map_sg, fib, 0); + bus_dmamap_sync(sc->aac_buffer_dmat, dump_datamap, + BUS_DMASYNC_PREWRITE); - blkno += blkcnt * dumppages; - count -= blkcnt * dumppages; - addr += PAGE_SIZE * dumppages; - if (count > 0) - continue; + /* fib->Header.Size is set in aac_dump_map_sg */ + size = fib->Header.Size + sizeof(struct aac_blockwrite); + + if (aac_sync_fib(sc, ContainerCommand, 0, fib, size)) { + printf("Error dumping block 0x%x\n", physical); + return (EIO); } - - /* - * Either the queue was full on the last attemp, or we have no - * more data to dump. Let the queue drain out and retry the - * block if the queue was full. - */ - aac_dump_complete(sc); - - if (error == EBUSY) - goto retry; + length -= len; + offset += len; } return (0); -#endif } /* diff --git a/sys/dev/aac/aac_pci.c b/sys/dev/aac/aac_pci.c index 3bcc1e2ddf6b..f19bf3d61fec 100644 --- a/sys/dev/aac/aac_pci.c +++ b/sys/dev/aac/aac_pci.c @@ -224,7 +224,7 @@ aac_pci_attach(device_t dev) * Note that some of these controllers are 64-bit capable. */ if (bus_dma_tag_create(NULL, /* parent */ - 1, 0, /* algnmnt, boundary */ + PAGE_SIZE, 0, /* algnmnt, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ diff --git a/sys/dev/aac/aacreg.h b/sys/dev/aac/aacreg.h index 8d526683afe9..2a954df7d880 100644 --- a/sys/dev/aac/aacreg.h +++ b/sys/dev/aac/aacreg.h @@ -986,7 +986,7 @@ struct aac_mntinfo { u_int32_t MntCount; } __attribute__ ((packed)); -struct aac_mntinforesponse { +struct aac_mntinforesp { AAC_FSAStatus Status; AAC_FType MntType; u_int32_t MntRespCount; diff --git a/sys/dev/aac/aacvar.h b/sys/dev/aac/aacvar.h index 7e8e4732373d..e4b870ee41c0 100644 --- a/sys/dev/aac/aacvar.h +++ b/sys/dev/aac/aacvar.h @@ -336,6 +336,10 @@ struct aac_softc struct aac_container_tq aac_container_tqh; aac_lock_t aac_container_lock; + /* Protect the sync fib */ +#define AAC_SYNC_LOCK_FORCE (1 << 0) + aac_lock_t aac_sync_lock; + /* delayed activity infrastructure */ #if __FreeBSD_version >= 500005 struct task aac_task_complete; /* deferred-completion @@ -373,9 +377,12 @@ extern int aac_resume(device_t dev); extern void aac_intr(void *arg); extern void aac_submit_bio(struct bio *bp); extern void aac_biodone(struct bio *bp); -extern int aac_dump_enqueue(struct aac_disk *ad, u_int32_t lba, - void *data, int nblks); -extern void aac_dump_complete(struct aac_softc *sc); +extern int aac_get_sync_fib(struct aac_softc *sc, + struct aac_fib **fib, int flags); +extern void aac_release_sync_fib(struct aac_softc *sc); +extern int aac_sync_fib(struct aac_softc *sc, u_int32_t command, + u_int32_t xferstate, struct aac_fib *fib, + u_int16_t datasize); /* * Debugging levels: @@ -400,7 +407,7 @@ extern void aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, extern void aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif); -# define AAC_PRINT_FIB(sc, fib) aac_print_fib(sc, fib, __func__) +#define AAC_PRINT_FIB(sc, fib) aac_print_fib(sc, fib, __func__) #else # define debug(level, fmt, args...)