--- //depot/vendor/freebsd/src/sys/dev/twe/twe.c 2009-12-25 17:35:14.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/twe/twe.c 2012-08-03 04:00:49.000000000 0000 @@ -151,8 +151,11 @@ /* * Put command onto the freelist. */ + TWE_IO_LOCK(sc); twe_release_request(tr); + TWE_IO_UNLOCK(sc); } + TWE_IO_LOCK(sc); /* * Check status register for errors, clear them. @@ -164,6 +167,7 @@ * Wait for the controller to come ready. */ if (twe_wait_status(sc, TWE_STATUS_MICROCONTROLLER_READY, 60)) { + TWE_IO_UNLOCK(sc); twe_printf(sc, "microcontroller not ready\n"); return(ENXIO); } @@ -185,6 +189,7 @@ if (!twe_soft_reset(sc)) break; /* reset process complete */ } + TWE_IO_UNLOCK(sc); /* did we give up? */ if (i >= TWE_MAX_RESET_TRIES) { twe_printf(sc, "can't initialise controller, giving up\n"); @@ -203,14 +208,17 @@ TWE_Param *drives = NULL, *param = NULL; TWE_Array_Descriptor *ud; + TWE_CONFIG_ASSERT_LOCKED(sc); if (unit < 0 || unit > TWE_MAX_UNITS) return (EINVAL); /* * The controller is in a safe state, so try to find drives attached to it. */ + TWE_IO_LOCK(sc); if ((drives = twe_get_param(sc, TWE_PARAM_UNITSUMMARY, TWE_PARAM_UNITSUMMARY_Status, TWE_MAX_UNITS, NULL)) == NULL) { + TWE_IO_UNLOCK(sc); twe_printf(sc, "can't detect attached units\n"); return (EIO); } @@ -218,6 +226,7 @@ dr = &sc->twe_drive[unit]; /* check that the drive is online */ if (!(drives->data[unit] & TWE_PARAM_UNITSTATUS_Online)) { + TWE_IO_UNLOCK(sc); error = ENXIO; goto out; } @@ -225,21 +234,25 @@ table = TWE_PARAM_UNITINFO + unit; if (twe_get_param_4(sc, table, TWE_PARAM_UNITINFO_Capacity, &dr->td_size)) { + TWE_IO_UNLOCK(sc); twe_printf(sc, "error fetching capacity for unit %d\n", unit); error = EIO; goto out; } if (twe_get_param_1(sc, table, TWE_PARAM_UNITINFO_Status, &dr->td_state)) { + TWE_IO_UNLOCK(sc); twe_printf(sc, "error fetching state for unit %d\n", unit); error = EIO; goto out; } if (twe_get_param_2(sc, table, TWE_PARAM_UNITINFO_DescriptorSize, &dsize)) { + TWE_IO_UNLOCK(sc); twe_printf(sc, "error fetching descriptor size for unit %d\n", unit); error = EIO; goto out; } if ((param = twe_get_param(sc, table, TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL)) == NULL) { + TWE_IO_UNLOCK(sc); twe_printf(sc, "error fetching descriptor for unit %d\n", unit); error = EIO; goto out; @@ -258,6 +271,7 @@ } dr->td_cylinders = dr->td_size / (dr->td_heads * dr->td_sectors); dr->td_twe_unit = unit; + TWE_IO_UNLOCK(sc); error = twe_attach_drive(sc, dr); @@ -274,6 +288,7 @@ { int error; + TWE_CONFIG_ASSERT_LOCKED(sc); if (unit < 0 || unit >= TWE_MAX_UNITS) return (ENXIO); @@ -295,12 +310,15 @@ /* * Scan for drives */ + TWE_CONFIG_LOCK(sc); for (i = 0; i < TWE_MAX_UNITS; i++) twe_add_unit(sc, i); + TWE_CONFIG_UNLOCK(sc); /* * Initialise connection with controller. */ + TWE_IO_LOCK(sc); twe_init_connection(sc, TWE_INIT_MESSAGE_CREDITS); #ifdef TWE_SHUTDOWN_NOTIFICATION @@ -319,6 +337,7 @@ * Finally enable interrupts. */ twe_enable_interrupts(sc); + TWE_IO_UNLOCK(sc); } /******************************************************************************** @@ -330,6 +349,7 @@ /* * Mark the controller as shutting down, and disable any further interrupts. */ + TWE_IO_ASSERT_LOCKED(sc); sc->twe_state |= TWE_STATE_SHUTDOWN; twe_disable_interrupts(sc); @@ -385,6 +405,7 @@ debug_called(4); + TWE_IO_ASSERT_LOCKED(sc); if (sc->twe_state & (TWE_STATE_CTLR_BUSY | TWE_STATE_FRZN)) return; @@ -500,15 +521,32 @@ u_int16_t *aen_code = (u_int16_t *)addr; struct twe_request *tr; u_int8_t srid; - int s, error; + int error; + size_t tr_length; error = 0; switch(ioctlcmd) { /* handle a command from userspace */ case TWEIO_COMMAND: + /* + * if there's a data buffer, allocate and copy it in. + * Must be in multipled of 512 bytes. + */ + tr_length = roundup2(tu->tu_size, 512); + if (tr_length > 0) { + data = malloc(tr_length, M_DEVBUF, M_WAITOK); + error = copyin(tu->tu_data, data, tu->tu_size); + if (error) { + free(data, M_DEVBUF); + break; + } + } else + data = NULL; + /* get a request */ + TWE_IO_LOCK(sc); while (twe_get_request(sc, &tr)) - tsleep(sc, PPAUSE, "twioctl", hz); + mtx_sleep(sc, &sc->twe_io_lock, PPAUSE, "twioctl", hz); /* * Save the command's request ID, copy the user-supplied command in, @@ -519,23 +557,15 @@ bcopy(&tu->tu_command, cmd, sizeof(TWE_Command)); cmd->generic.request_id = srid; - /* - * if there's a data buffer, allocate and copy it in. - * Must be in multipled of 512 bytes. - */ - tr->tr_length = (tu->tu_size + 511) & ~511; + tr->tr_length = tr_length; + tr->tr_data = data; if (tr->tr_length > 0) { - if ((tr->tr_data = malloc(tr->tr_length, M_DEVBUF, M_WAITOK)) == NULL) { - error = ENOMEM; - goto cmd_done; - } - if ((error = copyin(tu->tu_data, tr->tr_data, tu->tu_size)) != 0) - goto cmd_done; tr->tr_flags |= TWE_CMD_DATAIN | TWE_CMD_DATAOUT; } /* run the command */ error = twe_wait_request(tr); + TWE_IO_UNLOCK(sc); if (error) goto cmd_done; @@ -550,8 +580,9 @@ /* free resources */ if (tr->tr_data != NULL) free(tr->tr_data, M_DEVBUF); - if (tr != NULL) - twe_release_request(tr); + TWE_IO_LOCK(sc); + twe_release_request(tr); + TWE_IO_UNLOCK(sc); break; @@ -564,7 +595,9 @@ case TWEQ_READY: case TWEQ_BUSY: case TWEQ_COMPLETE: + TWE_IO_LOCK(sc); bcopy(&sc->twe_qstat[ts->ts_item], &ts->ts_qstat, sizeof(struct twe_qstat)); + TWE_IO_UNLOCK(sc); break; #endif default: @@ -575,22 +608,28 @@ /* poll for an AEN */ case TWEIO_AEN_POLL: + TWE_IO_LOCK(sc); *aen_code = twe_dequeue_aen(sc); + TWE_IO_UNLOCK(sc); break; /* wait for another AEN to show up */ case TWEIO_AEN_WAIT: - s = splbio(); + TWE_IO_LOCK(sc); while ((*aen_code = twe_dequeue_aen(sc)) == TWE_AEN_QUEUE_EMPTY) { - error = tsleep(&sc->twe_aen_queue, PRIBIO | PCATCH, "tweaen", 0); + error = mtx_sleep(&sc->twe_aen_queue, &sc->twe_io_lock, PRIBIO | PCATCH, + "tweaen", 0); if (error == EINTR) break; } - splx(s); + TWE_IO_UNLOCK(sc); break; case TWEIO_GET_PARAM: - if ((param = twe_get_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, NULL)) == NULL) { + TWE_IO_LOCK(sc); + param = twe_get_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, NULL); + TWE_IO_UNLOCK(sc); + if (param == NULL) { twe_printf(sc, "TWEIO_GET_PARAM failed for 0x%x/0x%x/%d\n", tp->tp_table_id, tp->tp_param_id, tp->tp_size); error = EINVAL; @@ -607,26 +646,32 @@ break; case TWEIO_SET_PARAM: - if ((data = malloc(tp->tp_size, M_DEVBUF, M_WAITOK)) == NULL) { - error = ENOMEM; - } else { - error = copyin(tp->tp_data, data, tp->tp_size); - if (error == 0) - error = twe_set_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, data); - free(data, M_DEVBUF); + data = malloc(tp->tp_size, M_DEVBUF, M_WAITOK); + error = copyin(tp->tp_data, data, tp->tp_size); + if (error == 0) { + TWE_IO_LOCK(sc); + error = twe_set_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, data); + TWE_IO_UNLOCK(sc); } + free(data, M_DEVBUF); break; case TWEIO_RESET: + TWE_IO_LOCK(sc); twe_reset(sc); + TWE_IO_UNLOCK(sc); break; case TWEIO_ADD_UNIT: + TWE_CONFIG_LOCK(sc); error = twe_add_unit(sc, td->td_unit); + TWE_CONFIG_UNLOCK(sc); break; case TWEIO_DEL_UNIT: + TWE_CONFIG_LOCK(sc); error = twe_del_unit(sc, td->td_unit); + TWE_CONFIG_UNLOCK(sc); break; /* XXX implement ATA PASSTHROUGH */ @@ -724,6 +769,7 @@ debug_called(4); + TWE_IO_ASSERT_LOCKED(sc); tr = NULL; param = NULL; @@ -817,6 +863,7 @@ debug_called(4); + TWE_IO_ASSERT_LOCKED(sc); tr = NULL; param = NULL; error = ENOMEM; @@ -874,6 +921,8 @@ debug_called(4); + TWE_IO_ASSERT_LOCKED(sc); + /* get a command */ if (twe_get_request(sc, &tr)) return(0); @@ -903,18 +952,16 @@ static int twe_wait_request(struct twe_request *tr) { - int s; debug_called(4); + TWE_IO_ASSERT_LOCKED(tr->tr_sc); tr->tr_flags |= TWE_CMD_SLEEPER; tr->tr_status = TWE_CMD_BUSY; twe_enqueue_ready(tr); twe_startio(tr->tr_sc); - s = splbio(); while (tr->tr_status == TWE_CMD_BUSY) - tsleep(tr, PRIBIO, "twewait", 0); - splx(s); + mtx_sleep(tr, &tr->tr_sc->twe_io_lock, PRIBIO, "twewait", 0); return(tr->tr_status != TWE_CMD_COMPLETE); } @@ -991,12 +1038,12 @@ twe_reset(struct twe_softc *sc) { struct twe_request *tr; - int i, s; + int i; /* * Sleep for a short period to allow AENs to be signalled. */ - tsleep(sc, PRIBIO, "twereset", hz); + mtx_sleep(sc, &sc->twe_io_lock, PRIBIO, "twereset", hz); /* * Disable interrupts from the controller, and mask any accidental entry @@ -1004,7 +1051,6 @@ */ twe_printf(sc, "controller reset in progress...\n"); twe_disable_interrupts(sc); - s = splbio(); /* * Try to soft-reset the controller. @@ -1036,11 +1082,9 @@ * Kick the controller to start things going again, then re-enable interrupts. */ twe_startio(sc); - twe_enable_interrupts(sc); twe_printf(sc, "controller reset done, %d commands restarted\n", i); out: - splx(s); twe_enable_interrupts(sc); } @@ -1060,23 +1104,33 @@ { struct twe_softc *sc = tr->tr_sc; TWE_Command *cmd; - int i, s, done; +#if 0 + int i; +#endif u_int32_t status_reg; debug_called(4); + if (!dumping) + TWE_IO_ASSERT_LOCKED(sc); + /* mark the command as currently being processed */ tr->tr_status = TWE_CMD_BUSY; cmd = TWE_FIND_COMMAND(tr); +#if 0 /* * Spin briefly waiting for the controller to come ready * * XXX it might be more efficient to return EBUSY immediately * and let the command be rescheduled. + * + * XXX: This all seems very dubious now with locking. Completion + * interrupts can't run, so checking this more than once is + * pointless. */ - for (i = 100000, done = 0; (i > 0) && !done; i--) { - s = splbio(); + for (i = 100000; (i > 0); i--) { +#endif /* check to see if we can post a command */ status_reg = TWE_STATUS(sc); @@ -1086,7 +1140,7 @@ twe_enqueue_busy(tr); TWE_COMMAND_QUEUE(sc, TWE_FIND_COMMANDPHYS(tr)); - done = 1; + /* move command to work queue */ #ifdef TWE_DEBUG if (tr->tr_complete != NULL) { @@ -1097,13 +1151,11 @@ debug(3, "queued request %d for polling caller", cmd->generic.request_id); } #endif + return(0); } - splx(s); /* drop spl to allow completion interrupts */ +#if 0 } - - /* command is enqueued */ - if (done) - return(0); +#endif /* * We couldn't get the controller to take the command; try submitting it again later. @@ -1125,14 +1177,13 @@ TWE_Response_Queue rq; TWE_Command *cmd; struct twe_request *tr; - int s, found; + int found; u_int32_t status_reg; debug_called(5); /* loop collecting completed commands */ found = 0; - s = splbio(); for (;;) { status_reg = TWE_STATUS(sc); twe_check_bits(sc, status_reg); /* XXX should this fail? */ @@ -1155,7 +1206,6 @@ break; /* no response ready */ } } - splx(s); /* if we've completed any commands, try posting some more */ if (found) @@ -1259,6 +1309,7 @@ debug_called(2); + TWE_IO_ASSERT_LOCKED(sc); TWE_SOFT_RESET(sc); if (twe_wait_status(sc, TWE_STATUS_ATTENTION_INTERRUPT, 30)) { @@ -1396,6 +1447,7 @@ { u_int16_t aen; + TWE_IO_ASSERT_LOCKED(sc); for (;;) { if (twe_get_param_2(sc, TWE_PARAM_AEN, TWE_PARAM_AEN_UnitCode, &aen)) return(1); @@ -1417,14 +1469,14 @@ twe_enqueue_aen(struct twe_softc *sc, u_int16_t aen) { char *msg; - int s, next, nextnext; + int next, nextnext; debug_called(4); + TWE_IO_ASSERT_LOCKED(sc); if ((msg = twe_format_aen(sc, aen)) != NULL) twe_printf(sc, "AEN: <%s>\n", msg); - s = splbio(); /* enqueue the AEN */ next = ((sc->twe_aen_head + 1) % TWE_Q_LENGTH); nextnext = ((sc->twe_aen_head + 2) % TWE_Q_LENGTH); @@ -1447,7 +1499,6 @@ sc->twe_wait_aen = -1; wakeup(&sc->twe_wait_aen); } - splx(s); } /******************************************************************************** @@ -1462,6 +1513,7 @@ debug_called(4); + TWE_IO_ASSERT_LOCKED(sc); if (sc->twe_aen_tail == sc->twe_aen_head) { result = TWE_AEN_QUEUE_EMPTY; } else { @@ -1479,15 +1531,13 @@ static int twe_find_aen(struct twe_softc *sc, u_int16_t aen) { - int i, s, missing; + int i, missing; missing = 1; - s = splbio(); for (i = sc->twe_aen_tail; (i != sc->twe_aen_head) && missing; i = (i + 1) % TWE_Q_LENGTH) { if (sc->twe_aen_queue[i] == aen) missing = 0; } - splx(s); return(missing); } @@ -1504,22 +1554,20 @@ twe_wait_aen(struct twe_softc *sc, int aen, int timeout) { time_t expiry; - int found, s; + int found; debug_called(4); expiry = time_second + timeout; found = 0; - s = splbio(); sc->twe_wait_aen = aen; do { twe_fetch_aen(sc); - tsleep(&sc->twe_wait_aen, PZERO, "twewaen", hz); + mtx_sleep(&sc->twe_wait_aen, &sc->twe_io_lock, PZERO, "twewaen", hz); if (sc->twe_wait_aen == -1) found = 1; } while ((time_second <= expiry) && !found); - splx(s); return(!found); } #endif @@ -1541,6 +1589,9 @@ TWE_Command *cmd; debug_called(4); + if (!dumping) + TWE_IO_ASSERT_LOCKED(sc); + /* try to reuse an old buffer */ *tr = twe_dequeue_free(sc); @@ -1567,6 +1618,8 @@ { debug_called(4); + if (!dumping) + TWE_IO_ASSERT_LOCKED(tr->tr_sc); if (tr->tr_private != NULL) twe_panic(tr->tr_sc, "tr_private != NULL"); twe_enqueue_free(tr); @@ -1591,6 +1644,8 @@ debug_called(2); + TWE_IO_LOCK(sc); + /* get the port count */ twe_get_param_1(sc, TWE_PARAM_CONTROLLER, TWE_PARAM_CONTROLLER_PortCount, &ports); @@ -1641,6 +1696,7 @@ if (p[0]) free(p[0], M_DEVBUF); } + TWE_IO_UNLOCK(sc); } /******************************************************************************** @@ -1722,6 +1778,7 @@ static char * twe_format_aen(struct twe_softc *sc, u_int16_t aen) { + /* XXX: This should perhaps be in the softc. */ static char buf[80]; device_t child; char *code, *msg; --- //depot/vendor/freebsd/src/sys/dev/twe/twe_compat.h 2005-05-29 04:45:51.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/twe/twe_compat.h 2012-08-03 03:58:12.000000000 0000 @@ -43,8 +43,11 @@ #include #include #include +#include #include +#include #include +#include #include #include @@ -65,10 +68,10 @@ /* * Wrappers for bus-space actions */ -#define TWE_CONTROL(sc, val) bus_space_write_4((sc)->twe_btag, (sc)->twe_bhandle, 0x0, (u_int32_t)val) -#define TWE_STATUS(sc) (u_int32_t)bus_space_read_4((sc)->twe_btag, (sc)->twe_bhandle, 0x4) -#define TWE_COMMAND_QUEUE(sc, val) bus_space_write_4((sc)->twe_btag, (sc)->twe_bhandle, 0x8, (u_int32_t)val) -#define TWE_RESPONSE_QUEUE(sc) (TWE_Response_Queue)bus_space_read_4((sc)->twe_btag, (sc)->twe_bhandle, 0xc) +#define TWE_CONTROL(sc, val) bus_write_4((sc)->twe_io, 0x0, (u_int32_t)val) +#define TWE_STATUS(sc) (u_int32_t)bus_read_4((sc)->twe_io, 0x4) +#define TWE_COMMAND_QUEUE(sc, val) bus_write_4((sc)->twe_io, 0x8, (u_int32_t)val) +#define TWE_RESPONSE_QUEUE(sc) (TWE_Response_Queue)bus_read_4((sc)->twe_io, 0xc) /* * FreeBSD-specific softc elements @@ -79,8 +82,6 @@ device_t twe_dev; /* bus device */ \ struct cdev *twe_dev_t; /* control device */ \ struct resource *twe_io; /* register interface window */ \ - bus_space_handle_t twe_bhandle; /* bus space handle */ \ - bus_space_tag_t twe_btag; /* bus space tag */ \ bus_dma_tag_t twe_parent_dmat; /* parent DMA tag */ \ bus_dma_tag_t twe_buffer_dmat; /* data buffer DMA tag */ \ bus_dma_tag_t twe_cmd_dmat; /* command buffer DMA tag */ \ @@ -91,8 +92,8 @@ void *twe_cmd; /* command structures */ \ void *twe_immediate; /* immediate commands */ \ bus_dmamap_t twe_immediate_map; \ - struct sysctl_ctx_list sysctl_ctx; \ - struct sysctl_oid *sysctl_tree; + struct mtx twe_io_lock; \ + struct sx twe_config_lock; /* * FreeBSD-specific request elements @@ -107,31 +108,6 @@ #define twe_printf(sc, fmt, args...) device_printf(sc->twe_dev, fmt , ##args) #define twed_printf(twed, fmt, args...) device_printf(twed->twed_dev, fmt , ##args) -#if __FreeBSD_version < 500003 -# include -# define INTR_ENTROPY 0 -# define FREEBSD_4 - -# include /* old buf style */ -typedef struct buf twe_bio; -typedef struct buf_queue_head twe_bioq; -# define TWE_BIO_QINIT(bq) bufq_init(&bq); -# define TWE_BIO_QINSERT(bq, bp) bufq_insert_tail(&bq, bp) -# define TWE_BIO_QFIRST(bq) bufq_first(&bq) -# define TWE_BIO_QREMOVE(bq, bp) bufq_remove(&bq, bp) -# define TWE_BIO_IS_READ(bp) ((bp)->b_flags & B_READ) -# define TWE_BIO_DATA(bp) (bp)->b_data -# define TWE_BIO_LENGTH(bp) (bp)->b_bcount -# define TWE_BIO_LBA(bp) (bp)->b_pblkno -# define TWE_BIO_SOFTC(bp) (bp)->b_dev->si_drv1 -# define TWE_BIO_UNIT(bp) *(int *)((bp)->b_dev->si_drv2) -# define TWE_BIO_SET_ERROR(bp, err) do { (bp)->b_error = err; (bp)->b_flags |= B_ERROR;} while(0) -# define TWE_BIO_HAS_ERROR(bp) ((bp)->b_flags & B_ERROR) -# define TWE_BIO_RESID(bp) (bp)->b_resid -# define TWE_BIO_DONE(bp) biodone(bp) -# define TWE_BIO_STATS_START(bp) devstat_start_transaction(&((struct twed_softc *)TWE_BIO_SOFTC(bp))->twed_stats) -# define TWE_BIO_STATS_END(bp) devstat_end_transaction_buf(&((struct twed_softc *)TWE_BIO_SOFTC(bp))->twed_stats, bp) -#else # include # include typedef struct bio twe_bio; @@ -152,7 +128,13 @@ # define TWE_BIO_DONE(bp) biodone(bp) # define TWE_BIO_STATS_START(bp) # define TWE_BIO_STATS_END(bp) -#endif + +#define TWE_IO_LOCK(sc) mtx_lock(&(sc)->twe_io_lock) +#define TWE_IO_UNLOCK(sc) mtx_unlock(&(sc)->twe_io_lock) +#define TWE_IO_ASSERT_LOCKED(sc) mtx_assert(&(sc)->twe_io_lock, MA_OWNED) +#define TWE_CONFIG_LOCK(sc) sx_xlock(&(sc)->twe_config_lock) +#define TWE_CONFIG_UNLOCK(sc) sx_xunlock(&(sc)->twe_config_lock) +#define TWE_CONFIG_ASSERT_LOCKED(sc) sx_assert(&(sc)->twe_config_lock, SA_XLOCKED) #endif /* FreeBSD */ --- //depot/vendor/freebsd/src/sys/dev/twe/twe_freebsd.c 2012-03-12 08:05:24.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/twe/twe_freebsd.c 2012-08-10 14:04:10.000000000 0000 @@ -69,7 +69,6 @@ static struct cdevsw twe_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = twe_open, .d_close = twe_close, .d_ioctl = twe_ioctl_wrapper, @@ -84,7 +83,13 @@ { struct twe_softc *sc = (struct twe_softc *)dev->si_drv1; + TWE_IO_LOCK(sc); + if (sc->twe_state & TWE_STATE_DETACHING) { + TWE_IO_UNLOCK(sc); + return (ENXIO); + } sc->twe_state |= TWE_STATE_OPEN; + TWE_IO_UNLOCK(sc); return(0); } @@ -96,7 +101,9 @@ { struct twe_softc *sc = (struct twe_softc *)dev->si_drv1; + TWE_IO_LOCK(sc); sc->twe_state &= ~TWE_STATE_OPEN; + TWE_IO_UNLOCK(sc); return (0); } @@ -172,8 +179,8 @@ twe_attach(device_t dev) { struct twe_softc *sc; + struct sysctl_oid *sysctl_tree; int rid, error; - u_int32_t command; debug_called(4); @@ -182,32 +189,24 @@ */ sc = device_get_softc(dev); sc->twe_dev = dev; + mtx_init(&sc->twe_io_lock, "twe I/O", NULL, MTX_DEF); + sx_init(&sc->twe_config_lock, "twe config"); - sysctl_ctx_init(&sc->sysctl_ctx); - sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, + sysctl_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev), SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, device_get_nameunit(dev), CTLFLAG_RD, 0, ""); - if (sc->sysctl_tree == NULL) { + if (sysctl_tree == NULL) { twe_printf(sc, "cannot add sysctl tree node\n"); return (ENXIO); } - SYSCTL_ADD_STRING(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), + SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "driver_version", CTLFLAG_RD, TWE_DRIVER_VERSION_STRING, 0, "TWE driver version"); /* - * Make sure we are going to be able to talk to this board. - */ - command = pci_read_config(dev, PCIR_COMMAND, 2); - if ((command & PCIM_CMD_PORTEN) == 0) { - twe_printf(sc, "register window not available\n"); - return(ENXIO); - } - /* * Force the busmaster enable bit on, in case the BIOS forgot. */ - command |= PCIM_CMD_BUSMASTEREN; - pci_write_config(dev, PCIR_COMMAND, command, 2); + pci_enable_busmaster(dev); /* * Allocate the PCI register window. @@ -219,8 +218,6 @@ twe_free(sc); return(ENXIO); } - sc->twe_btag = rman_get_bustag(sc->twe_io); - sc->twe_bhandle = rman_get_bushandle(sc->twe_io); /* * Allocate the parent bus DMA tag appropriate for PCI. @@ -251,7 +248,7 @@ twe_free(sc); return(ENXIO); } - if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY, + if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, NULL, twe_pci_intr, sc, &sc->twe_intr)) { twe_printf(sc, "can't set up interrupt\n"); twe_free(sc); @@ -302,7 +299,7 @@ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ busdma_lock_mutex, /* lockfunc */ - &Giant, /* lockarg */ + &sc->twe_io_lock, /* lockarg */ &sc->twe_buffer_dmat)) { twe_printf(sc, "can't allocate data buffer DMA tag\n"); twe_free(sc); @@ -424,7 +421,8 @@ if (sc->twe_dev_t != (struct cdev *)NULL) destroy_dev(sc->twe_dev_t); - sysctl_ctx_free(&sc->sysctl_ctx); + sx_destroy(&sc->twe_config_lock); + mtx_destroy(&sc->twe_io_lock); } /******************************************************************************** @@ -434,27 +432,30 @@ twe_detach(device_t dev) { struct twe_softc *sc = device_get_softc(dev); - int s, error; debug_called(4); - error = EBUSY; - s = splbio(); - if (sc->twe_state & TWE_STATE_OPEN) - goto out; + TWE_IO_LOCK(sc); + if (sc->twe_state & TWE_STATE_OPEN) { + TWE_IO_UNLOCK(sc); + return (EBUSY); + } + sc->twe_state |= TWE_STATE_DETACHING; + TWE_IO_UNLOCK(sc); /* * Shut the controller down. */ - if (twe_shutdown(dev)) - goto out; + if (twe_shutdown(dev)) { + TWE_IO_LOCK(sc); + sc->twe_state &= ~TWE_STATE_DETACHING; + TWE_IO_UNLOCK(sc); + return (EBUSY); + } twe_free(sc); - error = 0; - out: - splx(s); - return(error); + return(0); } /******************************************************************************** @@ -467,30 +468,32 @@ twe_shutdown(device_t dev) { struct twe_softc *sc = device_get_softc(dev); - int i, s, error = 0; + int i, error = 0; debug_called(4); - s = splbio(); - /* * Delete all our child devices. */ + TWE_CONFIG_LOCK(sc); for (i = 0; i < TWE_MAX_UNITS; i++) { if (sc->twe_drive[i].td_disk != 0) { - if ((error = twe_detach_drive(sc, i)) != 0) - goto out; + if ((error = twe_detach_drive(sc, i)) != 0) { + TWE_CONFIG_UNLOCK(sc); + return (error); + } } } + TWE_CONFIG_UNLOCK(sc); /* * Bring the controller down. */ + TWE_IO_LOCK(sc); twe_deinit(sc); + TWE_IO_UNLOCK(sc); -out: - splx(s); - return(error); + return(0); } /******************************************************************************** @@ -500,15 +503,14 @@ twe_suspend(device_t dev) { struct twe_softc *sc = device_get_softc(dev); - int s; debug_called(4); - s = splbio(); + TWE_IO_LOCK(sc); sc->twe_state |= TWE_STATE_SUSPEND; twe_disable_interrupts(sc); - splx(s); + TWE_IO_UNLOCK(sc); return(0); } @@ -523,8 +525,10 @@ debug_called(4); + TWE_IO_LOCK(sc); sc->twe_state &= ~TWE_STATE_SUSPEND; twe_enable_interrupts(sc); + TWE_IO_UNLOCK(sc); return(0); } @@ -536,7 +540,11 @@ static void twe_pci_intr(void *arg) { - twe_intr((struct twe_softc *)arg); + struct twe_softc *sc = arg; + + TWE_IO_LOCK(sc); + twe_intr(sc); + TWE_IO_UNLOCK(sc); } /******************************************************************************** @@ -565,8 +573,10 @@ char buf[80]; int error; + mtx_lock(&Giant); dr->td_disk = device_add_child(sc->twe_dev, NULL, -1); if (dr->td_disk == NULL) { + mtx_unlock(&Giant); twe_printf(sc, "Cannot add unit\n"); return (EIO); } @@ -582,7 +592,9 @@ twe_describe_code(twe_table_unitstate, dr->td_state & TWE_PARAM_UNITSTATUS_MASK)); device_set_desc_copy(dr->td_disk, buf); - if ((error = bus_generic_attach(sc->twe_dev)) != 0) { + error = device_probe_and_attach(dr->td_disk); + mtx_unlock(&Giant); + if (error != 0) { twe_printf(sc, "Cannot attach unit to controller. error = %d\n", error); return (EIO); } @@ -599,7 +611,11 @@ { int error = 0; - if ((error = device_delete_child(sc->twe_dev, sc->twe_drive[unit].td_disk)) != 0) { + TWE_CONFIG_ASSERT_LOCKED(sc); + mtx_lock(&Giant); + error = device_delete_child(sc->twe_dev, sc->twe_drive[unit].td_disk); + mtx_unlock(&Giant); + if (error != 0) { twe_printf(sc, "failed to delete unit %d\n", unit); return(error); } @@ -671,10 +687,6 @@ * Disk device control interface. */ -#ifdef FREEBSD_4 -static int disks_registered = 0; -#endif - /******************************************************************************** * Handle open from generic layer. * @@ -724,10 +736,12 @@ TWE_BIO_STATS_START(bp); /* queue the bio on the controller */ + TWE_IO_LOCK(sc->twed_controller); twe_enqueue_bio(sc->twed_controller, bp); /* poke the controller to start I/O */ twe_startio(sc->twed_controller); + TWE_IO_UNLOCK(sc->twed_controller); return; } @@ -827,14 +841,9 @@ sc->twed_disk->d_fwsectors = sc->twed_drive->td_sectors; sc->twed_disk->d_fwheads = sc->twed_drive->td_heads; sc->twed_disk->d_unit = sc->twed_drive->td_sys_unit; - sc->twed_disk->d_flags = DISKFLAG_NEEDSGIANT; disk_create(sc->twed_disk, DISK_VERSION); -#ifdef FREEBSD_4 - disks_registered++; -#endif - /* set the maximum I/O size to the theoretical maximum allowed by the S/G list size */ return (0); @@ -855,10 +864,6 @@ disk_destroy(sc->twed_disk); -#ifdef FREEBSD_4 - if (--disks_registered == 0) - cdevsw_remove(&tweddisk_cdevsw); -#endif return(0); } @@ -878,11 +883,7 @@ { struct twe_request *tr; - if ((tr = malloc(sizeof(struct twe_request), TWE_MALLOC_CLASS, M_WAITOK)) == NULL) { - twe_printf(sc, "unable to allocate memory for tag %d\n", tag); - return(NULL); - } - bzero(tr, sizeof(*tr)); + tr = malloc(sizeof(struct twe_request), TWE_MALLOC_CLASS, M_WAITOK | M_ZERO); tr->tr_sc = sc; tr->tr_tag = tag; if (bus_dmamap_create(sc->twe_buffer_dmat, 0, &tr->tr_dmamap)) { @@ -1044,6 +1045,8 @@ debug_called(4); + if (!dumping) + TWE_IO_ASSERT_LOCKED(sc); if (sc->twe_state & (TWE_STATE_CTLR_BUSY | TWE_STATE_FRZN)) { twe_requeue_ready(tr); return (EBUSY); @@ -1101,6 +1104,8 @@ debug_called(4); + if (!dumping) + TWE_IO_ASSERT_LOCKED(sc); bus_dmamap_sync(sc->twe_cmd_dmat, sc->twe_cmdmap, BUS_DMASYNC_POSTWRITE); /* @@ -1153,12 +1158,10 @@ twe_report(void) { struct twe_softc *sc; - int i, s; + int i; - s = splbio(); for (i = 0; (sc = devclass_get_softc(twe_devclass, i)) != NULL; i++) twe_print_controller(sc); printf("twed: total bio count in %u out %u\n", twed_bio_in, twed_bio_out); - splx(s); } #endif --- //depot/vendor/freebsd/src/sys/dev/twe/twevar.h 2009-12-25 17:35:14.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/twe/twevar.h 2012-08-03 04:00:49.000000000 0000 @@ -134,6 +134,7 @@ #define TWE_STATE_SUSPEND (1<<3) /* controller is suspended */ #define TWE_STATE_FRZN (1<<4) /* got EINPROGRESS */ #define TWE_STATE_CTLR_BUSY (1<<5) /* controller cmd queue full */ +#define TWE_STATE_DETACHING (1<<6) /* controller is being shut down */ int twe_host_id; struct twe_qstat twe_qstat[TWEQ_COUNT]; /* queue statistics */ @@ -209,46 +210,31 @@ static __inline void \ twe_enqueue_ ## name (struct twe_request *tr) \ { \ - int s; \ - \ - s = splbio(); \ TAILQ_INSERT_TAIL(&tr->tr_sc->twe_ ## name, tr, tr_link); \ TWEQ_ADD(tr->tr_sc, index); \ - splx(s); \ } \ static __inline void \ twe_requeue_ ## name (struct twe_request *tr) \ { \ - int s; \ - \ - s = splbio(); \ TAILQ_INSERT_HEAD(&tr->tr_sc->twe_ ## name, tr, tr_link); \ TWEQ_ADD(tr->tr_sc, index); \ - splx(s); \ } \ static __inline struct twe_request * \ twe_dequeue_ ## name (struct twe_softc *sc) \ { \ struct twe_request *tr; \ - int s; \ \ - s = splbio(); \ if ((tr = TAILQ_FIRST(&sc->twe_ ## name)) != NULL) { \ TAILQ_REMOVE(&sc->twe_ ## name, tr, tr_link); \ TWEQ_REMOVE(sc, index); \ } \ - splx(s); \ return(tr); \ } \ static __inline void \ twe_remove_ ## name (struct twe_request *tr) \ { \ - int s; \ - \ - s = splbio(); \ TAILQ_REMOVE(&tr->tr_sc->twe_ ## name, tr, tr_link); \ TWEQ_REMOVE(tr->tr_sc, index); \ - splx(s); \ } TWEQ_REQUEST_QUEUE(free, TWEQ_FREE) @@ -269,25 +255,18 @@ static __inline void twe_enqueue_bio(struct twe_softc *sc, twe_bio *bp) { - int s; - - s = splbio(); TWE_BIO_QINSERT(sc->twe_bioq, bp); TWEQ_ADD(sc, TWEQ_BIO); - splx(s); } static __inline twe_bio * twe_dequeue_bio(struct twe_softc *sc) { - int s; twe_bio *bp; - s = splbio(); if ((bp = TWE_BIO_QFIRST(sc->twe_bioq)) != NULL) { TWE_BIO_QREMOVE(sc->twe_bioq, bp); TWEQ_REMOVE(sc, TWEQ_BIO); } - splx(s); return(bp); }