diff options
Diffstat (limited to 'sys/cam/cam_sim.c')
-rw-r--r-- | sys/cam/cam_sim.c | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/sys/cam/cam_sim.c b/sys/cam/cam_sim.c index 322915f..cc8f86d 100644 --- a/sys/cam/cam_sim.c +++ b/sys/cam/cam_sim.c @@ -33,6 +33,8 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/malloc.h> #include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> #include <cam/cam.h> #include <cam/cam_ccb.h> @@ -58,39 +60,42 @@ cam_simq_free(struct cam_devq *devq) struct cam_sim * cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll, const char *sim_name, void *softc, u_int32_t unit, - int max_dev_transactions, + struct mtx *mtx, int max_dev_transactions, int max_tagged_dev_transactions, struct cam_devq *queue) { struct cam_sim *sim; - /* - * If this is the xpt layer creating a sim, then it's OK - * to wait for an allocation. - * - * XXX Should we pass in a flag to indicate that wait is OK? - */ - if (strcmp(sim_name, "xpt") == 0) - sim = (struct cam_sim *)malloc(sizeof(struct cam_sim), - M_CAMSIM, M_WAITOK); - else - sim = (struct cam_sim *)malloc(sizeof(struct cam_sim), - M_CAMSIM, M_NOWAIT); - - if (sim != NULL) { - sim->sim_action = sim_action; - sim->sim_poll = sim_poll; - sim->sim_name = sim_name; - sim->softc = softc; - sim->path_id = CAM_PATH_ANY; - sim->unit_number = unit; - sim->bus_id = 0; /* set in xpt_bus_register */ - sim->max_tagged_dev_openings = max_tagged_dev_transactions; - sim->max_dev_openings = max_dev_transactions; - sim->flags = 0; - callout_handle_init(&sim->c_handle); - sim->devq = queue; + if (mtx == NULL) + return (NULL); + + sim = (struct cam_sim *)malloc(sizeof(struct cam_sim), + M_CAMSIM, M_NOWAIT); + + if (sim == NULL) + return (NULL); + + sim->sim_action = sim_action; + sim->sim_poll = sim_poll; + sim->sim_name = sim_name; + sim->softc = softc; + sim->path_id = CAM_PATH_ANY; + sim->unit_number = unit; + sim->bus_id = 0; /* set in xpt_bus_register */ + sim->max_tagged_dev_openings = max_tagged_dev_transactions; + sim->max_dev_openings = max_dev_transactions; + sim->flags = 0; + sim->devq = queue; + sim->mtx = mtx; + if (mtx == &Giant) { + sim->flags |= 0; + callout_init(&sim->callout, 0); + } else { + sim->flags |= CAM_SIM_MPSAFE; + callout_init(&sim->callout, 1); } + SLIST_INIT(&sim->ccb_freeq); + return (sim); } |