mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-01 12:19:28 +00:00
Add mechanism to unload CAM periph drivers.
For now it allows to unload CTL kernel module if there are no target-capable SIMs in CAM. As next step full teardown of CAM targets can be implemented.
This commit is contained in:
parent
61471674c4
commit
94173c3c9b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=314870
@ -139,6 +139,38 @@ periphdriver_register(void *data)
|
||||
(*drv->init)();
|
||||
}
|
||||
|
||||
int
|
||||
periphdriver_unregister(void *data)
|
||||
{
|
||||
struct periph_driver *drv = (struct periph_driver *)data;
|
||||
int error, n;
|
||||
|
||||
/* If driver marked as early or it is late now, deinitialize it. */
|
||||
if (((drv->flags & CAM_PERIPH_DRV_EARLY) != 0 && initialized > 0) ||
|
||||
initialized > 1) {
|
||||
if (drv->deinit == NULL) {
|
||||
printf("CAM periph driver '%s' doesn't have deinit.\n",
|
||||
drv->driver_name);
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
error = drv->deinit();
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
|
||||
xpt_lock_buses();
|
||||
for (n = 0; n < nperiph_drivers && periph_drivers[n] != drv; n++)
|
||||
;
|
||||
KASSERT(n < nperiph_drivers,
|
||||
("Periph driver '%s' was not registered", drv->driver_name));
|
||||
for (; n + 1 < nperiph_drivers; n++)
|
||||
periph_drivers[n] = periph_drivers[n + 1];
|
||||
periph_drivers[n + 1] = NULL;
|
||||
nperiph_drivers--;
|
||||
xpt_unlock_buses();
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
periphdriver_init(int level)
|
||||
{
|
||||
|
@ -45,6 +45,7 @@ extern struct cam_periph *xpt_periph;
|
||||
|
||||
extern struct periph_driver **periph_drivers;
|
||||
void periphdriver_register(void *);
|
||||
int periphdriver_unregister(void *);
|
||||
void periphdriver_init(int level);
|
||||
|
||||
#include <sys/module.h>
|
||||
@ -56,8 +57,7 @@ void periphdriver_init(int level);
|
||||
periphdriver_register(data); \
|
||||
break; \
|
||||
case MOD_UNLOAD: \
|
||||
printf(#name " module unload - not possible for this module type\n"); \
|
||||
return EINVAL; \
|
||||
return (periphdriver_unregister(data)); \
|
||||
default: \
|
||||
return EOPNOTSUPP; \
|
||||
} \
|
||||
@ -71,20 +71,26 @@ void periphdriver_init(int level);
|
||||
DECLARE_MODULE(name, name ## _mod, SI_SUB_DRIVERS, SI_ORDER_ANY); \
|
||||
MODULE_DEPEND(name, cam, 1, 1, 1)
|
||||
|
||||
typedef void (periph_init_t)(void); /*
|
||||
* Callback informing the peripheral driver
|
||||
* it can perform it's initialization since
|
||||
* the XPT is now fully initialized.
|
||||
*/
|
||||
typedef periph_init_t *periph_init_func_t;
|
||||
/*
|
||||
* Callback informing the peripheral driver it can perform it's
|
||||
* initialization since the XPT is now fully initialized.
|
||||
*/
|
||||
typedef void (periph_init_t)(void);
|
||||
|
||||
/*
|
||||
* Callback requesting the peripheral driver to remove its instances
|
||||
* and shutdown, if possible.
|
||||
*/
|
||||
typedef int (periph_deinit_t)(void);
|
||||
|
||||
struct periph_driver {
|
||||
periph_init_func_t init;
|
||||
char *driver_name;
|
||||
periph_init_t *init;
|
||||
char *driver_name;
|
||||
TAILQ_HEAD(,cam_periph) units;
|
||||
u_int generation;
|
||||
u_int flags;
|
||||
#define CAM_PERIPH_DRV_EARLY 0x01
|
||||
periph_deinit_t *deinit;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -172,6 +172,7 @@ MALLOC_DEFINE(M_CTLFE, "CAM CTL FE", "CAM CTL FE interface");
|
||||
static int ctlfeinitialize(void);
|
||||
static int ctlfeshutdown(void);
|
||||
static periph_init_t ctlfeperiphinit;
|
||||
static periph_deinit_t ctlfeperiphdeinit;
|
||||
static void ctlfeasync(void *callback_arg, uint32_t code,
|
||||
struct cam_path *path, void *arg);
|
||||
static periph_ctor_t ctlferegister;
|
||||
@ -200,7 +201,8 @@ static struct periph_driver ctlfe_driver =
|
||||
{
|
||||
ctlfeperiphinit, "ctl",
|
||||
TAILQ_HEAD_INITIALIZER(ctlfe_driver.units), /*generation*/ 0,
|
||||
CAM_PERIPH_DRV_EARLY
|
||||
CAM_PERIPH_DRV_EARLY,
|
||||
ctlfeperiphdeinit
|
||||
};
|
||||
|
||||
static struct ctl_frontend ctlfe_frontend =
|
||||
@ -212,14 +214,6 @@ static struct ctl_frontend ctlfe_frontend =
|
||||
};
|
||||
CTL_FRONTEND_DECLARE(ctlfe, ctlfe_frontend);
|
||||
|
||||
static int
|
||||
ctlfeshutdown(void)
|
||||
{
|
||||
|
||||
/* CAM does not support periph driver unregister now. */
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
static int
|
||||
ctlfeinitialize(void)
|
||||
{
|
||||
@ -230,6 +224,18 @@ ctlfeinitialize(void)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ctlfeshutdown(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = periphdriver_unregister(&ctlfe_driver);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
mtx_destroy(&ctlfe_list_mtx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ctlfeperiphinit(void)
|
||||
{
|
||||
@ -243,6 +249,17 @@ ctlfeperiphinit(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ctlfeperiphdeinit(void)
|
||||
{
|
||||
|
||||
/* XXX: It would be good to tear down active ports here. */
|
||||
if (!TAILQ_EMPTY(&ctlfe_driver.units))
|
||||
return (EBUSY);
|
||||
xpt_register_async(0, ctlfeasync, NULL, NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user