Changeset View
Changeset View
Standalone View
Standalone View
sys/cam/cam_xpt.c
Show First 20 Lines • Show All 3,116 Lines • ▼ Show 20 Lines | if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) != 0) | ||||
xpt_freeze_devq(path, 1); | xpt_freeze_devq(path, 1); | ||||
start_ccb->ccb_h.status = CAM_REQ_CMP; | start_ccb->ccb_h.status = CAM_REQ_CMP; | ||||
break; | break; | ||||
case XPT_REPROBE_LUN: | case XPT_REPROBE_LUN: | ||||
xpt_async(AC_INQ_CHANGED, path, NULL); | xpt_async(AC_INQ_CHANGED, path, NULL); | ||||
start_ccb->ccb_h.status = CAM_REQ_CMP; | start_ccb->ccb_h.status = CAM_REQ_CMP; | ||||
xpt_done(start_ccb); | xpt_done(start_ccb); | ||||
break; | break; | ||||
case XPT_DEFERRED_CALLBACK: | |||||
case XPT_ASYNC: | case XPT_ASYNC: | ||||
/* | /* | ||||
* Queue the async operation so it can be run from a sleepable | * Queue the async operation so it can be run from a sleepable | ||||
* context. | * context. | ||||
*/ | */ | ||||
start_ccb->ccb_h.status = CAM_REQ_CMP; | start_ccb->ccb_h.status = CAM_REQ_CMP; | ||||
mtx_lock(&cam_async.cam_doneq_mtx); | mtx_lock(&cam_async.cam_doneq_mtx); | ||||
STAILQ_INSERT_TAIL(&cam_async.cam_doneq, &start_ccb->ccb_h, sim_links.stqe); | STAILQ_INSERT_TAIL(&cam_async.cam_doneq, &start_ccb->ccb_h, sim_links.stqe); | ||||
▲ Show 20 Lines • Show All 1,206 Lines • ▼ Show 20 Lines | if ((cur_entry->event_enable & async_code) != 0) { | ||||
cur_entry->callback(cur_entry->callback_arg, | cur_entry->callback(cur_entry->callback_arg, | ||||
async_code, path, | async_code, path, | ||||
async_arg); | async_arg); | ||||
if (mtx) | if (mtx) | ||||
mtx_unlock(mtx); | mtx_unlock(mtx); | ||||
} | } | ||||
cur_entry = next_entry; | cur_entry = next_entry; | ||||
} | } | ||||
} | |||||
/* Note: periph will always be NULL */ | |||||
static void | |||||
xpt_dc_process(struct cam_periph *periph, union ccb *ccb) | |||||
{ | |||||
struct cam_eb *bus; | |||||
struct cam_path *path; | |||||
void *arg; | |||||
u_int32_t code; | |||||
path = ccb->ccb_h.path; | |||||
code = ccb->cdc.code; | |||||
arg = ccb->cdc.arg_ptr; | |||||
CAM_DEBUG(path, CAM_DEBUG_TRACE | CAM_DEBUG_INFO, | |||||
("xpt_deffered_callback(%s)\n", xpt_async_string(code))); | |||||
bus = path->bus; | |||||
mav: Unused variable bus. | |||||
ccb->cdc.defferred_callback(periph, code, path, arg)l | |||||
mavUnsubmitted Not Done Inline ActionsTypo: s/l/;/ mav: Typo: s/l/;/ | |||||
if (path->device != NULL && path->device->lun_id != CAM_LUN_WILDCARD) | |||||
xpt_release_devq(path, 1, TRUE); | |||||
else | |||||
xpt_release_simq(path->bus->sim, TRUE); | |||||
if (ccb->cdc.arg_size > 0) | |||||
free(arg, M_CAMXPT); | |||||
xpt_free_path(path); | |||||
xpt_free_ccb(ccb); | |||||
} | |||||
/* | |||||
* Defer a single callback. The deferred callback is similar to an async | |||||
* callback, except it's is a call to a specific function instead of a | |||||
* dispatched call based on the target device. We pass in path information, but | |||||
* we clone the path in case this is used by code that destroys the path (like | |||||
* camperiphfree). We wind up calling this function with a first argument of | |||||
* NULL to indicate no async context, and callbacks that use this must tolerate | |||||
* that for the code they pass in here. We also assume that the periph in the | |||||
* path is 'unstable' so we NULL that out. The callback must be tolerant of that | |||||
a * as well. | |||||
*/ | |||||
void | |||||
xpt_deferred_callback(ac_callback_t *deferred_callback, uint32_t code, | |||||
struct cam_path *path, void *arg, size_t arglen) | |||||
{ | |||||
union ccb *ccb; | |||||
struct ccb_deferred_callback *cdc; | |||||
int size; | |||||
ccb = xpt_alloc_ccb_nowait(); | |||||
if (ccb == NULL) { | |||||
xpt_print(path, "Can't allocate CCB to defer %s\n", | |||||
xpt_async_string(code)); | |||||
return; | |||||
} | |||||
if (xpt_clone_path(&ccb->ccb_h.path, path) != 0) { | |||||
xpt_print(path, "Can't allocate path to defer %s\n", | |||||
xpt_async_string(code)); | |||||
xpt_free_ccb(ccb); | |||||
return; | |||||
} | |||||
cdc = &ccb->cdc; | |||||
cdc->ccb_h.path->periph = NULL; | |||||
cdc->ccb_h.func_code = XPT_DEFERRED_CALLBACK; | |||||
cdc->ccb_h.cbfcnp = xpt_dc_process; | |||||
cdc->ccb_h.flags |= CAM_UNLOCKED; | |||||
cdc->deferred_callback = deferred_callback; | |||||
cdc->code = code; | |||||
cdc->arg_size = 0; | |||||
if (arglen > 0 && arg != NULL) { | |||||
cdc->arg_ptr = malloc(arglen, M_CAMXPT, M_NOWAIT); | |||||
if (cdc->arg_ptr == NULL) { | |||||
xpt_print(path, "Can't allocate argument to defer %s\n", | |||||
xpt_async_string(code)); | |||||
xpt_free_path(ccb->ccb_h.path); | |||||
xpt_free_ccb(ccb); | |||||
return; | |||||
} | |||||
memcpy(cdc->arg_ptr, arg, arglen); | |||||
cdc->arg_size = arglen; | |||||
} | |||||
/* | |||||
* Freeze processing of other events while we process this out of band | |||||
*/ | |||||
if (path->device != NULL && path->device->lun_id != CAM_LUN_WILDCARD) | |||||
xpt_freeze_devq(path, 1); | |||||
else | |||||
xpt_freeze_simq(path->bus->sim, 1); | |||||
xpt_action(ccb); | |||||
} | } | ||||
void | void | ||||
xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg) | xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg) | ||||
{ | { | ||||
union ccb *ccb; | union ccb *ccb; | ||||
int size; | int size; | ||||
▲ Show 20 Lines • Show All 1,267 Lines • Show Last 20 Lines |
Unused variable bus.