diff options
author | Scott Long <scottl@FreeBSD.org> | 2002-04-24 05:12:50 +0000 |
---|---|---|
committer | Scott Long <scottl@FreeBSD.org> | 2002-04-24 05:12:50 +0000 |
commit | cbfd045b103707587ab0f74adeb4b5613815a573 (patch) | |
tree | def9cfe368f17c95e03e25881bfda308b7a3a6bc /sys/dev/aac/aac.c | |
parent | d5d1c5a11e3ab16009e04585cf3cb6f98a734529 (diff) | |
download | src-cbfd045b103707587ab0f74adeb4b5613815a573.tar.gz src-cbfd045b103707587ab0f74adeb4b5613815a573.zip |
Prepare for a major update to the aac driver:
Update the aac driver with the new crashdump api.
Protect sync fibs with a mutex.
Align all DMA buffers on a PAGE_SIZE boundary.
MFC after: 3 days
Notes
Notes:
svn path=/head/; revision=95350
Diffstat (limited to 'sys/dev/aac/aac.c')
-rw-r--r-- | sys/dev/aac/aac.c | 277 |
1 files changed, 88 insertions, 189 deletions
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"); @@ -1000,102 +1004,6 @@ aac_bio_complete(struct aac_command *cm) } /* - * 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 * be stuck here forever. At the same time, signals are not caught @@ -1604,19 +1512,43 @@ aac_sync_command(struct aac_softc *sc, u_int32_t command, } /* + * 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); @@ -1637,17 +1569,6 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, 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. */ if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, @@ -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 |