Make periphdriver_register() take XPT lock when modifying the periph_drivers
array. This fixes a panic that sometimes occured when kldloading ctl.ko. Reviewed by: mav@ MFC after: 1 month Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
da3b488d62
commit
5719711f8b
@ -108,9 +108,19 @@ periphdriver_register(void *data)
|
||||
struct periph_driver **newdrivers, **old;
|
||||
int ndrivers;
|
||||
|
||||
again:
|
||||
ndrivers = nperiph_drivers + 2;
|
||||
newdrivers = malloc(sizeof(*newdrivers) * ndrivers, M_CAMPERIPH,
|
||||
M_WAITOK);
|
||||
xpt_lock_buses();
|
||||
if (ndrivers != nperiph_drivers + 2) {
|
||||
/*
|
||||
* Lost race against itself; go around.
|
||||
*/
|
||||
xpt_unlock_buses();
|
||||
free(newdrivers, M_CAMPERIPH);
|
||||
goto again;
|
||||
}
|
||||
if (periph_drivers)
|
||||
bcopy(periph_drivers, newdrivers,
|
||||
sizeof(*newdrivers) * nperiph_drivers);
|
||||
@ -118,9 +128,10 @@ periphdriver_register(void *data)
|
||||
newdrivers[nperiph_drivers + 1] = NULL;
|
||||
old = periph_drivers;
|
||||
periph_drivers = newdrivers;
|
||||
nperiph_drivers++;
|
||||
xpt_unlock_buses();
|
||||
if (old)
|
||||
free(old, M_CAMPERIPH);
|
||||
nperiph_drivers++;
|
||||
/* If driver marked as early or it is late now, initialize it. */
|
||||
if (((drv->flags & CAM_PERIPH_DRV_EARLY) != 0 && initialized > 0) ||
|
||||
initialized > 1)
|
||||
|
@ -151,6 +151,8 @@ typedef int xpt_pdrvfunc_t (struct periph_driver **pdrv, void *arg);
|
||||
/* Transport layer configuration information */
|
||||
static struct xpt_softc xsoftc;
|
||||
|
||||
MTX_SYSINIT(xpt_topo_init, &xsoftc.xpt_topo_lock, "XPT topology lock", MTX_DEF);
|
||||
|
||||
SYSCTL_INT(_kern_cam, OID_AUTO, boot_delay, CTLFLAG_RDTUN,
|
||||
&xsoftc.boot_delay, 0, "Bus registration wait time");
|
||||
SYSCTL_UINT(_kern_cam, OID_AUTO, xpt_generation, CTLFLAG_RD,
|
||||
@ -850,7 +852,6 @@ xpt_init(void *dummy)
|
||||
|
||||
mtx_init(&xsoftc.xpt_lock, "XPT lock", NULL, MTX_DEF);
|
||||
mtx_init(&xsoftc.xpt_highpower_lock, "XPT highpower lock", NULL, MTX_DEF);
|
||||
mtx_init(&xsoftc.xpt_topo_lock, "XPT topology lock", NULL, MTX_DEF);
|
||||
xsoftc.xpt_taskq = taskqueue_create("CAM XPT task", M_WAITOK,
|
||||
taskqueue_thread_enqueue, /*context*/&xsoftc.xpt_taskq);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user