diff options
author | scottl <scottl@FreeBSD.org> | 2005-01-28 05:02:13 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2005-01-28 05:02:13 +0000 |
commit | bad78b265c4a0765532ab7d2ac5493c0a2e39191 (patch) | |
tree | 16fadd7614f98d4101435336cd7d5d0a95bbb58d /sys/dev/ips | |
parent | a52d6034c25c293be752e89574f77b0c7059ae46 (diff) | |
download | FreeBSD-src-bad78b265c4a0765532ab7d2ac5493c0a2e39191.zip FreeBSD-src-bad78b265c4a0765532ab7d2ac5493c0a2e39191.tar.gz |
Lock the IPS driver and bring it out from under Giant. Also do some
significant clean up and optimizations:
- don't call bioq_disksort() on every command, the hardware will do that for
us.
- remove all of the complicated bio deferral code. bio's that can't be
serviced immediately can just wait on the bioq.
- Only reserve one command object for doing control commands to the card.
This simplifies a lot of code and significantly reduces the size of the
command struct.
- Allocate commands out of a slab instead of embedding them into the softc.
- Call the command action method directly instead of having ips_get_free_cmd()
call it indirectly.
MFC After: 1 week
Diffstat (limited to 'sys/dev/ips')
-rw-r--r-- | sys/dev/ips/ips.c | 146 | ||||
-rw-r--r-- | sys/dev/ips/ips.h | 24 | ||||
-rw-r--r-- | sys/dev/ips/ips_commands.c | 184 | ||||
-rw-r--r-- | sys/dev/ips/ips_disk.c | 6 | ||||
-rw-r--r-- | sys/dev/ips/ips_ioctl.c | 14 | ||||
-rw-r--r-- | sys/dev/ips/ips_pci.c | 9 |
6 files changed, 149 insertions, 234 deletions
diff --git a/sys/dev/ips/ips.c b/sys/dev/ips/ips.c index b1a8297..d1aa459 100644 --- a/sys/dev/ips/ips.c +++ b/sys/dev/ips/ips.c @@ -101,7 +101,7 @@ static void ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments,int segnum } /* is locking needed? what locking guarentees are there on removal? */ -static __inline__ int ips_cmdqueue_free(ips_softc_t *sc) +static int ips_cmdqueue_free(ips_softc_t *sc) { int i, error = -1; ips_command_t *command; @@ -112,7 +112,6 @@ static __inline__ int ips_cmdqueue_free(ips_softc_t *sc) for(i = 0; i < sc->max_cmds; i++){ command = &sc->commandarray[i]; - sema_destroy(&command->cmd_sema); if(command->command_phys_addr == 0) continue; @@ -121,22 +120,32 @@ static __inline__ int ips_cmdqueue_free(ips_softc_t *sc) bus_dmamem_free(sc->command_dmatag, command->command_buffer, command->command_dmamap); + if (command->data_dmamap != NULL) + bus_dmamap_destroy(command->data_dmatag, + command->data_dmamap); } error = 0; sc->state |= IPS_OFFLINE; } + sc->staticcmd = NULL; + free(sc->commandarray, M_DEVBUF); splx(mask); return error; } /* places all ips command structs on the free command queue. No locking as if someone else tries * to access this during init, we have bigger problems */ -static __inline__ int ips_cmdqueue_init(ips_softc_t *sc) +static int ips_cmdqueue_init(ips_softc_t *sc) { int i; ips_command_t *command; + + sc->commandarray = (ips_command_t *)malloc(sizeof(ips_command_t) * + sc->max_cmds, M_DEVBUF, M_NOWAIT|M_ZERO); + if (sc->commandarray == NULL) + return (ENOMEM); + SLIST_INIT(&sc->free_cmd_list); - STAILQ_INIT(&sc->cmd_wait_list); for(i = 0; i < sc->max_cmds; i++){ command = &sc->commandarray[i]; command->id = i; @@ -154,8 +163,14 @@ static __inline__ int ips_cmdqueue_init(ips_softc_t *sc) goto error; } - sema_init(&command->cmd_sema, 0, "IPS Command Semaphore"); - SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next); + if (i != 0) { + command->data_dmatag = sc->sg_dmatag; + if (bus_dmamap_create(command->data_dmatag, 0, + &command->data_dmamap)) + goto error; + SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next); + } else + sc->staticcmd = command; } sc->state &= ~IPS_OFFLINE; return 0; @@ -164,75 +179,12 @@ error: return ENOMEM; } -static int ips_add_waiting_command(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data, unsigned long flags) -{ - intrmask_t mask; - ips_command_t *command; - ips_wait_list_t *waiter; - unsigned long memflags = 0; - if(IPS_NOWAIT_FLAG & flags) - memflags = M_NOWAIT; - waiter = malloc(sizeof(ips_wait_list_t), M_IPSBUF, memflags); - if(!waiter) - return ENOMEM; - mask = splbio(); - if(sc->state & IPS_OFFLINE){ - splx(mask); - free(waiter, M_IPSBUF); - return EIO; - } - command = SLIST_FIRST(&sc->free_cmd_list); - if(command && !(sc->state & IPS_TIMEOUT)){ - SLIST_REMOVE_HEAD(&sc->free_cmd_list, next); - (sc->used_commands)++; - splx(mask); - clear_ips_command(command); - bzero(command->command_buffer, IPS_COMMAND_LEN); - free(waiter, M_IPSBUF); - command->arg = data; - return callback(command); - } - DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n"); - waiter->callback = callback; - waiter->data = data; - STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next); - splx(mask); - return 0; -} - -static void ips_run_waiting_command(ips_softc_t *sc) -{ - ips_wait_list_t *waiter; - ips_command_t *command; - int (*callback)(ips_command_t*); - intrmask_t mask; - - mask = splbio(); - waiter = STAILQ_FIRST(&sc->cmd_wait_list); - command = SLIST_FIRST(&sc->free_cmd_list); - if(!waiter || !command){ - splx(mask); - return; - } - DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n"); - SLIST_REMOVE_HEAD(&sc->free_cmd_list, next); - STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next); - (sc->used_commands)++; - splx(mask); - clear_ips_command(command); - bzero(command->command_buffer, IPS_COMMAND_LEN); - command->arg = waiter->data; - callback = waiter->callback; - free(waiter, M_IPSBUF); - callback(command); - return; -} /* returns a free command struct if one is available. * It also blanks out anything that may be a wild pointer/value. * Also, command buffers are not freed. They are * small so they are saved and kept dmamapped and loaded. */ -int ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data, unsigned long flags) +int ips_get_free_cmd(ips_softc_t *sc, ips_command_t **cmd, unsigned long flags) { intrmask_t mask; ips_command_t *command; @@ -242,20 +194,25 @@ int ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *da splx(mask); return EIO; } - command = SLIST_FIRST(&sc->free_cmd_list); - if(!command || (sc->state & IPS_TIMEOUT)){ - splx(mask); - if(flags & IPS_NOWAIT_FLAG) + if ((flags & IPS_STATIC_FLAG) == 0) { + command = SLIST_FIRST(&sc->free_cmd_list); + if(!command || (sc->state & IPS_TIMEOUT)){ + splx(mask); + return EBUSY; + } + SLIST_REMOVE_HEAD(&sc->free_cmd_list, next); + (sc->used_commands)++; + } else { + if (sc->state & IPS_STATIC_BUSY) return EAGAIN; - return ips_add_waiting_command(sc, callback, data, flags); + command = sc->staticcmd; + sc->state |= IPS_STATIC_BUSY; } - SLIST_REMOVE_HEAD(&sc->free_cmd_list, next); - (sc->used_commands)++; splx(mask); clear_ips_command(command); bzero(command->command_buffer, IPS_COMMAND_LEN); - command->arg = data; - return callback(command); + *cmd = command; + return 0; } /* adds a command back to the free command queue */ @@ -264,14 +221,16 @@ void ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command) intrmask_t mask; mask = splbio(); - if (sema_value(&command->cmd_sema) != 0) + if (sema_value(&sc->cmd_sema) != 0) panic("ips: command returned non-zero semaphore"); - SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next); - (sc->used_commands)--; + if (command != sc->staticcmd) { + SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next); + (sc->used_commands)--; + } else { + sc->state &= ~IPS_STATIC_BUSY; + } splx(mask); - if(!(sc->state & IPS_TIMEOUT)) - ips_run_waiting_command(sc); } static const char* ips_diskdev_statename(u_int8_t state) { @@ -348,6 +307,8 @@ static void ips_timeout(void *arg) ips_softc_t *sc = arg; int i, state = 0; ips_command_t *command; + + mtx_lock(&sc->queue_mtx); command = &sc->commandarray[0]; mask = splbio(); for(i = 0; i < sc->max_cmds; i++){ @@ -376,10 +337,10 @@ static void ips_timeout(void *arg) would go to the card. This sucks. */ } else sc->state &= ~IPS_TIMEOUT; - ips_run_waiting_command(sc); } if (sc->state != IPS_OFFLINE) sc->timer = timeout(ips_timeout, sc, 10*hz); + mtx_unlock(&sc->queue_mtx); splx(mask); } @@ -402,8 +363,8 @@ int ips_adapter_init(ips_softc_t *sc) /* maxsegsize*/ IPS_COMMAND_LEN + IPS_MAX_SG_LEN, /* flags */ 0, - /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &Giant, + /* lockfunc */ NULL, + /* lockarg */ NULL, &sc->command_dmatag) != 0) { device_printf(sc->dev, "can't alloc command dma tag\n"); goto error; @@ -420,7 +381,7 @@ int ips_adapter_init(ips_softc_t *sc) /* maxsegsize*/ IPS_MAX_IOBUF_SIZE, /* flags */ 0, /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &Giant, + /* lockarg */ &sc->queue_mtx, &sc->sg_dmatag) != 0) { device_printf(sc->dev, "can't alloc SG dma tag\n"); goto error; @@ -563,11 +524,13 @@ void ips_morpheus_intr(void *void_sc) int cmdnumber; ips_cmd_status_t status; + mtx_lock(&sc->queue_mtx); iisr =ips_read_4(sc, MORPHEUS_REG_IISR); oisr =ips_read_4(sc, MORPHEUS_REG_OISR); PRINTF(9,"interrupt registers in:%x out:%x\n",iisr, oisr); if(!(oisr & MORPHEUS_BIT_CMD_IRQ)){ DEVICE_PRINTF(2,sc->dev, "got a non-command irq\n"); + mtx_unlock(&sc->queue_mtx); return; } while((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR)) != 0xffffffff){ @@ -579,6 +542,7 @@ void ips_morpheus_intr(void *void_sc) DEVICE_PRINTF(9,sc->dev, "got command %d\n", cmdnumber); } + mtx_unlock(&sc->queue_mtx); return; } @@ -622,8 +586,8 @@ static int ips_copperhead_queue_init(ips_softc_t *sc) /* numsegs */ 1, /* maxsegsize*/ sizeof(ips_copper_queue_t), /* flags */ 0, - /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &Giant, + /* lockfunc */ NULL, + /* lockarg */ NULL, &dmatag) != 0) { device_printf(sc->dev, "can't alloc dma tag for statue queue\n"); error = ENOMEM; @@ -742,6 +706,7 @@ void ips_copperhead_intr(void *void_sc) int cmdnumber; ips_cmd_status_t status; + mtx_lock(&sc->queue_mtx); while(ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT){ status.value = ips_copperhead_cmd_status(sc); cmdnumber = status.fields.command_id; @@ -750,6 +715,7 @@ void ips_copperhead_intr(void *void_sc) sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber])); PRINTF(9, "ips: got command %d\n", cmdnumber); } + mtx_unlock(&sc->queue_mtx); return; } diff --git a/sys/dev/ips/ips.h b/sys/dev/ips/ips.h index 9c26a7a..c6952fd 100644 --- a/sys/dev/ips/ips.h +++ b/sys/dev/ips/ips.h @@ -71,12 +71,13 @@ MALLOC_DECLARE(M_IPSBUF); #define IPS_MAX_SG_LEN (sizeof(ips_sg_element_t) * IPS_MAX_SG_ELEMENTS) #define IPS_NVRAM_PAGE_SIZE 128 /* various flags */ -#define IPS_NOWAIT_FLAG 1 +#define IPS_STATIC_FLAG 0x01 /* states for the card to be in */ #define IPS_DEV_OPEN 0x01 #define IPS_TIMEOUT 0x02 /* command time out, need reset */ #define IPS_OFFLINE 0x04 /* can't reset card/card failure */ +#define IPS_STATIC_BUSY 0x08 /* max number of commands set to something low for now */ #define IPS_MAX_CMD_NUM 128 @@ -379,25 +380,18 @@ typedef struct ips_command{ u_int8_t id; u_int8_t timeout; struct ips_softc * sc; + bus_dma_tag_t data_dmatag; + bus_dmamap_t data_dmamap; bus_dmamap_t command_dmamap; void * command_buffer; u_int32_t command_phys_addr;/*WARNING! must be changed if 64bit addressing ever used*/ - struct sema cmd_sema; ips_cmd_status_t status; SLIST_ENTRY(ips_command) next; - bus_dma_tag_t data_dmatag; - bus_dmamap_t data_dmamap; void * data_buffer; - void * arg; + void * arg; void (* callback)(struct ips_command *command); }ips_command_t; -typedef struct ips_wait_list{ - STAILQ_ENTRY(ips_wait_list) next; - void *data; - int (* callback)(ips_command_t *command); -}ips_wait_list_t; - typedef struct ips_softc{ struct resource * iores; struct resource * irqres; @@ -426,9 +420,9 @@ typedef struct ips_softc{ u_int8_t next_drive; u_int8_t max_cmds; volatile u_int8_t used_commands; - ips_command_t commandarray[IPS_MAX_CMD_NUM]; + ips_command_t *commandarray; + ips_command_t *staticcmd; SLIST_HEAD(command_list, ips_command) free_cmd_list; - STAILQ_HEAD(command_wait_list,ips_wait_list) cmd_wait_list; int (* ips_adapter_reinit)(struct ips_softc *sc, int force); void (* ips_adapter_intr)(void *sc); @@ -436,6 +430,7 @@ typedef struct ips_softc{ ips_copper_queue_t * copper_queue; struct mtx queue_mtx; struct bio_queue_head queue; + struct sema cmd_sema; }ips_softc_t; @@ -455,8 +450,7 @@ extern int ips_update_nvram(ips_softc_t *sc); extern int ips_clear_adapter(ips_softc_t *sc); /* function defines from ips.c */ -extern int ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), - void *data, unsigned long flags); +extern int ips_get_free_cmd(ips_softc_t *sc, ips_command_t **command, unsigned long flags); extern void ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command); extern int ips_adapter_init(ips_softc_t *sc); extern int ips_morpheus_reinit(ips_softc_t *sc, int force); diff --git a/sys/dev/ips/ips_commands.c b/sys/dev/ips/ips_commands.c index e2495ab..bbaed71 100644 --- a/sys/dev/ips/ips_commands.c +++ b/sys/dev/ips/ips_commands.c @@ -39,12 +39,9 @@ __FBSDID("$FreeBSD$"); */ static void ips_wakeup_callback(ips_command_t *command) { - ips_cmd_status_t *status; - status = command->arg; - status->value = command->status.value; bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap, BUS_DMASYNC_POSTWRITE); - sema_post(&command->cmd_sema); + sema_post(&command->sc->cmd_sema); } /* Below are a series of functions for sending an IO request * to the adapter. The flow order is: start, send, callback, finish. @@ -62,7 +59,6 @@ static void ips_io_request_finish(ips_command_t *command) BUS_DMASYNC_POSTWRITE); } bus_dmamap_unload(command->data_dmatag, command->data_dmamap); - bus_dmamap_destroy(command->data_dmatag, command->data_dmamap); if(COMMAND_ERROR(&command->status)){ iobuf->bio_flags |=BIO_ERROR; iobuf->bio_error = EIO; @@ -85,7 +81,6 @@ static void ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments,in if(error){ printf("ips: error = %d in ips_sg_request_callback\n", error); bus_dmamap_unload(command->data_dmatag, command->data_dmamap); - bus_dmamap_destroy(command->data_dmatag, command->data_dmamap); iobuf->bio_flags |= BIO_ERROR; iobuf->bio_error = ENOMEM; ips_insert_free_cmd(sc, command); @@ -140,20 +135,10 @@ static void ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments,in return; } -static int ips_send_io_request(ips_command_t *command) +static int ips_send_io_request(ips_command_t *command, struct bio *iobuf) { - ips_softc_t *sc = command->sc; - struct bio *iobuf = command->arg; - command->data_dmatag = sc->sg_dmatag; - if(bus_dmamap_create(command->data_dmatag, 0, &command->data_dmamap)){ - device_printf(sc->dev, "dmamap failed\n"); - iobuf->bio_flags |= BIO_ERROR; - iobuf->bio_error = ENOMEM; - ips_insert_free_cmd(sc, command); - ipsd_finish(iobuf); - return 0; - } command->callback = ips_io_request_finish; + command->arg = iobuf; PRINTF(10, "ips test: : bcount %ld\n", iobuf->bio_bcount); bus_dmamap_load(command->data_dmatag, command->data_dmamap, iobuf->bio_data, iobuf->bio_bcount, @@ -164,21 +149,17 @@ static int ips_send_io_request(ips_command_t *command) void ips_start_io_request(ips_softc_t *sc) { struct bio *iobuf; + ips_command_t *command; - mtx_lock(&sc->queue_mtx); iobuf = bioq_first(&sc->queue); - if(!iobuf) { - mtx_unlock(&sc->queue_mtx); + if(!iobuf) return; - } - if(ips_get_free_cmd(sc, ips_send_io_request, iobuf, IPS_NOWAIT_FLAG)){ - mtx_unlock(&sc->queue_mtx); + if (ips_get_free_cmd(sc, &command, 0)) return; - } bioq_remove(&sc->queue, iobuf); - mtx_unlock(&sc->queue_mtx); + ips_send_io_request(command, iobuf); return; } @@ -193,8 +174,7 @@ static void ips_adapter_info_callback(void *cmdptr, bus_dma_segment_t *segments, ips_adapter_info_cmd *command_struct; sc = command->sc; if(error){ - ips_cmd_status_t * status = command->arg; - status->value = IPS_ERROR_STATUS; /* a lovely error value */ + command->status.value = IPS_ERROR_STATUS; /* a lovely error value */ ips_insert_free_cmd(sc, command); printf("ips: error = %d in ips_get_adapter_info\n", error); return; @@ -217,7 +197,6 @@ static int ips_send_adapter_info_cmd(ips_command_t *command) { int error = 0; ips_softc_t *sc = command->sc; - ips_cmd_status_t *status = command->arg; if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, /* alignemnt */ 1, @@ -230,8 +209,8 @@ static int ips_send_adapter_info_cmd(ips_command_t *command) /* numsegs */ 1, /* maxsegsize*/ IPS_ADAPTER_INFO_LEN, /* flags */ 0, - /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &Giant, + /* lockfunc */ NULL, + /* lockarg */ NULL, &command->data_dmatag) != 0) { printf("ips: can't alloc dma tag for adapter status\n"); error = ENOMEM; @@ -247,8 +226,8 @@ static int ips_send_adapter_info_cmd(ips_command_t *command) command->data_buffer,IPS_ADAPTER_INFO_LEN, ips_adapter_info_callback, command, BUS_DMA_NOWAIT); - if ((status->value == IPS_ERROR_STATUS) || - (sema_timedwait(&command->cmd_sema, 30*hz) != 0)) + if ((command->status.value == IPS_ERROR_STATUS) || + (sema_timedwait(&sc->cmd_sema, 30*hz) != 0)) error = ETIMEDOUT; if (error == 0) { @@ -270,21 +249,17 @@ exit: int ips_get_adapter_info(ips_softc_t *sc) { + ips_command_t *command; int error = 0; - ips_cmd_status_t *status; - status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO); - if(!status) - return ENOMEM; - if(ips_get_free_cmd(sc, ips_send_adapter_info_cmd, status, - IPS_NOWAIT_FLAG) > 0){ + + if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) > 0){ device_printf(sc->dev, "unable to get adapter configuration\n"); - free(status, M_IPSBUF); return ENXIO; } - if (COMMAND_ERROR(status)){ + ips_send_adapter_info_cmd(command); + if (COMMAND_ERROR(&command->status)){ error = ENXIO; } - free(status, M_IPSBUF); return error; } @@ -299,8 +274,7 @@ static void ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments,in ips_drive_cmd *command_struct; sc = command->sc; if(error){ - ips_cmd_status_t * status = command->arg; - status->value = IPS_ERROR_STATUS; + command->status.value = IPS_ERROR_STATUS; ips_insert_free_cmd(sc, command); printf("ips: error = %d in ips_get_drive_info\n", error); return; @@ -321,7 +295,6 @@ static int ips_send_drive_info_cmd(ips_command_t *command) { int error = 0; ips_softc_t *sc = command->sc; - ips_cmd_status_t *status = command->arg; ips_drive_info_t *driveinfo; if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, @@ -335,8 +308,8 @@ static int ips_send_drive_info_cmd(ips_command_t *command) /* numsegs */ 1, /* maxsegsize*/ IPS_DRIVE_INFO_LEN, /* flags */ 0, - /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &Giant, + /* lockfunc */ NULL, + /* lockarg */ NULL, &command->data_dmatag) != 0) { printf("ips: can't alloc dma tag for drive status\n"); error = ENOMEM; @@ -351,8 +324,8 @@ static int ips_send_drive_info_cmd(ips_command_t *command) bus_dmamap_load(command->data_dmatag, command->data_dmamap, command->data_buffer,IPS_DRIVE_INFO_LEN, ips_drive_info_callback, command, BUS_DMA_NOWAIT); - if ((status->value == IPS_ERROR_STATUS) || - (sema_timedwait(&command->cmd_sema, 10*hz) != 0)) + if ((command->status.value == IPS_ERROR_STATUS) || + (sema_timedwait(&sc->cmd_sema, 10*hz) != 0)) error = ETIMEDOUT; if (error == 0) { @@ -377,20 +350,16 @@ exit: int ips_get_drive_info(ips_softc_t *sc) { int error = 0; - ips_cmd_status_t *status; - status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO); - if(!status) - return ENOMEM; - if(ips_get_free_cmd(sc, ips_send_drive_info_cmd, status, - IPS_NOWAIT_FLAG) > 0){ - free(status, M_IPSBUF); + ips_command_t *command; + + if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) > 0){ device_printf(sc->dev, "unable to get drive configuration\n"); return ENXIO; } - if(COMMAND_ERROR(status)){ + ips_send_drive_info_cmd(command); + if(COMMAND_ERROR(&command->status)){ error = ENXIO; } - free(status, M_IPSBUF); return error; } @@ -399,7 +368,6 @@ int ips_get_drive_info(ips_softc_t *sc) static int ips_send_flush_cache_cmd(ips_command_t *command) { ips_softc_t *sc = command->sc; - ips_cmd_status_t *status = command->arg; ips_generic_cmd *command_struct; PRINTF(10,"ips test: got a command, building flush command\n"); @@ -410,28 +378,24 @@ static int ips_send_flush_cache_cmd(ips_command_t *command) bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, BUS_DMASYNC_PREWRITE); sc->ips_issue_cmd(command); - if (status->value != IPS_ERROR_STATUS) - sema_wait(&command->cmd_sema); + if (command->status.value != IPS_ERROR_STATUS) + sema_wait(&sc->cmd_sema); ips_insert_free_cmd(sc, command); return 0; } int ips_flush_cache(ips_softc_t *sc) { - ips_cmd_status_t *status; - status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO); - if(!status) - return ENOMEM; + ips_command_t *command; + device_printf(sc->dev, "flushing cache\n"); - if(ips_get_free_cmd(sc, ips_send_flush_cache_cmd, status, - IPS_NOWAIT_FLAG)){ - free(status, M_IPSBUF); + if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ device_printf(sc->dev, "ERROR: unable to get a command! can't flush cache!\n"); } - if(COMMAND_ERROR(status)){ + ips_send_flush_cache_cmd(command); + if(COMMAND_ERROR(&command->status)){ device_printf(sc->dev, "ERROR: cache flush command failed!\n"); } - free(status, M_IPSBUF); return 0; } @@ -481,7 +445,6 @@ void static ips_ffdc_settime(ips_adapter_ffdc_cmd *command, time_t sctime) static int ips_send_ffdc_reset_cmd(ips_command_t *command) { ips_softc_t *sc = command->sc; - ips_cmd_status_t *status = command->arg; ips_adapter_ffdc_cmd *command_struct; PRINTF(10,"ips test: got a command, building ffdc reset command\n"); @@ -496,27 +459,23 @@ static int ips_send_ffdc_reset_cmd(ips_command_t *command) bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, BUS_DMASYNC_PREWRITE); sc->ips_issue_cmd(command); - if (status->value != IPS_ERROR_STATUS) - sema_wait(&command->cmd_sema); + if (command->status.value != IPS_ERROR_STATUS) + sema_wait(&sc->cmd_sema); ips_insert_free_cmd(sc, command); return 0; } int ips_ffdc_reset(ips_softc_t *sc) { - ips_cmd_status_t *status; - status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO); - if(!status) - return ENOMEM; - if(ips_get_free_cmd(sc, ips_send_ffdc_reset_cmd, status, - IPS_NOWAIT_FLAG)){ - free(status, M_IPSBUF); + ips_command_t *command; + + if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ device_printf(sc->dev, "ERROR: unable to get a command! can't send ffdc reset!\n"); } - if(COMMAND_ERROR(status)){ + ips_send_ffdc_reset_cmd(command); + if(COMMAND_ERROR(&command->status)){ device_printf(sc->dev, "ERROR: ffdc reset command failed!\n"); } - free(status, M_IPSBUF); return 0; } @@ -553,8 +512,7 @@ static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,in ips_rw_nvram_cmd *command_struct; sc = command->sc; if(error){ - ips_cmd_status_t * status = command->arg; - status->value = IPS_ERROR_STATUS; + command->status.value = IPS_ERROR_STATUS; ips_insert_free_cmd(sc, command); printf("ips: error = %d in ips_read_nvram_callback\n", error); return; @@ -573,10 +531,10 @@ static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,in sc->ips_issue_cmd(command); } -static int ips_read_nvram(ips_command_t *command){ +static int ips_read_nvram(ips_command_t *command) +{ int error = 0; ips_softc_t *sc = command->sc; - ips_cmd_status_t *status = command->arg; if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, /* alignemnt */ 1, @@ -589,8 +547,8 @@ static int ips_read_nvram(ips_command_t *command){ /* numsegs */ 1, /* maxsegsize*/ IPS_NVRAM_PAGE_SIZE, /* flags */ 0, - /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &Giant, + /* lockfunc */ NULL, + /* lockarg */ NULL, &command->data_dmatag) != 0) { printf("ips: can't alloc dma tag for nvram\n"); error = ENOMEM; @@ -605,8 +563,8 @@ static int ips_read_nvram(ips_command_t *command){ bus_dmamap_load(command->data_dmatag, command->data_dmamap, command->data_buffer,IPS_NVRAM_PAGE_SIZE, ips_read_nvram_callback, command, BUS_DMA_NOWAIT); - if ((status->value == IPS_ERROR_STATUS) || - (sema_timedwait(&command->cmd_sema, 30*hz) != 0)) + if ((command->status.value == IPS_ERROR_STATUS) || + (sema_timedwait(&sc->cmd_sema, 30*hz) != 0)) error = ETIMEDOUT; if (error == 0) { @@ -625,19 +583,16 @@ exit: int ips_update_nvram(ips_softc_t *sc) { - ips_cmd_status_t *status; - status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO); - if(!status) - return ENOMEM; - if(ips_get_free_cmd(sc, ips_read_nvram, status, IPS_NOWAIT_FLAG)){ - free(status, M_IPSBUF); + ips_command_t *command; + + if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ device_printf(sc->dev, "ERROR: unable to get a command! can't update nvram\n"); return 1; } - if(COMMAND_ERROR(status)){ + ips_read_nvram(command); + if(COMMAND_ERROR(&command->status)){ device_printf(sc->dev, "ERROR: nvram update command failed!\n"); } - free(status, M_IPSBUF); return 0; @@ -647,7 +602,6 @@ int ips_update_nvram(ips_softc_t *sc) static int ips_send_config_sync_cmd(ips_command_t *command) { ips_softc_t *sc = command->sc; - ips_cmd_status_t *status = command->arg; ips_generic_cmd *command_struct; PRINTF(10,"ips test: got a command, building flush command\n"); @@ -659,8 +613,8 @@ static int ips_send_config_sync_cmd(ips_command_t *command) bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, BUS_DMASYNC_PREWRITE); sc->ips_issue_cmd(command); - if (status->value != IPS_ERROR_STATUS) - sema_wait(&command->cmd_sema); + if (command->status.value != IPS_ERROR_STATUS) + sema_wait(&sc->cmd_sema); ips_insert_free_cmd(sc, command); return 0; } @@ -668,7 +622,6 @@ static int ips_send_config_sync_cmd(ips_command_t *command) static int ips_send_error_table_cmd(ips_command_t *command) { ips_softc_t *sc = command->sc; - ips_cmd_status_t *status = command->arg; ips_generic_cmd *command_struct; PRINTF(10,"ips test: got a command, building errortable command\n"); @@ -680,8 +633,8 @@ static int ips_send_error_table_cmd(ips_command_t *command) bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, BUS_DMASYNC_PREWRITE); sc->ips_issue_cmd(command); - if (status->value != IPS_ERROR_STATUS) - sema_wait(&command->cmd_sema); + if (command->status.value != IPS_ERROR_STATUS) + sema_wait(&sc->cmd_sema); ips_insert_free_cmd(sc, command); return 0; } @@ -689,36 +642,29 @@ static int ips_send_error_table_cmd(ips_command_t *command) int ips_clear_adapter(ips_softc_t *sc) { - ips_cmd_status_t *status; - status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO); - if(!status) - return ENOMEM; + ips_command_t *command; + device_printf(sc->dev, "syncing config\n"); - if(ips_get_free_cmd(sc, ips_send_config_sync_cmd, status, - IPS_NOWAIT_FLAG)){ - free(status, M_IPSBUF); + if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n"); return 1; } - if(COMMAND_ERROR(status)){ - free(status, M_IPSBUF); + ips_send_config_sync_cmd(command); + if(COMMAND_ERROR(&command->status)){ device_printf(sc->dev, "ERROR: cache sync command failed!\n"); return 1; } device_printf(sc->dev, "clearing error table\n"); - if(ips_get_free_cmd(sc, ips_send_error_table_cmd, status, - IPS_NOWAIT_FLAG)){ - free(status, M_IPSBUF); + if(ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n"); return 1; } - if(COMMAND_ERROR(status)){ + ips_send_error_table_cmd(command); + if(COMMAND_ERROR(&command->status)){ device_printf(sc->dev, "ERROR: etable command failed!\n"); - free(status, M_IPSBUF); return 1; } - free(status, M_IPSBUF); return 0; } diff --git a/sys/dev/ips/ips_disk.c b/sys/dev/ips/ips_disk.c index 87b848e..4ddcfa1 100644 --- a/sys/dev/ips/ips_disk.c +++ b/sys/dev/ips/ips_disk.c @@ -102,9 +102,9 @@ static void ipsd_strategy(struct bio *iobuf) DEVICE_PRINTF(8,dsc->dev,"in strategy\n"); iobuf->bio_driver1 = (void *)(uintptr_t)dsc->sc->drives[dsc->disk_number].drivenum; mtx_lock(&dsc->sc->queue_mtx); - bioq_disksort(&dsc->sc->queue, iobuf); - mtx_unlock(&dsc->sc->queue_mtx); + bioq_insert_tail(&dsc->sc->queue, iobuf); ips_start_io_request(dsc->sc); + mtx_unlock(&dsc->sc->queue_mtx); } static int ipsd_probe(device_t dev) @@ -149,7 +149,7 @@ static int ipsd_attach(device_t dev) dsc->ipsd_disk->d_sectorsize = IPS_BLKSIZE; dsc->ipsd_disk->d_mediasize = (off_t)totalsectors * IPS_BLKSIZE; dsc->ipsd_disk->d_unit = dsc->unit; - dsc->ipsd_disk->d_flags = DISKFLAG_NEEDSGIANT; + dsc->ipsd_disk->d_flags = 0; disk_create(dsc->ipsd_disk, DISK_VERSION); device_printf(dev, "Logical Drive (%dMB)\n", diff --git a/sys/dev/ips/ips_ioctl.c b/sys/dev/ips/ips_ioctl.c index fa4ff36..d3cee20 100644 --- a/sys/dev/ips/ips_ioctl.c +++ b/sys/dev/ips/ips_ioctl.c @@ -85,6 +85,7 @@ static int ips_ioctl_start(ips_command_t *command) static int ips_ioctl_cmd(ips_softc_t *sc, ips_ioctl_t *ioctl_cmd, ips_user_request *user_request) { + ips_command_t *command; int error = EINVAL; if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, @@ -98,8 +99,8 @@ static int ips_ioctl_cmd(ips_softc_t *sc, ips_ioctl_t *ioctl_cmd, ips_user_reque /* numsegs */ 1, /* maxsegsize*/ ioctl_cmd->datasize, /* flags */ 0, - /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &Giant, + /* lockfunc */ NULL, + /* lockarg */ NULL, &ioctl_cmd->dmatag) != 0) { return ENOMEM; } @@ -112,16 +113,21 @@ static int ips_ioctl_cmd(ips_softc_t *sc, ips_ioctl_t *ioctl_cmd, ips_user_reque ioctl_cmd->datasize)) goto exit; ioctl_cmd->status.value = 0xffffffff; - if((error = ips_get_free_cmd(sc, ips_ioctl_start, ioctl_cmd,0)) > 0){ + mtx_lock(&sc->queue_mtx); + if((error = ips_get_free_cmd(sc, &command, 0)) > 0){ error = ENOMEM; + mtx_unlock(&sc->queue_mtx); goto exit; } + command->arg = ioctl_cmd; + ips_ioctl_start(command); while( ioctl_cmd->status.value == 0xffffffff) - tsleep(ioctl_cmd, 0, "ips", hz/10); + msleep(ioctl_cmd, &sc->queue_mtx, 0, "ips", hz/10); if(COMMAND_ERROR(&ioctl_cmd->status)) error = EIO; else error = 0; + mtx_unlock(&sc->queue_mtx); if(copyout(ioctl_cmd->data_buffer, user_request->data_buffer, ioctl_cmd->datasize)) error = EINVAL; diff --git a/sys/dev/ips/ips_pci.c b/sys/dev/ips/ips_pci.c index 5431c96..3b76c93 100644 --- a/sys/dev/ips/ips_pci.c +++ b/sys/dev/ips/ips_pci.c @@ -123,7 +123,7 @@ static int ips_pci_attach(device_t dev) device_printf(dev, "irq allocation failed\n"); goto error; } - if(bus_setup_intr(dev, sc->irqres, INTR_TYPE_BIO, sc->ips_adapter_intr, sc, &sc->irqcookie)){ + if(bus_setup_intr(dev, sc->irqres, INTR_TYPE_BIO|INTR_MPSAFE, sc->ips_adapter_intr, sc, &sc->irqcookie)){ device_printf(dev, "irq setup failed\n"); goto error; } @@ -138,8 +138,8 @@ static int ips_pci_attach(device_t dev) /* numsegs */ IPS_MAX_SG_ELEMENTS, /* maxsegsize*/ BUS_SPACE_MAXSIZE_32BIT, /* flags */ 0, - /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &Giant, + /* lockfunc */ NULL, + /* lockarg */ NULL, &sc->adapter_dmatag) != 0) { printf("IPS can't alloc dma tag\n"); goto error; @@ -147,6 +147,7 @@ static int ips_pci_attach(device_t dev) sc->ips_ich.ich_func = ips_intrhook; sc->ips_ich.ich_arg = sc; mtx_init(&sc->queue_mtx, "IPS bioqueue lock", MTX_DEF, 0); + sema_init(&sc->cmd_sema, 0, "IPS Command Semaphore"); bioq_init(&sc->queue); if (config_intrhook_establish(&sc->ips_ich) != 0) { printf("IPS can't establish configuration hook\n"); @@ -181,6 +182,8 @@ static int ips_pci_free(ips_softc_t *sc) if(sc->iores) bus_release_resource(sc->dev, sc->iotype, sc->rid, sc->iores); sc->configured = 0; + mtx_destroy(&sc->queue_mtx); + sema_destroy(&sc->cmd_sema); return 0; } |