Make CAM SIM lock optional.

For three years now CAM does not use SIM lock, but still enforces SIM to
use it.  Remove this requirement, allowing SIMs to have any locking they
prefer, if they pass no mutex to cam_sim_alloc().

MFC after:	2 weeks
This commit is contained in:
Alexander Motin 2017-03-21 09:12:41 +00:00
parent 817e1ad9d0
commit 401ed17ad0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=315673
3 changed files with 66 additions and 39 deletions

View File

@ -46,6 +46,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_CAMSIM, "CAM SIM", "CAM SIM buffers");
static struct mtx cam_sim_free_mtx;
MTX_SYSINIT(cam_sim_free_init, &cam_sim_free_mtx, "CAM SIM free lock", MTX_DEF);
struct cam_devq *
cam_simq_alloc(u_int32_t max_sim_transactions)
{
@ -66,9 +69,6 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
{
struct cam_sim *sim;
if (mtx == NULL)
return (NULL);
sim = (struct cam_sim *)malloc(sizeof(struct cam_sim),
M_CAMSIM, M_ZERO | M_NOWAIT);
@ -101,16 +101,23 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
void
cam_sim_free(struct cam_sim *sim, int free_devq)
{
struct mtx *mtx = sim->mtx;
int error;
mtx_assert(sim->mtx, MA_OWNED);
if (mtx) {
mtx_assert(mtx, MA_OWNED);
} else {
mtx = &cam_sim_free_mtx;
mtx_lock(mtx);
}
sim->refcount--;
if (sim->refcount > 0) {
error = msleep(sim, sim->mtx, PRIBIO, "simfree", 0);
error = msleep(sim, mtx, PRIBIO, "simfree", 0);
KASSERT(error == 0, ("invalid error value for msleep(9)"));
}
KASSERT(sim->refcount == 0, ("sim->refcount == 0"));
if (sim->mtx == NULL)
mtx_unlock(mtx);
if (free_devq)
cam_simq_free(sim->devq);
@ -120,31 +127,43 @@ cam_sim_free(struct cam_sim *sim, int free_devq)
void
cam_sim_release(struct cam_sim *sim)
{
int lock;
struct mtx *mtx = sim->mtx;
lock = (mtx_owned(sim->mtx) == 0);
if (lock)
CAM_SIM_LOCK(sim);
if (mtx) {
if (!mtx_owned(mtx))
mtx_lock(mtx);
else
mtx = NULL;
} else {
mtx = &cam_sim_free_mtx;
mtx_lock(mtx);
}
KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
sim->refcount--;
if (sim->refcount == 0)
wakeup(sim);
if (lock)
CAM_SIM_UNLOCK(sim);
if (mtx)
mtx_unlock(mtx);
}
void
cam_sim_hold(struct cam_sim *sim)
{
int lock;
struct mtx *mtx = sim->mtx;
lock = (mtx_owned(sim->mtx) == 0);
if (lock)
CAM_SIM_LOCK(sim);
if (mtx) {
if (!mtx_owned(mtx))
mtx_lock(mtx);
else
mtx = NULL;
} else {
mtx = &cam_sim_free_mtx;
mtx_lock(mtx);
}
KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
sim->refcount++;
if (lock)
CAM_SIM_UNLOCK(sim);
if (mtx)
mtx_unlock(mtx);
}
void

View File

@ -2523,7 +2523,7 @@ xpt_action_default(union ccb *start_ccb)
{
struct cam_path *path;
struct cam_sim *sim;
int lock;
struct mtx *mtx;
path = start_ccb->ccb_h.path;
CAM_DEBUG(path, CAM_DEBUG_TRACE,
@ -2681,16 +2681,18 @@ xpt_action_default(union ccb *start_ccb)
case XPT_PATH_INQ:
call_sim:
sim = path->bus->sim;
lock = (mtx_owned(sim->mtx) == 0);
if (lock)
CAM_SIM_LOCK(sim);
mtx = sim->mtx;
if (mtx && !mtx_owned(mtx))
mtx_lock(mtx);
else
mtx = NULL;
CAM_DEBUG(path, CAM_DEBUG_TRACE,
("sim->sim_action: func=%#x\n", start_ccb->ccb_h.func_code));
(*(sim->sim_action))(sim, start_ccb);
CAM_DEBUG(path, CAM_DEBUG_TRACE,
("sim->sim_action: status=%#x\n", start_ccb->ccb_h.status));
if (lock)
CAM_SIM_UNLOCK(sim);
if (mtx)
mtx_unlock(mtx);
break;
case XPT_PATH_STATS:
start_ccb->cpis.last_reset = path->bus->last_reset;
@ -2914,8 +2916,8 @@ xpt_action_default(union ccb *start_ccb)
break;
}
cur_entry->event_enable = csa->event_enable;
cur_entry->event_lock =
mtx_owned(path->bus->sim->mtx) ? 1 : 0;
cur_entry->event_lock = (path->bus->sim->mtx &&
mtx_owned(path->bus->sim->mtx)) ? 1 : 0;
cur_entry->callback_arg = csa->callback_arg;
cur_entry->callback = csa->callback;
SLIST_INSERT_HEAD(async_head, cur_entry, links);
@ -3082,10 +3084,12 @@ xpt_polled_action(union ccb *start_ccb)
struct cam_sim *sim;
struct cam_devq *devq;
struct cam_ed *dev;
struct mtx *mtx;
timeout = start_ccb->ccb_h.timeout * 10;
sim = start_ccb->ccb_h.path->bus->sim;
devq = sim->devq;
mtx = sim->mtx;
dev = start_ccb->ccb_h.path->device;
mtx_unlock(&dev->device_mtx);
@ -3100,9 +3104,11 @@ xpt_polled_action(union ccb *start_ccb)
(--timeout > 0)) {
mtx_unlock(&devq->send_mtx);
DELAY(100);
CAM_SIM_LOCK(sim);
if (mtx)
mtx_lock(mtx);
(*(sim->sim_poll))(sim);
CAM_SIM_UNLOCK(sim);
if (mtx)
mtx_unlock(mtx);
camisr_runqueue();
mtx_lock(&devq->send_mtx);
}
@ -3112,9 +3118,11 @@ xpt_polled_action(union ccb *start_ccb)
if (timeout != 0) {
xpt_action(start_ccb);
while(--timeout > 0) {
CAM_SIM_LOCK(sim);
if (mtx)
mtx_lock(mtx);
(*(sim->sim_poll))(sim);
CAM_SIM_UNLOCK(sim);
if (mtx)
mtx_unlock(mtx);
camisr_runqueue();
if ((start_ccb->ccb_h.status & CAM_STATUS_MASK)
!= CAM_REQ_INPROG)
@ -3271,7 +3279,7 @@ xpt_run_allocq(struct cam_periph *periph, int sleep)
static void
xpt_run_devq(struct cam_devq *devq)
{
int lock;
struct mtx *mtx;
CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_devq\n"));
@ -3361,13 +3369,15 @@ xpt_run_devq(struct cam_devq *devq)
* queued device, rather than the one from the calling bus.
*/
sim = device->sim;
lock = (mtx_owned(sim->mtx) == 0);
if (lock)
CAM_SIM_LOCK(sim);
mtx = sim->mtx;
if (mtx && !mtx_owned(mtx))
mtx_lock(mtx);
else
mtx = NULL;
work_ccb->ccb_h.qos.sim_data = sbinuptime(); // xxx uintprt_t too small 32bit platforms
(*(sim->sim_action))(sim, work_ccb);
if (lock)
CAM_SIM_UNLOCK(sim);
if (mtx)
mtx_unlock(mtx);
mtx_lock(&devq->send_mtx);
}
devq->send_queue.qfrozen_cnt--;
@ -3878,8 +3888,6 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
struct cam_path *path;
cam_status status;
mtx_assert(sim->mtx, MA_OWNED);
sim->bus_id = bus;
new_bus = (struct cam_eb *)malloc(sizeof(*new_bus),
M_CAMXPT, M_NOWAIT|M_ZERO);

View File

@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 1200026 /* Master, propagated to newvers */
#define __FreeBSD_version 1200027 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,