Date: Tue, 7 Mar 2017 17:41:08 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r314870 - in head/sys/cam: . ctl Message-ID: <201703071741.v27Hf8LD073505@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Tue Mar 7 17:41:08 2017 New Revision: 314870 URL: https://svnweb.freebsd.org/changeset/base/314870 Log: 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. Modified: head/sys/cam/cam_periph.c head/sys/cam/cam_periph.h head/sys/cam/ctl/scsi_ctl.c Modified: head/sys/cam/cam_periph.c ============================================================================== --- head/sys/cam/cam_periph.c Tue Mar 7 17:38:52 2017 (r314869) +++ head/sys/cam/cam_periph.c Tue Mar 7 17:41:08 2017 (r314870) @@ -139,6 +139,38 @@ again: (*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) { Modified: head/sys/cam/cam_periph.h ============================================================================== --- head/sys/cam/cam_periph.h Tue Mar 7 17:38:52 2017 (r314869) +++ head/sys/cam/cam_periph.h Tue Mar 7 17:41:08 2017 (r314870) @@ -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 { Modified: head/sys/cam/ctl/scsi_ctl.c ============================================================================== --- head/sys/cam/ctl/scsi_ctl.c Tue Mar 7 17:38:52 2017 (r314869) +++ head/sys/cam/ctl/scsi_ctl.c Tue Mar 7 17:41:08 2017 (r314870) @@ -172,6 +172,7 @@ MALLOC_DEFINE(M_CTLFE, "CAM CTL FE", "CA 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 = @@ -213,20 +215,24 @@ static struct ctl_frontend ctlfe_fronten CTL_FRONTEND_DECLARE(ctlfe, ctlfe_frontend); static int -ctlfeshutdown(void) +ctlfeinitialize(void) { - /* CAM does not support periph driver unregister now. */ - return (EBUSY); + STAILQ_INIT(&ctlfe_softc_list); + mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF); + periphdriver_register(&ctlfe_driver); + return (0); } static int -ctlfeinitialize(void) +ctlfeshutdown(void) { + int error; - STAILQ_INIT(&ctlfe_softc_list); - mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF); - periphdriver_register(&ctlfe_driver); + error = periphdriver_unregister(&ctlfe_driver); + if (error != 0) + return (error); + mtx_destroy(&ctlfe_list_mtx); return (0); } @@ -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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703071741.v27Hf8LD073505>