summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2017-04-04 17:59:10 +0000
committermav <mav@FreeBSD.org>2017-04-04 17:59:10 +0000
commitbf1725b6d0368e24bcef41677d339fd2bbaee04a (patch)
tree5c712cf8807aeb6f43c8a2a60cb0a2d0910fa9ae /sys/cam
parent96da464044374cced2d40f90774e1c1efb428fd7 (diff)
downloadFreeBSD-src-bf1725b6d0368e24bcef41677d339fd2bbaee04a.zip
FreeBSD-src-bf1725b6d0368e24bcef41677d339fd2bbaee04a.tar.gz
MFC r315673, r315674: 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().
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/cam_sim.c55
-rw-r--r--sys/cam/cam_xpt.c61
2 files changed, 72 insertions, 44 deletions
diff --git a/sys/cam/cam_sim.c b/sys/cam/cam_sim.c
index 9a8c666..a024d06 100644
--- a/sys/cam/cam_sim.c
+++ b/sys/cam/cam_sim.c
@@ -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
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 628a128..47b99bc 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -2486,7 +2486,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,
@@ -2647,16 +2647,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;
@@ -2878,8 +2880,8 @@ call_sim:
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);
@@ -3044,10 +3046,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);
@@ -3062,9 +3066,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);
}
@@ -3074,9 +3080,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)
@@ -3234,7 +3242,7 @@ static void
xpt_run_devq(struct cam_devq *devq)
{
char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
- int lock;
+ struct mtx *mtx;
CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_devq\n"));
@@ -3336,13 +3344,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--;
@@ -3848,8 +3858,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);
@@ -4206,7 +4214,7 @@ xpt_async_bcast(struct async_list *async_head,
struct cam_path *path, void *async_arg)
{
struct async_node *cur_entry;
- int lock;
+ struct mtx *mtx;
cur_entry = SLIST_FIRST(async_head);
while (cur_entry != NULL) {
@@ -4218,14 +4226,15 @@ xpt_async_bcast(struct async_list *async_head,
*/
next_entry = SLIST_NEXT(cur_entry, links);
if ((cur_entry->event_enable & async_code) != 0) {
- lock = cur_entry->event_lock;
- if (lock)
- CAM_SIM_LOCK(path->device->sim);
+ mtx = cur_entry->event_lock ?
+ path->device->sim->mtx : NULL;
+ if (mtx)
+ mtx_lock(mtx);
cur_entry->callback(cur_entry->callback_arg,
async_code, path,
async_arg);
- if (lock)
- CAM_SIM_UNLOCK(path->device->sim);
+ if (mtx)
+ mtx_unlock(mtx);
}
cur_entry = next_entry;
}
OpenPOWER on IntegriCloud