summaryrefslogtreecommitdiffstats
path: root/sys/cam/ctl/scsi_ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/ctl/scsi_ctl.c')
-rw-r--r--sys/cam/ctl/scsi_ctl.c166
1 files changed, 68 insertions, 98 deletions
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index 45acdba..3f50269 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -73,8 +73,7 @@ __FBSDID("$FreeBSD$");
#include <cam/ctl/ctl_error.h>
typedef enum {
- CTLFE_CCB_DEFAULT = 0x00,
- CTLFE_CCB_WAITING = 0x01
+ CTLFE_CCB_DEFAULT = 0x00
} ctlfe_ccb_types;
struct ctlfe_softc {
@@ -82,6 +81,7 @@ struct ctlfe_softc {
path_id_t path_id;
struct cam_sim *sim;
char port_name[DEV_IDLEN];
+ struct mtx lun_softc_mtx;
STAILQ_HEAD(, ctlfe_lun_softc) lun_softc_list;
STAILQ_ENTRY(ctlfe_softc) links;
};
@@ -320,7 +320,6 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
#ifdef CTLFE_INIT_ENABLE
if (ctlfe_num_targets >= ctlfe_max_targets) {
union ccb *ccb;
- struct cam_sim *sim;
ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP,
M_NOWAIT | M_ZERO);
@@ -328,18 +327,12 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
printf("%s: unable to malloc CCB!\n", __func__);
return;
}
- xpt_setup_ccb(&ccb->ccb_h, cpi->ccb_h.path,
- CAM_PRIORITY_NONE);
-
- sim = xpt_path_sim(cpi->ccb_h.path);
+ xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
ccb->knob.xport_specific.valid = KNOB_VALID_ROLE;
ccb->knob.xport_specific.fc.role = KNOB_ROLE_INITIATOR;
- /* We should hold the SIM lock here */
- mtx_assert(sim->mtx, MA_OWNED);
-
xpt_action(ccb);
if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
@@ -381,7 +374,9 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
}
bus_softc->path_id = cpi->ccb_h.path_id;
- bus_softc->sim = xpt_path_sim(cpi->ccb_h.path);
+ bus_softc->sim = xpt_path_sim(path);
+ mtx_init(&bus_softc->lun_softc_mtx, "LUN softc mtx", NULL,
+ MTX_DEF);
STAILQ_INIT(&bus_softc->lun_softc_list);
fe = &bus_softc->fe;
@@ -435,6 +430,7 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
if (retval != 0) {
printf("%s: ctl_frontend_register() failed with "
"error %d!\n", __func__, retval);
+ mtx_destroy(&bus_softc->lun_softc_mtx);
free(bus_softc, M_CTLFE);
break;
} else {
@@ -464,6 +460,7 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
* are no outstanding commands for this frontend?
*/
ctl_frontend_deregister(&softc->fe);
+ mtx_destroy(&softc->lun_softc_mtx);
free(softc, M_CTLFE);
}
break;
@@ -538,19 +535,18 @@ ctlferegister(struct cam_periph *periph, void *arg)
{
struct ctlfe_softc *bus_softc;
struct ctlfe_lun_softc *softc;
- struct cam_sim *sim;
union ccb en_lun_ccb;
cam_status status;
int i;
softc = (struct ctlfe_lun_softc *)arg;
bus_softc = softc->parent_softc;
- sim = xpt_path_sim(periph->path);
TAILQ_INIT(&softc->work_queue);
softc->periph = periph;
- callout_init_mtx(&softc->dma_callout, sim->mtx, /*flags*/ 0);
+ callout_init_mtx(&softc->dma_callout, xpt_path_mtx(periph->path),
+ /*flags*/ 0);
periph->softc = softc;
xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE);
@@ -580,6 +576,7 @@ ctlferegister(struct cam_periph *periph, void *arg)
xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
new_ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
new_ccb->ccb_h.cbfcnp = ctlfedone;
+ new_ccb->ccb_h.flags |= CAM_UNLOCKED;
xpt_action(new_ccb);
softc->atios_sent++;
status = new_ccb->ccb_h.status;
@@ -615,6 +612,7 @@ ctlferegister(struct cam_periph *periph, void *arg)
xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
new_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
new_ccb->ccb_h.cbfcnp = ctlfedone;
+ new_ccb->ccb_h.flags |= CAM_UNLOCKED;
xpt_action(new_ccb);
softc->inots_sent++;
status = new_ccb->ccb_h.status;
@@ -646,6 +644,7 @@ ctlfeoninvalidate(struct cam_periph *periph)
{
union ccb en_lun_ccb;
cam_status status;
+ struct ctlfe_softc *bus_softc;
struct ctlfe_lun_softc *softc;
softc = (struct ctlfe_lun_softc *)periph->softc;
@@ -668,21 +667,22 @@ ctlfeoninvalidate(struct cam_periph *periph)
"INOTs outstanding, %d refs\n", softc->atios_sent -
softc->atios_returned, softc->inots_sent -
softc->inots_returned, periph->refcount);
+
+ bus_softc = softc->parent_softc;
+ mtx_lock(&bus_softc->lun_softc_mtx);
+ STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links);
+ mtx_unlock(&bus_softc->lun_softc_mtx);
}
static void
ctlfecleanup(struct cam_periph *periph)
{
struct ctlfe_lun_softc *softc;
- struct ctlfe_softc *bus_softc;
xpt_print(periph->path, "%s: Called\n", __func__);
softc = (struct ctlfe_lun_softc *)periph->softc;
- bus_softc = softc->parent_softc;
- STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links);
-
/*
* XXX KDM is there anything else that needs to be done here?
*/
@@ -705,14 +705,7 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
start_ccb->ccb_h.ccb_type = CTLFE_CCB_DEFAULT;
ccb_h = TAILQ_FIRST(&softc->work_queue);
- if (periph->immediate_priority <= periph->pinfo.priority) {
- panic("shouldn't get to the CCB waiting case!");
- start_ccb->ccb_h.ccb_type = CTLFE_CCB_WAITING;
- SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
- periph_links.sle);
- periph->immediate_priority = CAM_PRIORITY_NONE;
- wakeup(&periph->ccb_list);
- } else if (ccb_h == NULL) {
+ if (ccb_h == NULL) {
softc->ccbs_freed++;
xpt_release_ccb(start_ccb);
} else {
@@ -791,7 +784,6 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
}
start_ccb->ccb_h.func_code = XPT_ABORT;
start_ccb->cab.abort_ccb = (union ccb *)atio;
- start_ccb->ccb_h.cbfcnp = ctlfedone;
/* Tell the SIM that we've aborted this ATIO */
xpt_action(start_ccb);
@@ -1004,6 +996,7 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
/*data_ptr*/ data_ptr,
/*dxfer_len*/ dxfer_len,
/*timeout*/ 5 * 1000);
+ start_ccb->ccb_h.flags |= CAM_UNLOCKED;
start_ccb->ccb_h.ccb_atio = atio;
if (((flags & CAM_SEND_STATUS) == 0)
&& (io != NULL))
@@ -1011,7 +1004,9 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
softc->ctios_sent++;
+ cam_periph_unlock(periph);
xpt_action(start_ccb);
+ cam_periph_lock(periph);
if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
cam_release_devq(periph->path,
@@ -1148,7 +1143,10 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
struct ctlfe_softc *bus_softc;
struct ccb_accept_tio *atio = NULL;
union ctl_io *io = NULL;
+ struct mtx *mtx;
+ KASSERT((done_ccb->ccb_h.flags & CAM_UNLOCKED) != 0,
+ ("CCB in ctlfedone() without CAM_UNLOCKED flag"));
#ifdef CTLFE_DEBUG
printf("%s: entered, func_code = %#x, type = %#lx\n", __func__,
done_ccb->ccb_h.func_code, done_ccb->ccb_h.ccb_type);
@@ -1156,12 +1154,8 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
softc = (struct ctlfe_lun_softc *)periph->softc;
bus_softc = softc->parent_softc;
-
- if (done_ccb->ccb_h.ccb_type == CTLFE_CCB_WAITING) {
- panic("shouldn't get to the CCB waiting case!");
- wakeup(&done_ccb->ccb_h.cbfcnp);
- return;
- }
+ mtx = cam_periph_mtx(periph);
+ mtx_lock(mtx);
/*
* If the peripheral is invalid, ATIOs and immediate notify CCBs
@@ -1177,7 +1171,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
case XPT_IMMEDIATE_NOTIFY:
case XPT_NOTIFY_ACKNOWLEDGE:
ctlfe_free_ccb(periph, done_ccb);
- return;
+ goto out;
default:
break;
}
@@ -1215,6 +1209,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_schedule(periph, /*priority*/ 1);
break;
}
+ mtx_unlock(mtx);
ctl_zero_io(io);
/* Save pointers on both sides */
@@ -1271,7 +1266,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
#endif
ctl_queue(io);
- break;
+ return;
}
case XPT_CONT_TARGET_IO: {
int srr = 0;
@@ -1333,7 +1328,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
TAILQ_INSERT_HEAD(&softc->work_queue, &atio->ccb_h,
periph_links.tqe);
xpt_schedule(periph, /*priority*/ 1);
- return;
+ break;
}
/*
@@ -1359,10 +1354,11 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
}
if (periph->flags & CAM_PERIPH_INVALID) {
ctlfe_free_ccb(periph, (union ccb *)atio);
- return;
} else {
- xpt_action((union ccb *)atio);
softc->atios_sent++;
+ mtx_unlock(mtx);
+ xpt_action((union ccb *)atio);
+ return;
}
} else {
struct ctlfe_lun_cmd_info *cmd_info;
@@ -1478,10 +1474,12 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
/*dxfer_len*/ dxfer_len,
/*timeout*/ 5 * 1000);
+ csio->ccb_h.flags |= CAM_UNLOCKED;
csio->resid = 0;
csio->ccb_h.ccb_atio = atio;
io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
softc->ctios_sent++;
+ mtx_unlock(mtx);
xpt_action((union ccb *)csio);
} else {
/*
@@ -1490,10 +1488,12 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
*/
softc->ccbs_freed++;
xpt_release_ccb(done_ccb);
+ mtx_unlock(mtx);
/* Call the backend move done callback */
io->scsiio.be_move_done(io);
}
+ return;
}
break;
}
@@ -1614,7 +1614,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
ctl_free_io(io);
ctlfe_free_ccb(periph, done_ccb);
- return;
+ goto out;
}
if (send_ctl_io != 0) {
ctl_queue(io);
@@ -1651,12 +1651,6 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_action(done_ccb);
softc->inots_sent++;
break;
- case XPT_ABORT:
- /*
- * XPT_ABORT is an immediate CCB, we shouldn't get here.
- */
- panic("%s: XPT_ABORT CCB returned!", __func__);
- break;
case XPT_SET_SIM_KNOB:
case XPT_GET_SIM_KNOB:
break;
@@ -1665,6 +1659,9 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
done_ccb->ccb_h.func_code);
break;
}
+
+out:
+ mtx_unlock(mtx);
}
static void
@@ -1674,17 +1671,12 @@ ctlfe_onoffline(void *arg, int online)
union ccb *ccb;
cam_status status;
struct cam_path *path;
- struct cam_sim *sim;
int set_wwnn;
bus_softc = (struct ctlfe_softc *)arg;
set_wwnn = 0;
- sim = bus_softc->sim;
-
- mtx_assert(sim->mtx, MA_OWNED);
-
status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP) {
@@ -1844,12 +1836,8 @@ ctlfe_online(void *arg)
struct cam_path *path;
cam_status status;
struct ctlfe_lun_softc *lun_softc;
- struct cam_sim *sim;
bus_softc = (struct ctlfe_softc *)arg;
- sim = bus_softc->sim;
-
- CAM_SIM_LOCK(sim);
/*
* Create the wildcard LUN before bringing the port online.
@@ -1860,7 +1848,6 @@ ctlfe_online(void *arg)
if (status != CAM_REQ_CMP) {
printf("%s: unable to create path for wildcard periph\n",
__func__);
- CAM_SIM_UNLOCK(sim);
return;
}
@@ -1870,15 +1857,16 @@ ctlfe_online(void *arg)
xpt_print(path, "%s: unable to allocate softc for "
"wildcard periph\n", __func__);
xpt_free_path(path);
- CAM_SIM_UNLOCK(sim);
return;
}
+ xpt_path_lock(path);
lun_softc->parent_softc = bus_softc;
lun_softc->flags |= CTLFE_LUN_WILDCARD;
+ mtx_lock(&bus_softc->lun_softc_mtx);
STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, lun_softc, links);
-
+ mtx_unlock(&bus_softc->lun_softc_mtx);
status = cam_periph_alloc(ctlferegister,
ctlfeoninvalidate,
@@ -1901,11 +1889,10 @@ ctlfe_online(void *arg)
entry->status_text : "Unknown", status);
}
- xpt_free_path(path);
-
ctlfe_onoffline(arg, /*online*/ 1);
- CAM_SIM_UNLOCK(sim);
+ xpt_path_unlock(path);
+ xpt_free_path(path);
}
static void
@@ -1915,14 +1902,8 @@ ctlfe_offline(void *arg)
struct cam_path *path;
cam_status status;
struct cam_periph *periph;
- struct cam_sim *sim;
bus_softc = (struct ctlfe_softc *)arg;
- sim = bus_softc->sim;
-
- CAM_SIM_LOCK(sim);
-
- ctlfe_onoffline(arg, /*online*/ 0);
/*
* Disable the wildcard LUN for this port now that we have taken
@@ -1932,19 +1913,20 @@ ctlfe_offline(void *arg)
bus_softc->path_id, CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP) {
- CAM_SIM_UNLOCK(sim);
printf("%s: unable to create path for wildcard periph\n",
__func__);
return;
}
+ xpt_path_lock(path);
+
+ ctlfe_onoffline(arg, /*online*/ 0);
if ((periph = cam_periph_find(path, "ctl")) != NULL)
cam_periph_invalidate(periph);
+ xpt_path_unlock(path);
xpt_free_path(path);
-
- CAM_SIM_UNLOCK(sim);
}
static int
@@ -1970,15 +1952,13 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
struct ctlfe_lun_softc *softc;
struct cam_path *path;
struct cam_periph *periph;
- struct cam_sim *sim;
cam_status status;
bus_softc = (struct ctlfe_softc *)arg;
- sim = bus_softc->sim;
- status = xpt_create_path_unlocked(&path, /*periph*/ NULL,
- bus_softc->path_id,
- targ_id.id, lun_id);
+ status = xpt_create_path(&path, /*periph*/ NULL,
+ bus_softc->path_id,
+ targ_id.id, lun_id);
/* XXX KDM need some way to return status to CTL here? */
if (status != CAM_REQ_CMP) {
printf("%s: could not create path, status %#x\n", __func__,
@@ -1987,18 +1967,20 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
}
softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO);
- CAM_SIM_LOCK(sim);
+ xpt_path_lock(path);
periph = cam_periph_find(path, "ctl");
if (periph != NULL) {
/* We've already got a periph, no need to alloc a new one. */
+ xpt_path_unlock(path);
xpt_free_path(path);
free(softc, M_CTLFE);
- CAM_SIM_UNLOCK(sim);
return (0);
}
softc->parent_softc = bus_softc;
+ mtx_lock(&bus_softc->lun_softc_mtx);
STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, softc, links);
+ mtx_unlock(&bus_softc->lun_softc_mtx);
status = cam_periph_alloc(ctlferegister,
ctlfeoninvalidate,
@@ -2011,10 +1993,8 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
0,
softc);
+ xpt_path_unlock(path);
xpt_free_path(path);
-
- CAM_SIM_UNLOCK(sim);
-
return (0);
}
@@ -2027,12 +2007,10 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
{
struct ctlfe_softc *softc;
struct ctlfe_lun_softc *lun_softc;
- struct cam_sim *sim;
softc = (struct ctlfe_softc *)arg;
- sim = softc->sim;
- CAM_SIM_LOCK(sim);
+ mtx_lock(&softc->lun_softc_mtx);
STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) {
struct cam_path *path;
@@ -2044,16 +2022,18 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
}
}
if (lun_softc == NULL) {
- CAM_SIM_UNLOCK(sim);
+ mtx_unlock(&softc->lun_softc_mtx);
printf("%s: can't find target %d lun %d\n", __func__,
targ_id.id, lun_id);
return (1);
}
+ cam_periph_acquire(lun_softc->periph);
+ mtx_unlock(&softc->lun_softc_mtx);
+ cam_periph_lock(lun_softc->periph);
cam_periph_invalidate(lun_softc->periph);
-
- CAM_SIM_UNLOCK(sim);
-
+ cam_periph_unlock(lun_softc->periph);
+ cam_periph_release(lun_softc->periph);
return (0);
}
@@ -2064,12 +2044,6 @@ ctlfe_dump_sim(struct cam_sim *sim)
printf("%s%d: max tagged openings: %d, max dev openings: %d\n",
sim->sim_name, sim->unit_number,
sim->max_tagged_dev_openings, sim->max_dev_openings);
- printf("%s%d: max_ccbs: %u, ccb_count: %u\n",
- sim->sim_name, sim->unit_number,
- sim->max_ccbs, sim->ccb_count);
- printf("%s%d: ccb_freeq is %sempty\n",
- sim->sim_name, sim->unit_number,
- (SLIST_FIRST(&sim->ccb_freeq) == NULL) ? "" : "NOT ");
printf("\n");
}
@@ -2200,17 +2174,13 @@ static void
ctlfe_datamove_done(union ctl_io *io)
{
union ccb *ccb;
- struct cam_sim *sim;
struct cam_periph *periph;
struct ctlfe_lun_softc *softc;
ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
- sim = xpt_path_sim(ccb->ccb_h.path);
-
- CAM_SIM_LOCK(sim);
-
periph = xpt_path_periph(ccb->ccb_h.path);
+ cam_periph_lock(periph);
softc = (struct ctlfe_lun_softc *)periph->softc;
@@ -2255,7 +2225,7 @@ ctlfe_datamove_done(union ctl_io *io)
xpt_schedule(periph, /*priority*/ 1);
}
- CAM_SIM_UNLOCK(sim);
+ cam_periph_unlock(periph);
}
static void
OpenPOWER on IntegriCloud