mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-16 10:20:30 +00:00
Rework aac locking for MPSAFE CAM. This fixes a Giant mutex assertion
reported on freebsd-current [1]. Also dequeue all events in aac_release_command (instead of just one) so that there's no risk of them getting stranded. Reported by: Steven Brown [1] Submitted by: scottl@ [1] http://lists.freebsd.org/pipermail/freebsd-current/2007-October/077928.html
This commit is contained in:
parent
3c2ff3b0a5
commit
eb5cbaa020
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=173264
@ -1310,9 +1310,12 @@ aac_release_command(struct aac_command *cm)
|
||||
|
||||
aac_enqueue_free(cm);
|
||||
|
||||
/*
|
||||
* Dequeue all events so that there's no risk of events getting
|
||||
* stranded.
|
||||
*/
|
||||
sc = cm->cm_sc;
|
||||
event = TAILQ_FIRST(&sc->aac_ev_cmfree);
|
||||
if (event != NULL) {
|
||||
while ((event = TAILQ_FIRST(&sc->aac_ev_cmfree)) != NULL) {
|
||||
TAILQ_REMOVE(&sc->aac_ev_cmfree, event, ev_links);
|
||||
event->ev_callback(sc, event, event->ev_arg);
|
||||
}
|
||||
|
@ -103,13 +103,17 @@ MALLOC_DEFINE(M_AACCAM, "aaccam", "AAC CAM info");
|
||||
static void
|
||||
aac_cam_event(struct aac_softc *sc, struct aac_event *event, void *arg)
|
||||
{
|
||||
union ccb *ccb;
|
||||
struct aac_cam *camsc;
|
||||
|
||||
switch (event->ev_type) {
|
||||
case AAC_EVENT_CMFREE:
|
||||
camsc = arg;
|
||||
ccb = arg;
|
||||
camsc = ccb->ccb_h.sim_priv.entries[0].ptr;
|
||||
free(event, M_AACCAM);
|
||||
xpt_release_simq(camsc->sim, 1);
|
||||
ccb->ccb_h.status = CAM_REQUEUE_REQ;
|
||||
xpt_done(ccb);
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->aac_dev, "unknown event %d in aac_cam\n",
|
||||
@ -131,19 +135,21 @@ aac_cam_probe(device_t dev)
|
||||
static int
|
||||
aac_cam_detach(device_t dev)
|
||||
{
|
||||
struct aac_softc *sc;
|
||||
struct aac_cam *camsc;
|
||||
debug_called(2);
|
||||
|
||||
camsc = (struct aac_cam *)device_get_softc(dev);
|
||||
sc = camsc->inf->aac_sc;
|
||||
|
||||
mtx_lock(&Giant);
|
||||
mtx_lock(&sc->aac_io_lock);
|
||||
|
||||
xpt_async(AC_LOST_DEVICE, camsc->path, NULL);
|
||||
xpt_free_path(camsc->path);
|
||||
xpt_bus_deregister(cam_sim_path(camsc->sim));
|
||||
cam_sim_free(camsc->sim, /*free_devq*/TRUE);
|
||||
|
||||
mtx_unlock(&Giant);
|
||||
mtx_unlock(&sc->aac_io_lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -171,15 +177,17 @@ aac_cam_attach(device_t dev)
|
||||
return (EIO);
|
||||
|
||||
sim = cam_sim_alloc(aac_cam_action, aac_cam_poll, "aacp", camsc,
|
||||
device_get_unit(dev), &Giant, 1, 1, devq);
|
||||
device_get_unit(dev), &inf->aac_sc->aac_io_lock, 1, 1, devq);
|
||||
if (sim == NULL) {
|
||||
cam_simq_free(devq);
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
/* Since every bus has it's own sim, every bus 'appears' as bus 0 */
|
||||
mtx_lock(&inf->aac_sc->aac_io_lock);
|
||||
if (xpt_bus_register(sim, dev, 0) != CAM_SUCCESS) {
|
||||
cam_sim_free(sim, TRUE);
|
||||
mtx_unlock(&inf->aac_sc->aac_io_lock);
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
@ -187,8 +195,10 @@ aac_cam_attach(device_t dev)
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_bus_deregister(cam_sim_path(sim));
|
||||
cam_sim_free(sim, TRUE);
|
||||
mtx_unlock(&inf->aac_sc->aac_io_lock);
|
||||
return (EIO);
|
||||
}
|
||||
mtx_unlock(&inf->aac_sc->aac_io_lock);
|
||||
|
||||
camsc->sim = sim;
|
||||
camsc->path = path;
|
||||
@ -321,27 +331,23 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb)
|
||||
|
||||
/* Async ops that require communcation with the controller */
|
||||
|
||||
mtx_lock(&sc->aac_io_lock);
|
||||
if (aac_alloc_command(sc, &cm)) {
|
||||
struct aac_event *event;
|
||||
|
||||
xpt_freeze_simq(sim, 1);
|
||||
ccb->ccb_h.status = CAM_REQUEUE_REQ;
|
||||
xpt_done(ccb);
|
||||
ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
|
||||
ccb->ccb_h.sim_priv.entries[0].ptr = camsc;
|
||||
event = malloc(sizeof(struct aac_event), M_AACCAM,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (event == NULL) {
|
||||
device_printf(sc->aac_dev,
|
||||
"Warning, out of memory for event\n");
|
||||
/* XXX Yuck, what to do here? */
|
||||
mtx_unlock(&sc->aac_io_lock);
|
||||
return;
|
||||
}
|
||||
event->ev_callback = aac_cam_event;
|
||||
event->ev_arg = camsc;
|
||||
event->ev_arg = ccb;
|
||||
event->ev_type = AAC_EVENT_CMFREE;
|
||||
aac_add_event(sc, event);
|
||||
mtx_unlock(&sc->aac_io_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -429,7 +435,6 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb)
|
||||
} else {
|
||||
ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
xpt_done(ccb);
|
||||
mtx_unlock(&sc->aac_io_lock);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
@ -460,8 +465,6 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb)
|
||||
aac_enqueue_ready(cm);
|
||||
aac_startio(cm->cm_sc);
|
||||
|
||||
mtx_unlock(&sc->aac_io_lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -565,7 +568,6 @@ aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb)
|
||||
return (CAM_REQ_ABORTED);
|
||||
}
|
||||
|
||||
mtx_lock(&sc->aac_io_lock);
|
||||
aac_alloc_sync_fib(sc, &fib);
|
||||
|
||||
vmi = (struct aac_vmioctl *)&fib->data[0];
|
||||
@ -586,12 +588,10 @@ aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb)
|
||||
device_printf(sc->aac_dev,"Error %d sending ResetBus command\n",
|
||||
e);
|
||||
aac_release_sync_fib(sc);
|
||||
mtx_unlock(&sc->aac_io_lock);
|
||||
return (CAM_REQ_ABORTED);
|
||||
}
|
||||
|
||||
aac_release_sync_fib(sc);
|
||||
mtx_unlock(&sc->aac_io_lock);
|
||||
return (CAM_REQ_CMP);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user