--- //depot/vendor/freebsd/src/sys/dev/mlx/mlx.c 2012-02-27 16:15:16.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/mlx/mlx.c 2012-08-16 18:12:35.000000000 0000 @@ -32,8 +32,11 @@ #include #include +#include #include +#include #include +#include #include #include @@ -53,7 +56,6 @@ static struct cdevsw mlx_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = mlx_open, .d_close = mlx_close, .d_ioctl = mlx_ioctl, @@ -68,17 +70,17 @@ static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); static void mlx_v3_intaction(struct mlx_softc *sc, int action); -static int mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); +static int mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first); static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); static void mlx_v4_intaction(struct mlx_softc *sc, int action); -static int mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); +static int mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first); static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); static void mlx_v5_intaction(struct mlx_softc *sc, int action); -static int mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); +static int mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first); /* * Status monitoring @@ -130,8 +132,9 @@ bus_dma_segment_t *segs, int nsegments, int error); static void mlx_unmapcmd(struct mlx_command *mc); +static int mlx_shutdown_locked(struct mlx_softc *sc); static int mlx_start(struct mlx_command *mc); -static int mlx_done(struct mlx_softc *sc); +static int mlx_done(struct mlx_softc *sc, int startio); static void mlx_complete(struct mlx_softc *sc); /* @@ -164,14 +167,24 @@ debug_called(1); + /* destroy control device */ + if (sc->mlx_dev_t != NULL) + destroy_dev(sc->mlx_dev_t); + + if (sc->mlx_intr) + bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr); + /* cancel status timeout */ - untimeout(mlx_periodic, sc, sc->mlx_timeout); + MLX_IO_LOCK(sc); + callout_stop(&sc->mlx_timeout); /* throw away any command buffers */ while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) { TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); mlx_freecmd(mc); } + MLX_IO_UNLOCK(sc); + callout_drain(&sc->mlx_timeout); /* destroy data-transfer DMA tag */ if (sc->mlx_buffer_dmat) @@ -184,8 +197,6 @@ bus_dma_tag_destroy(sc->mlx_sg_dmat); /* disconnect the interrupt handler */ - if (sc->mlx_intr) - bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr); if (sc->mlx_irq != NULL) bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq); @@ -201,9 +212,8 @@ if (sc->mlx_enq2 != NULL) free(sc->mlx_enq2, M_DEVBUF); - /* destroy control device */ - if (sc->mlx_dev_t != (struct cdev *)NULL) - destroy_dev(sc->mlx_dev_t); + sx_destroy(&sc->mlx_config_lock); + mtx_destroy(&sc->mlx_io_lock); } /******************************************************************************** @@ -327,7 +337,9 @@ } /* disable interrupts before we start talking to the controller */ + MLX_IO_LOCK(sc); sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); + MLX_IO_UNLOCK(sc); /* * Wait for the controller to come ready, handshake with the firmware if required. @@ -336,7 +348,8 @@ */ hsmsg = 0; DELAY(1000); - while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2)) != 0) { + while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2, + hsmsg == 0)) != 0) { /* report first time around... */ if (hsmsg == 0) { device_printf(sc->mlx_dev, "controller initialisation in progress...\n"); @@ -364,7 +377,8 @@ device_printf(sc->mlx_dev, "can't allocate interrupt\n"); return(ENXIO); } - error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO | INTR_ENTROPY, NULL, mlx_intr, sc, &sc->mlx_intr); + error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO | + INTR_ENTROPY | INTR_MPSAFE, NULL, mlx_intr, sc, &sc->mlx_intr); if (error) { device_printf(sc->mlx_dev, "can't set up interrupt\n"); return(ENXIO); @@ -382,7 +396,7 @@ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 0, /* flags */ busdma_lock_mutex, /* lockfunc */ - &Giant, /* lockarg */ + &sc->mlx_io_lock, /* lockarg */ &sc->mlx_buffer_dmat); if (error != 0) { device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n"); @@ -407,7 +421,9 @@ /* * Obtain controller feature information */ + MLX_IO_LOCK(sc); if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) { + MLX_IO_UNLOCK(sc); device_printf(sc->mlx_dev, "ENQUIRY2 failed\n"); return(ENXIO); } @@ -420,6 +436,7 @@ case MLX_IFTYPE_2: /* These controllers don't report the firmware version in the ENQUIRY2 response */ if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) { + MLX_IO_UNLOCK(sc); device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n"); return(ENXIO); } @@ -453,8 +470,10 @@ } break; default: + MLX_IO_UNLOCK(sc); return(ENXIO); /* should never happen */ } + MLX_IO_UNLOCK(sc); /* * Create the final scatter/gather mappings now that we have characterised the controller. @@ -481,7 +500,7 @@ /* * Start the timeout routine. */ - sc->mlx_timeout = timeout(mlx_periodic, sc, hz); + callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc); /* print a little information about the controller */ mlx_describe_controller(sc); @@ -505,13 +524,16 @@ * Scan all the system drives and attach children for those that * don't currently have them. */ + MLX_IO_LOCK(sc); mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL); + MLX_IO_UNLOCK(sc); if (mes == NULL) { device_printf(sc->mlx_dev, "error fetching drive status\n"); return; } /* iterate over drives returned */ + MLX_CONFIG_LOCK(sc); for (i = 0, dr = &sc->mlx_sysdrive[0]; (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff); i++, dr++) { @@ -543,10 +565,13 @@ device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error); /* mark controller back up */ + MLX_IO_LOCK(sc); sc->mlx_state &= ~MLX_STATE_SHUTDOWN; /* enable interrupts */ sc->mlx_intaction(sc, MLX_INTACTION_ENABLE); + MLX_IO_UNLOCK(sc); + MLX_CONFIG_UNLOCK(sc); } /******************************************************************************** @@ -557,12 +582,12 @@ { struct mlx_softc *sc = device_get_softc(dev); struct mlxd_softc *mlxd; - int i, s, error; + int i, error; debug_called(1); error = EBUSY; - s = splbio(); + MLX_CONFIG_LOCK(sc); if (sc->mlx_state & MLX_STATE_OPEN) goto out; @@ -577,12 +602,13 @@ } if ((error = mlx_shutdown(dev))) goto out; + MLX_CONFIG_UNLOCK(sc); mlx_free(sc); - error = 0; + return (0); out: - splx(s); + MLX_CONFIG_UNLOCK(sc); return(error); } @@ -600,13 +626,24 @@ mlx_shutdown(device_t dev) { struct mlx_softc *sc = device_get_softc(dev); - int i, s, error; + int error; + + MLX_CONFIG_LOCK(sc); + error = mlx_shutdown_locked(sc); + MLX_CONFIG_UNLOCK(sc); + return (error); +} + +static int +mlx_shutdown_locked(struct mlx_softc *sc) +{ + int i, error; debug_called(1); - s = splbio(); - error = 0; + MLX_CONFIG_ASSERT_LOCKED(sc); + MLX_IO_LOCK(sc); sc->mlx_state |= MLX_STATE_SHUTDOWN; sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); @@ -617,19 +654,18 @@ } else { printf("done\n"); } + MLX_IO_UNLOCK(sc); /* delete all our child devices */ for (i = 0; i < MLX_MAXDRIVES; i++) { if (sc->mlx_sysdrive[i].ms_disk != 0) { if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0) - goto out; + return (error); sc->mlx_sysdrive[i].ms_disk = 0; } } - out: - splx(s); - return(error); + return (0); } /******************************************************************************** @@ -639,11 +675,10 @@ mlx_suspend(device_t dev) { struct mlx_softc *sc = device_get_softc(dev); - int s; debug_called(1); - s = splbio(); + MLX_IO_LOCK(sc); sc->mlx_state |= MLX_STATE_SUSPEND; /* flush controller */ @@ -651,7 +686,7 @@ printf("%s\n", mlx_flush(sc) ? "failed" : "done"); sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); - splx(s); + MLX_IO_UNLOCK(sc); return(0); } @@ -666,8 +701,10 @@ debug_called(1); + MLX_IO_LOCK(sc); sc->mlx_state &= ~MLX_STATE_SUSPEND; sc->mlx_intaction(sc, MLX_INTACTION_ENABLE); + MLX_IO_UNLOCK(sc); return(0); } @@ -684,7 +721,9 @@ debug_called(1); /* collect finished commands, queue anything waiting */ - mlx_done(sc); + MLX_IO_LOCK(sc); + mlx_done(sc, 1); + MLX_IO_UNLOCK(sc); }; /******************************************************************************* @@ -694,14 +733,12 @@ int mlx_submit_buf(struct mlx_softc *sc, mlx_bio *bp) { - int s; debug_called(1); - s = splbio(); + MLX_IO_ASSERT_LOCKED(sc); MLX_BIO_QINSERT(sc->mlx_bioq, bp); sc->mlx_waitbufs++; - splx(s); mlx_startio(sc); return(0); } @@ -714,7 +751,11 @@ { struct mlx_softc *sc = dev->si_drv1; + MLX_CONFIG_LOCK(sc); + MLX_IO_LOCK(sc); sc->mlx_state |= MLX_STATE_OPEN; + MLX_IO_UNLOCK(sc); + MLX_CONFIG_UNLOCK(sc); return(0); } @@ -726,7 +767,11 @@ { struct mlx_softc *sc = dev->si_drv1; + MLX_CONFIG_LOCK(sc); + MLX_IO_LOCK(sc); sc->mlx_state &= ~MLX_STATE_OPEN; + MLX_IO_UNLOCK(sc); + MLX_CONFIG_UNLOCK(sc); return (0); } @@ -753,12 +798,14 @@ */ case MLX_NEXT_CHILD: /* search system drives */ + MLX_CONFIG_LOCK(sc); for (i = 0; i < MLX_MAXDRIVES; i++) { /* is this one attached? */ if (sc->mlx_sysdrive[i].ms_disk != 0) { /* looking for the next one we come across? */ if (*arg == -1) { *arg = device_get_unit(sc->mlx_sysdrive[i].ms_disk); + MLX_CONFIG_UNLOCK(sc); return(0); } /* we want the one after this one */ @@ -766,13 +813,16 @@ *arg = -1; } } + MLX_CONFIG_UNLOCK(sc); return(ENOENT); /* * Scan the controller to see whether new drives have appeared. */ case MLX_RESCAN_DRIVES: + mtx_lock(&Giant); mlx_startup(sc); + mtx_unlock(&Giant); return(0); /* @@ -780,10 +830,12 @@ * away. */ case MLX_DETACH_DRIVE: /* detach one drive */ - + MLX_CONFIG_LOCK(sc); if (((dr = mlx_findunit(sc, *arg)) == NULL) || - ((mlxd = device_get_softc(dr->ms_disk)) == NULL)) + ((mlxd = device_get_softc(dr->ms_disk)) == NULL)) { + MLX_CONFIG_UNLOCK(sc); return(ENOENT); + } device_printf(dr->ms_disk, "detaching..."); error = 0; @@ -793,10 +845,13 @@ } /* flush controller */ + MLX_IO_LOCK(sc); if (mlx_flush(sc)) { + MLX_IO_UNLOCK(sc); error = EBUSY; goto detach_out; } + MLX_IO_UNLOCK(sc); /* nuke drive */ if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0) @@ -804,6 +859,7 @@ dr->ms_disk = 0; detach_out: + MLX_CONFIG_UNLOCK(sc); if (error) { printf("failed\n"); } else { @@ -823,28 +879,33 @@ if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS)) return(EOPNOTSUPP); + /* check time values */ mp = (struct mlx_pause *)addr; + if ((mp->mp_when < 0) || (mp->mp_when > 3600)) + return(EINVAL); + if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30))) + return(EINVAL); + + MLX_IO_LOCK(sc); if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) { /* cancel a pending pause operation */ sc->mlx_pause.mp_which = 0; } else { /* fix for legal channels */ mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1); - /* check time values */ - if ((mp->mp_when < 0) || (mp->mp_when > 3600)) - return(EINVAL); - if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30))) - return(EINVAL); /* check for a pause currently running */ - if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0)) + if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0)) { + MLX_IO_UNLOCK(sc); return(EBUSY); + } /* looks ok, go with it */ sc->mlx_pause.mp_which = mp->mp_which; sc->mlx_pause.mp_when = time_second + mp->mp_when; sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong; } + MLX_IO_UNLOCK(sc); return(0); /* @@ -857,7 +918,9 @@ * Start a rebuild on a given SCSI disk */ case MLX_REBUILDASYNC: + MLX_IO_LOCK(sc); if (sc->mlx_background != 0) { + MLX_IO_UNLOCK(sc); rb->rr_status = 0x0106; return(EBUSY); } @@ -887,13 +950,16 @@ } if (error == 0) sc->mlx_background = MLX_BACKGROUND_REBUILD; + MLX_IO_UNLOCK(sc); return(error); /* * Get the status of the current rebuild or consistency check. */ case MLX_REBUILDSTAT: + MLX_IO_LOCK(sc); *rs = sc->mlx_rebuildstat; + MLX_IO_UNLOCK(sc); return(0); /* @@ -902,12 +968,16 @@ */ case MLX_GET_SYSDRIVE: error = ENOENT; + MLX_CONFIG_LOCK(sc); + mtx_lock(&Giant); mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg); + mtx_unlock(&Giant); if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) && (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) { error = 0; *arg = mlxd->mlxd_drive - sc->mlx_sysdrive; } + MLX_CONFIG_UNLOCK(sc); return(error); default: @@ -930,14 +1000,18 @@ * Return the current status of this drive. */ case MLXD_STATUS: + MLX_IO_LOCK(sc); *arg = drive->ms_state; + MLX_IO_UNLOCK(sc); return(0); /* * Start a background consistency check on this drive. */ case MLXD_CHECKASYNC: /* start a background consistency check */ + MLX_IO_LOCK(sc); if (sc->mlx_background != 0) { + MLX_IO_UNLOCK(sc); *arg = 0x0106; return(EBUSY); } @@ -964,6 +1038,7 @@ } if (error == 0) sc->mlx_background = MLX_BACKGROUND_CHECK; + MLX_IO_UNLOCK(sc); *arg = result; return(error); @@ -987,6 +1062,7 @@ struct mlx_softc *sc = (struct mlx_softc *)data; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); /* * Run a bus pause? @@ -1045,10 +1121,10 @@ mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild); /* deal with possibly-missed interrupts and timed-out commands */ - mlx_done(sc); + mlx_done(sc, 1); /* reschedule another poll next second or so */ - sc->mlx_timeout = timeout(mlx_periodic, sc, hz); + callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc); } /******************************************************************************** @@ -1060,6 +1136,7 @@ struct mlx_softc *sc = mc->mc_sc; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); /* Command completed OK? */ if (mc->mc_status != 0) { @@ -1124,7 +1201,7 @@ debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent); /* mark the event log as busy */ - atomic_set_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY); + sc->mlx_flags |= MLX_EVENTLOG_BUSY; /* drain new eventlog entries */ mlx_periodic_eventlog_poll(sc); @@ -1205,6 +1282,7 @@ int error = 0; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); /* get ourselves a command buffer */ error = 1; @@ -1263,6 +1341,7 @@ char *reason; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); sc->mlx_lastevent++; /* next message... */ if (mc->mc_status == 0) { @@ -1321,7 +1400,7 @@ mlx_periodic_eventlog_poll(sc); } else { /* clear log-busy status */ - atomic_clear_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY); + sc->mlx_flags &= ~MLX_EVENTLOG_BUSY; } } @@ -1334,6 +1413,7 @@ struct mlx_softc *sc = mc->mc_sc; struct mlx_rebuild_status *mr = (struct mlx_rebuild_status *)mc->mc_data; + MLX_IO_ASSERT_LOCKED(sc); switch(mc->mc_status) { case 0: /* operation running, update stats */ sc->mlx_rebuildstat = *mr; @@ -1384,6 +1464,8 @@ struct mlx_command *mc; int failsafe, i, command; + MLX_IO_ASSERT_LOCKED(sc); + /* What are we doing here? */ if (sc->mlx_pause.mp_when == 0) { command = MLX_CMD_STARTCHANNEL; @@ -1440,7 +1522,8 @@ struct mlx_softc *sc = mc->mc_sc; int command = mc->mc_mailbox[0]; int channel = mc->mc_mailbox[2] & 0xf; - + + MLX_IO_ASSERT_LOCKED(sc); if (mc->mc_status != 0) { device_printf(sc->mlx_dev, "%s command failed - %s\n", command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc)); @@ -1509,6 +1592,7 @@ int error; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); /* get ourselves a command buffer */ error = 1; @@ -1562,6 +1646,7 @@ int error; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); /* get ourselves a command buffer */ error = 1; @@ -1604,6 +1689,7 @@ int error; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); /* get ourselves a command buffer */ error = 0x10000; @@ -1647,6 +1733,7 @@ int error; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); /* get ourselves a command buffer */ error = 0x10000; @@ -1689,6 +1776,7 @@ int error, count; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); mc->mc_complete = NULL; mc->mc_private = mc; /* wake us when you're done */ @@ -1698,7 +1786,7 @@ count = 0; /* XXX better timeout? */ while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) { - tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz); + mtx_sleep(mc->mc_private, &sc->mlx_io_lock, PRIBIO | PCATCH, "mlxwcmd", hz); } if (mc->mc_status != 0) { @@ -1720,9 +1808,10 @@ mlx_poll_command(struct mlx_command *mc) { struct mlx_softc *sc = mc->mc_sc; - int error, count, s; + int error, count; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); mc->mc_complete = NULL; mc->mc_private = NULL; /* we will poll for it */ @@ -1732,13 +1821,11 @@ count = 0; do { /* poll for completion */ - mlx_done(mc->mc_sc); + mlx_done(mc->mc_sc, 1); } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000)); if (mc->mc_status != MLX_STATUS_BUSY) { - s = splbio(); TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); - splx(s); return(0); } device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc)); @@ -1809,30 +1896,27 @@ mc->mc_status = MLX_STATUS_WEDGED; mlx_completeio(mc); } + + sc->mlx_state &= ~MLX_STATE_QFROZEN; } /******************************************************************************** * Pull as much work off the softc's work queue as possible and give it to the * controller. Leave a couple of slots free for emergencies. - * - * Must be called at splbio or in an equivalent fashion that prevents - * reentry or activity on the bioq. */ static void mlx_startio(struct mlx_softc *sc) { struct mlx_command *mc; mlx_bio *bp; - int s; int error; - /* avoid reentrancy */ - if (mlx_lock_tas(sc, MLX_LOCK_STARTING)) - return; + MLX_IO_ASSERT_LOCKED(sc); /* spin until something prevents us from doing any work */ - s = splbio(); for (;;) { + if (sc->mlx_state & MLX_STATE_QFROZEN) + break; /* see if there's work to be done */ if ((bp = MLX_BIO_QFIRST(sc->mlx_bioq)) == NULL) @@ -1848,7 +1932,6 @@ /* get the buf containing our work */ MLX_BIO_QREMOVE(sc->mlx_bioq, bp); sc->mlx_waitbufs--; - splx(s); /* connect the buf to the command */ mc->mc_complete = mlx_completeio; @@ -1859,14 +1942,11 @@ /* map the command so the controller can work with it */ error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length, mlx_startio_cb, mc, 0); - if (error == EINPROGRESS) { - break; + if (error == EINPROGRESS) { + sc->mlx_state |= MLX_STATE_QFROZEN; + break; } - - s = splbio(); } - splx(s); - mlx_lock_clr(sc, MLX_LOCK_STARTING); } /******************************************************************************** @@ -1878,7 +1958,8 @@ struct mlx_softc *sc = mc->mc_sc; mlx_bio *bp = (mlx_bio *)mc->mc_private; struct mlxd_softc *mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp); - + + MLX_IO_ASSERT_LOCKED(sc); if (mc->mc_status != MLX_STATUS_OK) { /* could be more verbose here? */ MLX_BIO_SET_ERROR(bp, EIO); @@ -1969,8 +2050,11 @@ error = ENOMEM; /* get ourselves a command and copy in from user space */ - if ((mc = mlx_alloccmd(sc)) == NULL) + MLX_IO_LOCK(sc); + if ((mc = mlx_alloccmd(sc)) == NULL) { + MLX_IO_UNLOCK(sc); return(error); + } bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox)); debug(0, "got command buffer"); @@ -1983,9 +2067,13 @@ error = EINVAL; goto out; } + MLX_IO_UNLOCK(sc); if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) || - (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))) + (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))) { + MLX_IO_LOCK(sc); goto out; + } + MLX_IO_LOCK(sc); debug(0, "got kernel buffer"); } @@ -2010,17 +2098,20 @@ mc->mc_private = mu; error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length, mlx_user_cb, mc, BUS_DMA_NOWAIT); + if (error) + goto out; /* copy out status and data */ mu->mu_status = mc->mc_status; - if ((mu->mu_datasize > 0) && - ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize)))) - goto out; - - error = 0; + if (mu->mu_datasize > 0) { + MLX_IO_UNLOCK(sc); + error = copyout(kbuf, mu->mu_buf, mu->mu_datasize); + MLX_IO_LOCK(sc); + } out: mlx_releasecmd(mc); + MLX_IO_UNLOCK(sc); if (kbuf != NULL) free(kbuf, M_DEVBUF); return(error); @@ -2042,10 +2133,12 @@ mlx_getslot(struct mlx_command *mc) { struct mlx_softc *sc = mc->mc_sc; - int s, slot, limit; + int slot, limit; debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); + /* * Enforce slot-usage limit, if we have the required information. */ @@ -2062,7 +2155,6 @@ * * XXX linear search is slow */ - s = splbio(); for (slot = 0; slot < limit; slot++) { debug(2, "try slot %d", slot); if (sc->mlx_busycmd[slot] == NULL) @@ -2072,7 +2164,6 @@ sc->mlx_busycmd[slot] = mc; sc->mlx_busycmds++; } - splx(s); /* out of slots? */ if (slot >= limit) @@ -2153,7 +2244,7 @@ mlx_start(struct mlx_command *mc) { struct mlx_softc *sc = mc->mc_sc; - int i, s, done; + int i; debug_called(1); @@ -2165,22 +2256,17 @@ /* set a default 60-second timeout XXX tunable? XXX not currently used */ mc->mc_timeout = time_second + 60; - + /* spin waiting for the mailbox */ - for (i = 100000, done = 0; (i > 0) && !done; i--) { - s = splbio(); + for (i = 100000; i > 0; i--) { if (sc->mlx_tryqueue(sc, mc)) { - done = 1; /* move command to work queue */ TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link); - } - splx(s); /* drop spl to allow completion interrupts */ + return (0); + } else + mlx_done(sc, 0); } - /* command is enqueued */ - if (done) - return(0); - /* * We couldn't get the controller to take the command. Revoke the slot * that the command was given and return it with a bad status. @@ -2200,19 +2286,19 @@ * Returns nonzero if one or more commands were completed. */ static int -mlx_done(struct mlx_softc *sc) +mlx_done(struct mlx_softc *sc, int startio) { struct mlx_command *mc; - int s, result; + int result; u_int8_t slot; u_int16_t status; debug_called(2); + MLX_IO_ASSERT_LOCKED(sc); result = 0; /* loop collecting completed commands */ - s = splbio(); for (;;) { /* poll for a completed command's identifier and status */ if (sc->mlx_findcomplete(sc, &slot, &status)) { @@ -2235,10 +2321,9 @@ break; } } - splx(s); /* if we've completed any commands, try posting some more */ - if (result) + if (result && startio) mlx_startio(sc); /* handle completion and timeouts */ @@ -2254,16 +2339,10 @@ mlx_complete(struct mlx_softc *sc) { struct mlx_command *mc, *nc; - int s; debug_called(2); + MLX_IO_ASSERT_LOCKED(sc); - /* avoid reentrancy XXX might want to signal and request a restart */ - if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING)) - return; - - s = splbio(); - /* scan the list of busy/done commands */ mc = TAILQ_FIRST(&sc->mlx_work); while (mc != NULL) { @@ -2299,9 +2378,6 @@ } mc = nc; } - splx(s); - - mlx_lock_clr(sc, MLX_LOCK_COMPLETING); } /******************************************************************************** @@ -2329,14 +2405,12 @@ { struct mlx_command *mc; int error; - int s; debug_called(1); - s = splbio(); + MLX_IO_ASSERT_LOCKED(sc); if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); - splx(s); /* allocate a new command buffer? */ if (mc == NULL) { @@ -2362,13 +2436,11 @@ static void mlx_releasecmd(struct mlx_command *mc) { - int s; debug_called(1); - s = splbio(); + MLX_IO_ASSERT_LOCKED(mc->mc_sc); TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link); - splx(s); } /******************************************************************************** @@ -2394,8 +2466,6 @@ /******************************************************************************** * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure * (the controller is not ready to take a command). - * - * Must be called at splbio or in a fashion that prevents reentry. */ static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) @@ -2403,6 +2473,7 @@ int i; debug_called(2); + MLX_IO_ASSERT_LOCKED(sc); /* ready for our command? */ if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) { @@ -2420,14 +2491,13 @@ /******************************************************************************** * See if a command has been completed, if so acknowledge its completion * and recover the slot number and status code. - * - * Must be called at splbio or in a fashion that prevents reentry. */ static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) { debug_called(2); + MLX_IO_ASSERT_LOCKED(sc); /* status available? */ if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) { @@ -2444,13 +2514,12 @@ /******************************************************************************** * Enable/disable interrupts as requested. (No acknowledge required) - * - * Must be called at splbio or in a fashion that prevents reentry. */ static void mlx_v3_intaction(struct mlx_softc *sc, int action) { debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); switch(action) { case MLX_INTACTION_DISABLE: @@ -2470,18 +2539,17 @@ * error has been fetched, 2 if an error has been retrieved. */ static int -mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) +mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, + int first) { u_int8_t fwerror; - static int initted = 0; debug_called(2); /* first time around, clear any hardware completion status */ - if (!initted) { + if (first) { MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK); DELAY(1000); - initted = 1; } /* init in progress? */ @@ -2513,8 +2581,6 @@ /******************************************************************************** * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure * (the controller is not ready to take a command). - * - * Must be called at splbio or in a fashion that prevents reentry. */ static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) @@ -2522,6 +2588,7 @@ int i; debug_called(2); + MLX_IO_ASSERT_LOCKED(sc); /* ready for our command? */ if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) { @@ -2530,7 +2597,7 @@ MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */ - bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH, + bus_barrier(sc->mlx_mem, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH, BUS_SPACE_BARRIER_WRITE); /* post command */ @@ -2543,14 +2610,13 @@ /******************************************************************************** * See if a command has been completed, if so acknowledge its completion * and recover the slot number and status code. - * - * Must be called at splbio or in a fashion that prevents reentry. */ static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) { debug_called(2); + MLX_IO_ASSERT_LOCKED(sc); /* status available? */ if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) { @@ -2567,13 +2633,12 @@ /******************************************************************************** * Enable/disable interrupts as requested. - * - * Must be called at splbio or in a fashion that prevents reentry. */ static void mlx_v4_intaction(struct mlx_softc *sc, int action) { debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); switch(action) { case MLX_INTACTION_DISABLE: @@ -2593,18 +2658,17 @@ * error has been fetched, 2 if an error has been retrieved. */ static int -mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) +mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, + int first) { u_int8_t fwerror; - static int initted = 0; debug_called(2); /* first time around, clear any hardware completion status */ - if (!initted) { + if (first) { MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK); DELAY(1000); - initted = 1; } /* init in progress? */ @@ -2636,8 +2700,6 @@ /******************************************************************************** * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure * (the controller is not ready to take a command). - * - * Must be called at splbio or in a fashion that prevents reentry. */ static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) @@ -2645,6 +2707,7 @@ int i; debug_called(2); + MLX_IO_ASSERT_LOCKED(sc); /* ready for our command? */ if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) { @@ -2662,14 +2725,13 @@ /******************************************************************************** * See if a command has been completed, if so acknowledge its completion * and recover the slot number and status code. - * - * Must be called at splbio or in a fashion that prevents reentry. */ static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) { debug_called(2); + MLX_IO_ASSERT_LOCKED(sc); /* status available? */ if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) { @@ -2686,13 +2748,12 @@ /******************************************************************************** * Enable/disable interrupts as requested. - * - * Must be called at splbio or in a fashion that prevents reentry. */ static void mlx_v5_intaction(struct mlx_softc *sc, int action) { debug_called(1); + MLX_IO_ASSERT_LOCKED(sc); switch(action) { case MLX_INTACTION_DISABLE: @@ -2712,18 +2773,17 @@ * error has been fetched, 2 if an error has been retrieved. */ static int -mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) +mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, + int first) { u_int8_t fwerror; - static int initted = 0; debug_called(2); /* first time around, clear any hardware completion status */ - if (!initted) { + if (first) { MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK); DELAY(1000); - initted = 1; } /* init in progress? */ @@ -2992,6 +3052,7 @@ int i; /* search system drives */ + MLX_CONFIG_ASSERT_LOCKED(sc); for (i = 0; i < MLX_MAXDRIVES; i++) { /* is this one attached? */ if (sc->mlx_sysdrive[i].ms_disk != 0) { --- //depot/vendor/freebsd/src/sys/dev/mlx/mlx_disk.c 2004-11-25 12:20:50.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/mlx/mlx_disk.c 2012-08-06 19:03:29.000000000 0000 @@ -36,7 +36,9 @@ #include #include #include +#include #include +#include #include #include @@ -84,10 +86,17 @@ return (ENXIO); /* controller not active? */ - if (sc->mlxd_controller->mlx_state & MLX_STATE_SHUTDOWN) + MLX_CONFIG_LOCK(sc->mlxd_controller); + MLX_IO_LOCK(sc->mlxd_controller); + if (sc->mlxd_controller->mlx_state & MLX_STATE_SHUTDOWN) { + MLX_IO_UNLOCK(sc->mlxd_controller); + MLX_CONFIG_UNLOCK(sc->mlxd_controller); return(ENXIO); + } sc->mlxd_flags |= MLXD_OPEN; + MLX_IO_UNLOCK(sc->mlxd_controller); + MLX_CONFIG_UNLOCK(sc->mlxd_controller); return (0); } @@ -97,10 +106,14 @@ struct mlxd_softc *sc = (struct mlxd_softc *)dp->d_drv1; debug_called(1); - + if (sc == NULL) return (ENXIO); + MLX_CONFIG_LOCK(sc->mlxd_controller); + MLX_IO_LOCK(sc->mlxd_controller); sc->mlxd_flags &= ~MLXD_OPEN; + MLX_IO_UNLOCK(sc->mlxd_controller); + MLX_CONFIG_UNLOCK(sc->mlxd_controller); return (0); } @@ -142,14 +155,17 @@ } /* XXX may only be temporarily offline - sleep? */ + MLX_IO_LOCK(sc->mlxd_controller); if (sc->mlxd_drive->ms_state == MLX_SYSD_OFFLINE) { + MLX_IO_UNLOCK(sc->mlxd_controller); MLX_BIO_SET_ERROR(bp, ENXIO); goto bad; } MLX_BIO_STATS_START(bp); mlx_submit_buf(sc->mlxd_controller, bp); - return; + MLX_IO_UNLOCK(sc->mlxd_controller); + return; bad: /* @@ -232,7 +248,6 @@ sc->mlxd_disk->d_mediasize = MLX_BLKSIZE * (off_t)sc->mlxd_drive->ms_size; sc->mlxd_disk->d_fwsectors = sc->mlxd_drive->ms_sectors; sc->mlxd_disk->d_fwheads = sc->mlxd_drive->ms_heads; - sc->mlxd_disk->d_flags = DISKFLAG_NEEDSGIANT; /* * Set maximum I/O size to the lesser of the recommended maximum and the practical --- //depot/vendor/freebsd/src/sys/dev/mlx/mlx_pci.c 2012-03-12 08:05:24.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/mlx/mlx_pci.c 2012-08-06 19:03:29.000000000 0000 @@ -30,7 +30,10 @@ #include #include #include +#include #include +#include +#include #include #include @@ -88,6 +91,21 @@ {0, 0, 0, 0, 0, 0} }; +static struct mlx_ident * +mlx_pci_match(device_t dev) +{ + struct mlx_ident *m; + + for (m = mlx_identifiers; m->vendor != 0; m++) { + if ((m->vendor == pci_get_vendor(dev)) && + (m->device == pci_get_device(dev)) && + ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) && + (m->subdevice == pci_get_subdevice(dev))))) + return (m); + } + return (NULL); +} + static int mlx_pci_probe(device_t dev) { @@ -95,15 +113,10 @@ debug_called(1); - for (m = mlx_identifiers; m->vendor != 0; m++) { - if ((m->vendor == pci_get_vendor(dev)) && - (m->device == pci_get_device(dev)) && - ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) && - (m->subdevice == pci_get_subdevice(dev))))) { - - device_set_desc(dev, m->desc); - return(BUS_PROBE_DEFAULT); - } + m = mlx_pci_match(dev); + if (m != NULL) { + device_set_desc(dev, m->desc); + return(BUS_PROBE_DEFAULT); } return(ENXIO); } @@ -112,45 +125,29 @@ mlx_pci_attach(device_t dev) { struct mlx_softc *sc; - int i, error; - u_int32_t command; + struct mlx_ident *m; + int error; debug_called(1); - /* - * 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_MEMEN) == 0) { - device_printf(dev, "memory window not available\n"); - return(ENXIO); - } - /* force the busmaster enable bit on */ - command |= PCIM_CMD_BUSMASTEREN; - pci_write_config(dev, PCIR_COMMAND, command, 2); + pci_enable_busmaster(dev); - /* - * Initialise softc. - */ sc = device_get_softc(dev); - bzero(sc, sizeof(*sc)); sc->mlx_dev = dev; /* * Work out what sort of adapter this is (we need to know this in order * to map the appropriate interface resources). */ - sc->mlx_iftype = 0; - for (i = 0; mlx_identifiers[i].vendor != 0; i++) { - if ((mlx_identifiers[i].vendor == pci_get_vendor(dev)) && - (mlx_identifiers[i].device == pci_get_device(dev))) { - sc->mlx_iftype = mlx_identifiers[i].iftype; - break; - } - } - if (sc->mlx_iftype == 0) /* shouldn't happen */ + m = mlx_pci_match(dev); + if (m == NULL) /* shouldn't happen */ return(ENXIO); - + sc->mlx_iftype = m->iftype; + + mtx_init(&sc->mlx_io_lock, "mlx I/O", NULL, MTX_DEF); + sx_init(&sc->mlx_config_lock, "mlx config"); + callout_init_mtx(&sc->mlx_timeout, &sc->mlx_io_lock, 0); + /* * Allocate the PCI register window. */ @@ -183,8 +180,6 @@ mlx_free(sc); return(ENXIO); } - sc->mlx_btag = rman_get_bustag(sc->mlx_mem); - sc->mlx_bhandle = rman_get_bushandle(sc->mlx_mem); /* * Allocate the parent bus DMA tag appropriate for PCI. --- //depot/vendor/freebsd/src/sys/dev/mlx/mlxreg.h 2004-11-25 12:20:50.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/mlx/mlxreg.h 2012-08-05 20:26:24.000000000 0000 @@ -78,18 +78,18 @@ #define MLX_V3_FWERROR_PARAM1 0x00 #define MLX_V3_FWERROR_PARAM2 0x01 -#define MLX_V3_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_MAILBOX + idx, val) -#define MLX_V3_GET_STATUS_IDENT(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS_IDENT) -#define MLX_V3_GET_STATUS(sc) bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS) -#define MLX_V3_GET_IDBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR) -#define MLX_V3_PUT_IDBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR, val) -#define MLX_V3_GET_ODBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR) -#define MLX_V3_PUT_ODBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR, val) -#define MLX_V3_PUT_IER(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IER, val) -#define MLX_V3_GET_FWERROR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR) -#define MLX_V3_PUT_FWERROR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR, val) -#define MLX_V3_GET_FWERROR_PARAM1(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR_PARAM1) -#define MLX_V3_GET_FWERROR_PARAM2(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR_PARAM2) +#define MLX_V3_PUT_MAILBOX(sc, idx, val) bus_write_1(sc->mlx_mem, MLX_V3_MAILBOX + idx, val) +#define MLX_V3_GET_STATUS_IDENT(sc) bus_read_1 (sc->mlx_mem, MLX_V3_STATUS_IDENT) +#define MLX_V3_GET_STATUS(sc) bus_read_2 (sc->mlx_mem, MLX_V3_STATUS) +#define MLX_V3_GET_IDBR(sc) bus_read_1 (sc->mlx_mem, MLX_V3_IDBR) +#define MLX_V3_PUT_IDBR(sc, val) bus_write_1(sc->mlx_mem, MLX_V3_IDBR, val) +#define MLX_V3_GET_ODBR(sc) bus_read_1 (sc->mlx_mem, MLX_V3_ODBR) +#define MLX_V3_PUT_ODBR(sc, val) bus_write_1(sc->mlx_mem, MLX_V3_ODBR, val) +#define MLX_V3_PUT_IER(sc, val) bus_write_1(sc->mlx_mem, MLX_V3_IER, val) +#define MLX_V3_GET_FWERROR(sc) bus_read_1 (sc->mlx_mem, MLX_V3_FWERROR) +#define MLX_V3_PUT_FWERROR(sc, val) bus_write_1(sc->mlx_mem, MLX_V3_FWERROR, val) +#define MLX_V3_GET_FWERROR_PARAM1(sc) bus_read_1 (sc->mlx_mem, MLX_V3_FWERROR_PARAM1) +#define MLX_V3_GET_FWERROR_PARAM2(sc) bus_read_1 (sc->mlx_mem, MLX_V3_FWERROR_PARAM2) #define MLX_V3_IDB_FULL (1<<0) /* mailbox is full */ #define MLX_V3_IDB_INIT_BUSY (1<<1) /* initialisation in progress */ @@ -115,18 +115,18 @@ #define MLX_V4_FWERROR_PARAM2 0x1001 /* use longword access? */ -#define MLX_V4_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX + idx, val) -#define MLX_V4_GET_STATUS_IDENT(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_STATUS_IDENT) -#define MLX_V4_GET_STATUS(sc) bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_STATUS) -#define MLX_V4_GET_IDBR(sc) bus_space_read_4 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IDBR) -#define MLX_V4_PUT_IDBR(sc, val) bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IDBR, val) -#define MLX_V4_GET_ODBR(sc) bus_space_read_4 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_ODBR) -#define MLX_V4_PUT_ODBR(sc, val) bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_ODBR, val) -#define MLX_V4_PUT_IER(sc, val) bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IER, val) -#define MLX_V4_GET_FWERROR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR) -#define MLX_V4_PUT_FWERROR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR, val) -#define MLX_V4_GET_FWERROR_PARAM1(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR_PARAM1) -#define MLX_V4_GET_FWERROR_PARAM2(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR_PARAM2) +#define MLX_V4_PUT_MAILBOX(sc, idx, val) bus_write_1(sc->mlx_mem, MLX_V4_MAILBOX + idx, val) +#define MLX_V4_GET_STATUS_IDENT(sc) bus_read_1 (sc->mlx_mem, MLX_V4_STATUS_IDENT) +#define MLX_V4_GET_STATUS(sc) bus_read_2 (sc->mlx_mem, MLX_V4_STATUS) +#define MLX_V4_GET_IDBR(sc) bus_read_4 (sc->mlx_mem, MLX_V4_IDBR) +#define MLX_V4_PUT_IDBR(sc, val) bus_write_4(sc->mlx_mem, MLX_V4_IDBR, val) +#define MLX_V4_GET_ODBR(sc) bus_read_4 (sc->mlx_mem, MLX_V4_ODBR) +#define MLX_V4_PUT_ODBR(sc, val) bus_write_4(sc->mlx_mem, MLX_V4_ODBR, val) +#define MLX_V4_PUT_IER(sc, val) bus_write_4(sc->mlx_mem, MLX_V4_IER, val) +#define MLX_V4_GET_FWERROR(sc) bus_read_1 (sc->mlx_mem, MLX_V4_FWERROR) +#define MLX_V4_PUT_FWERROR(sc, val) bus_write_1(sc->mlx_mem, MLX_V4_FWERROR, val) +#define MLX_V4_GET_FWERROR_PARAM1(sc) bus_read_1 (sc->mlx_mem, MLX_V4_FWERROR_PARAM1) +#define MLX_V4_GET_FWERROR_PARAM2(sc) bus_read_1 (sc->mlx_mem, MLX_V4_FWERROR_PARAM2) #define MLX_V4_IDB_FULL (1<<0) /* mailbox is full */ #define MLX_V4_IDB_INIT_BUSY (1<<1) /* initialisation in progress */ @@ -160,18 +160,18 @@ #define MLX_V5_FWERROR_PARAM1 0x50 #define MLX_V5_FWERROR_PARAM2 0x51 -#define MLX_V5_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_MAILBOX + idx, val) -#define MLX_V5_GET_STATUS_IDENT(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_STATUS_IDENT) -#define MLX_V5_GET_STATUS(sc) bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_STATUS) -#define MLX_V5_GET_IDBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IDBR) -#define MLX_V5_PUT_IDBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IDBR, val) -#define MLX_V5_GET_ODBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_ODBR) -#define MLX_V5_PUT_ODBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_ODBR, val) -#define MLX_V5_PUT_IER(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IER, val) -#define MLX_V5_GET_FWERROR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR) -#define MLX_V5_PUT_FWERROR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR, val) -#define MLX_V5_GET_FWERROR_PARAM1(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR_PARAM1) -#define MLX_V5_GET_FWERROR_PARAM2(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR_PARAM2) +#define MLX_V5_PUT_MAILBOX(sc, idx, val) bus_write_1(sc->mlx_mem, MLX_V5_MAILBOX + idx, val) +#define MLX_V5_GET_STATUS_IDENT(sc) bus_read_1 (sc->mlx_mem, MLX_V5_STATUS_IDENT) +#define MLX_V5_GET_STATUS(sc) bus_read_2 (sc->mlx_mem, MLX_V5_STATUS) +#define MLX_V5_GET_IDBR(sc) bus_read_1 (sc->mlx_mem, MLX_V5_IDBR) +#define MLX_V5_PUT_IDBR(sc, val) bus_write_1(sc->mlx_mem, MLX_V5_IDBR, val) +#define MLX_V5_GET_ODBR(sc) bus_read_1 (sc->mlx_mem, MLX_V5_ODBR) +#define MLX_V5_PUT_ODBR(sc, val) bus_write_1(sc->mlx_mem, MLX_V5_ODBR, val) +#define MLX_V5_PUT_IER(sc, val) bus_write_1(sc->mlx_mem, MLX_V5_IER, val) +#define MLX_V5_GET_FWERROR(sc) bus_read_1 (sc->mlx_mem, MLX_V5_FWERROR) +#define MLX_V5_PUT_FWERROR(sc, val) bus_write_1(sc->mlx_mem, MLX_V5_FWERROR, val) +#define MLX_V5_GET_FWERROR_PARAM1(sc) bus_read_1 (sc->mlx_mem, MLX_V5_FWERROR_PARAM1) +#define MLX_V5_GET_FWERROR_PARAM2(sc) bus_read_1 (sc->mlx_mem, MLX_V5_FWERROR_PARAM2) #define MLX_V5_IDB_EMPTY (1<<0) /* mailbox is empty */ #define MLX_V5_IDB_INIT_DONE (1<<1) /* initialisation has completed */ --- //depot/vendor/freebsd/src/sys/dev/mlx/mlxvar.h 2012-08-03 00:15:17.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/mlx/mlxvar.h 2012-08-06 18:47:34.000000000 0000 @@ -113,8 +113,6 @@ struct resource *mlx_mem; /* mailbox interface window */ int mlx_mem_rid; int mlx_mem_type; - bus_space_handle_t mlx_bhandle; /* bus space handle */ - bus_space_tag_t mlx_btag; /* bus space tag */ bus_dma_tag_t mlx_parent_dmat;/* parent DMA tag */ bus_dma_tag_t mlx_buffer_dmat;/* data buffer DMA tag */ struct resource *mlx_irq; /* interrupt */ @@ -149,7 +147,10 @@ #define MLX_STATE_SHUTDOWN (1<<1) /* controller is shut down */ #define MLX_STATE_OPEN (1<<2) /* control device is open */ #define MLX_STATE_SUSPEND (1<<3) /* controller is suspended */ - struct callout_handle mlx_timeout; /* periodic status monitor */ +#define MLX_STATE_QFROZEN (1<<4) /* bio queue frozen */ + struct mtx mlx_io_lock; + struct sx mlx_config_lock; + struct callout mlx_timeout; /* periodic status monitor */ time_t mlx_lastpoll; /* last time_second we polled for status */ u_int16_t mlx_lastevent; /* sequence number of the last event we recorded */ int mlx_currevent; /* sequence number last time we looked */ @@ -160,7 +161,6 @@ struct mlx_rebuild_status mlx_rebuildstat; /* last rebuild status */ struct mlx_pause mlx_pause; /* pending pause operation details */ - int mlx_locks; /* reentrancy avoidance */ int mlx_flags; #define MLX_SPINUP_REPORTED (1<<0) /* "spinning up drives" message displayed */ #define MLX_EVENTLOG_BUSY (1<<1) /* currently reading event log */ @@ -174,34 +174,17 @@ int (* mlx_tryqueue)(struct mlx_softc *sc, struct mlx_command *mc); int (* mlx_findcomplete)(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); void (* mlx_intaction)(struct mlx_softc *sc, int action); - int (* mlx_fw_handshake)(struct mlx_softc *sc, int *error, int *param1, int *param2); + int (* mlx_fw_handshake)(struct mlx_softc *sc, int *error, int *param1, int *param2, int first); #define MLX_INTACTION_DISABLE 0 #define MLX_INTACTION_ENABLE 1 }; -/* - * Simple (stupid) locks. - * - * Note that these are designed to avoid reentrancy, not concurrency, and will - * need to be replaced with something better. - */ -#define MLX_LOCK_COMPLETING (1<<0) -#define MLX_LOCK_STARTING (1<<1) - -static __inline int -mlx_lock_tas(struct mlx_softc *sc, int lock) -{ - if ((sc)->mlx_locks & (lock)) - return(1); - atomic_set_int(&sc->mlx_locks, lock); - return(0); -} - -static __inline void -mlx_lock_clr(struct mlx_softc *sc, int lock) -{ - atomic_clear_int(&sc->mlx_locks, lock); -} +#define MLX_IO_LOCK(sc) mtx_lock(&(sc)->mlx_io_lock) +#define MLX_IO_UNLOCK(sc) mtx_unlock(&(sc)->mlx_io_lock) +#define MLX_IO_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mlx_io_lock, MA_OWNED) +#define MLX_CONFIG_LOCK(sc) sx_xlock(&(sc)->mlx_config_lock) +#define MLX_CONFIG_UNLOCK(sc) sx_xunlock(&(sc)->mlx_config_lock) +#define MLX_CONFIG_ASSERT_LOCKED(sc) sx_assert(&(sc)->mlx_config_lock, SA_XLOCKED) /* * Interface between bus connections and driver core.