svn commit: r237208 - in stable/9/sys: conf dev/isp
Matt Jacob
mjacob at FreeBSD.org
Sun Jun 17 21:28:12 UTC 2012
Author: mjacob
Date: Sun Jun 17 21:28:11 2012
New Revision: 237208
URL: http://svn.freebsd.org/changeset/base/237208
Log:
MFC of r236427
Clean up and complete the incomplete deferred enable code.
Make the default role NONE if target mode is selected. This
allows ctl(8) to switch to/from target mode via knob settings.
If we default to role 'none', this causes a reset of the
24XX f/w which then causes initiators to wake up and notice
when we come online.
Modified:
stable/9/sys/conf/NOTES
stable/9/sys/dev/isp/isp.c
stable/9/sys/dev/isp/isp_freebsd.c
stable/9/sys/dev/isp/isp_freebsd.h
stable/9/sys/dev/isp/ispvar.h
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/conf/ (props changed)
stable/9/sys/dev/ (props changed)
stable/9/sys/dev/isp/ (props changed)
Modified: stable/9/sys/conf/NOTES
==============================================================================
--- stable/9/sys/conf/NOTES Sun Jun 17 21:07:27 2012 (r237207)
+++ stable/9/sys/conf/NOTES Sun Jun 17 21:28:11 2012 (r237208)
@@ -1592,7 +1592,7 @@ options ISP_TARGET_MODE=1
#
# ISP_INTERNAL_TARGET (trivial internal disk target, for testing)
#
-options ISP_DEFAULT_ROLES=2
+options ISP_DEFAULT_ROLES=0
# Options used in dev/sym/ (Symbios SCSI driver).
#options SYM_SETUP_LP_PROBE_MAP #-Low Priority Probe Map (bits)
Modified: stable/9/sys/dev/isp/isp.c
==============================================================================
--- stable/9/sys/dev/isp/isp.c Sun Jun 17 21:07:27 2012 (r237207)
+++ stable/9/sys/dev/isp/isp.c Sun Jun 17 21:28:11 2012 (r237208)
@@ -2277,6 +2277,11 @@ isp_port_login(ispsoftc_t *isp, uint16_t
}
}
+/*
+ * Pre-24XX fabric port logout
+ *
+ * Note that portid is not used
+ */
static int
isp_port_logout(ispsoftc_t *isp, uint16_t handle, uint32_t portid)
{
@@ -2721,7 +2726,7 @@ not_on_fabric:
* layer appropriately).
*
* We also do initiator map target id assignment here for new initiator
- * devices and refresh old ones ot make sure that they point to the corret
+ * devices and refresh old ones ot make sure that they point to the correct
* entities.
*/
static int
Modified: stable/9/sys/dev/isp/isp_freebsd.c
==============================================================================
--- stable/9/sys/dev/isp/isp_freebsd.c Sun Jun 17 21:07:27 2012 (r237207)
+++ stable/9/sys/dev/isp/isp_freebsd.c Sun Jun 17 21:28:11 2012 (r237208)
@@ -773,6 +773,9 @@ isp_free_pcmd(ispsoftc_t *isp, union ccb
*/
#ifdef ISP_TARGET_MODE
+static ISP_INLINE void isp_tmlock(ispsoftc_t *, const char *);
+static ISP_INLINE void isp_tmunlk(ispsoftc_t *);
+static ISP_INLINE int is_any_lun_enabled(ispsoftc_t *, int);
static ISP_INLINE int is_lun_enabled(ispsoftc_t *, int, lun_id_t);
static ISP_INLINE tstate_t *get_lun_statep(ispsoftc_t *, int, lun_id_t);
static ISP_INLINE tstate_t *get_lun_statep_from_tag(ispsoftc_t *, int, uint32_t);
@@ -786,10 +789,11 @@ static ISP_INLINE void isp_put_ntpd(isps
static cam_status create_lun_state(ispsoftc_t *, int, struct cam_path *, tstate_t **);
static void destroy_lun_state(ispsoftc_t *, tstate_t *);
static void isp_enable_lun(ispsoftc_t *, union ccb *);
-static void isp_enable_deferred_luns(ispsoftc_t *, int);
+static cam_status isp_enable_deferred_luns(ispsoftc_t *, int);
static cam_status isp_enable_deferred(ispsoftc_t *, int, lun_id_t);
static void isp_disable_lun(ispsoftc_t *, union ccb *);
static int isp_enable_target_mode(ispsoftc_t *, int);
+static int isp_disable_target_mode(ispsoftc_t *, int);
static void isp_ledone(ispsoftc_t *, lun_entry_t *);
static timeout_t isp_refire_putback_atio;
static void isp_complete_ctio(union ccb *);
@@ -807,6 +811,40 @@ static void isp_handle_platform_target_t
static void isp_target_mark_aborted(ispsoftc_t *, union ccb *);
static void isp_target_mark_aborted_early(ispsoftc_t *, tstate_t *, uint32_t);
+static ISP_INLINE void
+isp_tmlock(ispsoftc_t *isp, const char *msg)
+{
+ while (isp->isp_osinfo.tmbusy) {
+ isp->isp_osinfo.tmwanted = 1;
+ mtx_sleep(isp, &isp->isp_lock, PRIBIO, msg, 0);
+ }
+ isp->isp_osinfo.tmbusy = 1;
+}
+
+static ISP_INLINE void
+isp_tmunlk(ispsoftc_t *isp)
+{
+ isp->isp_osinfo.tmbusy = 0;
+ if (isp->isp_osinfo.tmwanted) {
+ isp->isp_osinfo.tmwanted = 0;
+ wakeup(isp);
+ }
+}
+
+static ISP_INLINE int
+is_any_lun_enabled(ispsoftc_t *isp, int bus)
+{
+ struct tslist *lhp;
+ int i;
+
+ for (i = 0; i < LUN_HASH_SIZE; i++) {
+ ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
+ if (SLIST_FIRST(lhp))
+ return (1);
+ }
+ return (0);
+}
+
static ISP_INLINE int
is_lun_enabled(ispsoftc_t *isp, int bus, lun_id_t lun)
{
@@ -909,6 +947,7 @@ get_ntp_from_tagdata(ispsoftc_t *isp, ui
}
return (NULL);
}
+
static ISP_INLINE void
rls_lun_statep(ispsoftc_t *isp, tstate_t *tptr)
{
@@ -1050,7 +1089,7 @@ create_lun_state(ispsoftc_t *isp, int bu
if (is_lun_enabled(isp, bus, lun)) {
return (CAM_LUN_ALRDY_ENA);
}
- tptr = (tstate_t *) malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT|M_ZERO);
+ tptr = malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT|M_ZERO);
if (tptr == NULL) {
return (CAM_RESRC_UNAVAIL);
}
@@ -1079,10 +1118,12 @@ static ISP_INLINE void
destroy_lun_state(ispsoftc_t *isp, tstate_t *tptr)
{
struct tslist *lhp;
+
KASSERT((tptr->hold != 0), ("tptr is not held"));
KASSERT((tptr->hold == 1), ("tptr still held (%d)", tptr->hold));
ISP_GET_PC_ADDR(isp, cam_sim_bus(xpt_path_sim(tptr->owner)), lun_hash[LUN_HASH_FUNC(xpt_path_lun_id(tptr->owner))], lhp);
SLIST_REMOVE(lhp, tptr, tstate, next);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "destroyed tstate\n");
xpt_free_path(tptr->owner);
free(tptr, M_DEVBUF);
}
@@ -1098,12 +1139,14 @@ isp_enable_lun(ispsoftc_t *isp, union cc
target_id_t target;
lun_id_t lun;
+
/*
* We only support either a wildcard target/lun or a target ID of zero and a non-wildcard lun
*/
bus = XS_CHANNEL(ccb);
target = ccb->ccb_h.target_id;
lun = ccb->ccb_h.target_lun;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0|ISP_LOGCONFIG, ccb->ccb_h.path, "enabling lun %u\n", lun);
if (target != CAM_TARGET_WILDCARD && target != 0) {
ccb->ccb_h.status = CAM_TID_INVALID;
xpt_done(ccb);
@@ -1127,11 +1170,7 @@ isp_enable_lun(ispsoftc_t *isp, union cc
/*
* Wait until we're not busy with the lun enables subsystem
*/
- while (isp->isp_osinfo.tmbusy) {
- isp->isp_osinfo.tmwanted = 1;
- mtx_sleep(isp, &isp->isp_lock, PRIBIO, "want_isp_enable_lun", 0);
- }
- isp->isp_osinfo.tmbusy = 1;
+ isp_tmlock(isp, "isp_enable_lun");
/*
* This is as a good a place as any to check f/w capabilities.
@@ -1200,7 +1239,7 @@ isp_enable_lun(ispsoftc_t *isp, union cc
if (tm_enabled == 0) {
ISP_SET_PC(isp, bus, tm_enable_defer, 1);
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_print(ccb->ccb_h.path, "Target Mode Not Enabled Yet- Lun Enables Deferred\n");
+ xpt_print(ccb->ccb_h.path, "Target Mode not enabled yet- lun enable deferred\n");
goto done;
}
@@ -1210,37 +1249,78 @@ isp_enable_lun(ispsoftc_t *isp, union cc
ccb->ccb_h.status = isp_enable_deferred(isp, bus, lun);
done:
- if (ccb->ccb_h.status != CAM_REQ_CMP && tptr) {
- destroy_lun_state(isp, tptr);
- tptr = NULL;
+ if (ccb->ccb_h.status != CAM_REQ_CMP) {
+ if (tptr) {
+ destroy_lun_state(isp, tptr);
+ tptr = NULL;
+ }
+ } else {
+ tptr->enabled = 1;
}
if (tptr) {
rls_lun_statep(isp, tptr);
}
- isp->isp_osinfo.tmbusy = 0;
- if (isp->isp_osinfo.tmwanted) {
- isp->isp_osinfo.tmwanted = 0;
- wakeup(isp);
- }
+
+ /*
+ * And we're outta here....
+ */
+ isp_tmunlk(isp);
xpt_done(ccb);
}
-static void
+static cam_status
isp_enable_deferred_luns(ispsoftc_t *isp, int bus)
{
+ tstate_t *tptr = NULL;
+ struct tslist *lhp;
+ int i, n;
+
+ ISP_GET_PC(isp, bus, tm_enabled, i);
+ if (i == 1) {
+ return (CAM_REQ_CMP);
+ }
+ ISP_GET_PC(isp, bus, tm_enable_defer, i);
+ if (i == 0) {
+ return (CAM_REQ_CMP);
+ }
/*
- * XXX: not entirely implemented yet
+ * If this succeeds, it will set tm_enable
*/
- (void) isp_enable_deferred(isp, bus, 0);
+ if (isp_enable_target_mode(isp, bus)) {
+ return (CAM_REQ_CMP_ERR);
+ }
+ isp_tmlock(isp, "isp_enable_deferred_luns");
+ for (n = i = 0; i < LUN_HASH_SIZE; i++) {
+ ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
+ SLIST_FOREACH(tptr, lhp, next) {
+ tptr->hold++;
+ if (tptr->enabled == 0) {
+ if (isp_enable_deferred(isp, bus, xpt_path_lun_id(tptr->owner)) == 0) {
+ tptr->enabled = 1;
+ n++;
+ }
+ } else {
+ n++;
+ }
+ tptr->hold--;
+ }
+ }
+ isp_tmunlk(isp);
+ if (n == 0) {
+ return (CAM_REQ_CMP_ERR);
+ }
+ ISP_SET_PC(isp, bus, tm_enable_defer, 0);
+ return (CAM_REQ_CMP);
}
-static uint32_t
+static cam_status
isp_enable_deferred(ispsoftc_t *isp, int bus, lun_id_t lun)
{
cam_status status;
+ int luns_already_enabled = ISP_FC_PC(isp, bus)->tm_luns_enabled;
isp_prt(isp, ISP_LOGTINFO, "%s: bus %d lun %u", __func__, bus, lun);
- if (IS_24XX(isp) || (IS_FC(isp) && ISP_FC_PC(isp, bus)->tm_luns_enabled)) {
+ if (IS_24XX(isp) || (IS_FC(isp) && luns_already_enabled)) {
status = CAM_REQ_CMP;
} else {
int cmd_cnt, not_cnt;
@@ -1261,10 +1341,9 @@ isp_enable_deferred(ispsoftc_t *isp, int
}
isp->isp_osinfo.rptr = NULL;
}
-
if (status == CAM_REQ_CMP) {
ISP_SET_PC(isp, bus, tm_luns_enabled, 1);
- isp_prt(isp, ISP_LOGTINFO, "bus %d lun %u now enabled for target mode", bus, lun);
+ isp_prt(isp, ISP_LOGCONFIG|ISP_LOGTINFO, "bus %d lun %u now enabled for target mode", bus, lun);
}
return (status);
}
@@ -1281,11 +1360,13 @@ isp_disable_lun(ispsoftc_t *isp, union c
bus = XS_CHANNEL(ccb);
target = ccb->ccb_h.target_id;
lun = ccb->ccb_h.target_lun;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0|ISP_LOGCONFIG, ccb->ccb_h.path, "disabling lun %u\n", lun);
if (target != CAM_TARGET_WILDCARD && target != 0) {
ccb->ccb_h.status = CAM_TID_INVALID;
xpt_done(ccb);
return;
}
+
if (target == CAM_TARGET_WILDCARD && lun != CAM_LUN_WILDCARD) {
ccb->ccb_h.status = CAM_LUN_INVALID;
xpt_done(ccb);
@@ -1297,18 +1378,11 @@ isp_disable_lun(ispsoftc_t *isp, union c
xpt_done(ccb);
return;
}
- if (isp->isp_dblev & ISP_LOGTDEBUG0) {
- xpt_print(ccb->ccb_h.path, "enabling lun 0x%x on channel %d\n", lun, bus);
- }
/*
* See if we're busy disabling a lun now.
*/
- while (isp->isp_osinfo.tmbusy) {
- isp->isp_osinfo.tmwanted = 1;
- mtx_sleep(isp, &isp->isp_lock, PRIBIO, "want_isp_disable_lun", 0);
- }
- isp->isp_osinfo.tmbusy = 1;
+ isp_tmlock(isp, "isp_disable_lun");
status = CAM_REQ_INPROG;
/*
@@ -1333,85 +1407,86 @@ isp_disable_lun(ispsoftc_t *isp, union c
if (IS_FC(isp)) {
lun = 0;
}
-
isp->isp_osinfo.rptr = &status;
if (isp_lun_cmd(isp, RQSTYPE_ENABLE_LUN, bus, lun, 0, 0)) {
status = CAM_RESRC_UNAVAIL;
} else {
mtx_sleep(ccb, &isp->isp_lock, PRIBIO, "isp_disable_lun", 0);
}
+ isp->isp_osinfo.rptr = NULL;
done:
- ccb->ccb_h.status = status;
if (status == CAM_REQ_CMP) {
- xpt_print(ccb->ccb_h.path, "now disabled for target mode\n");
+ tptr->enabled = 0;
+ /*
+ * If we have no more luns enabled for this bus, delete all tracked wwns for it (if we are FC)
+ * and disable target mode.
+ */
+ if (is_any_lun_enabled(isp, bus) == 0) {
+ isp_del_all_wwn_entries(isp, bus);
+ if (isp_disable_target_mode(isp, bus)) {
+ status = CAM_REQ_CMP_ERR;
+ }
+ }
}
- if (tptr) {
+ ccb->ccb_h.status = status;
+ if (status == CAM_REQ_CMP) {
+ xpt_print(ccb->ccb_h.path, "lun now disabled for target mode\n");
destroy_lun_state(isp, tptr);
+ } else {
+ if (tptr)
+ rls_lun_statep(isp, tptr);
}
- isp->isp_osinfo.rptr = NULL;
- isp->isp_osinfo.tmbusy = 0;
- if (isp->isp_osinfo.tmwanted) {
- isp->isp_osinfo.tmwanted = 0;
- wakeup(isp);
- }
+ isp_tmunlk(isp);
xpt_done(ccb);
}
static int
isp_enable_target_mode(ispsoftc_t *isp, int bus)
{
- int ct;
+ int tm_enabled;
- ISP_GET_PC(isp, bus, tm_enabled, ct);
- if (ct != 0) {
+ ISP_GET_PC(isp, bus, tm_enabled, tm_enabled);
+ if (tm_enabled != 0) {
return (0);
}
-
if (IS_SCSI(isp)) {
mbreg_t mbs;
-
MBSINIT(&mbs, MBOX_ENABLE_TARGET_MODE, MBLOGALL, 0);
mbs.param[0] = MBOX_ENABLE_TARGET_MODE;
mbs.param[1] = ENABLE_TARGET_FLAG|ENABLE_TQING_FLAG;
mbs.param[2] = bus << 7;
if (isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs) < 0 || mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_prt(isp, ISP_LOGERR, "Unable to add Target Role to Bus %d", bus);
+ isp_prt(isp, ISP_LOGERR, "Unable to enable Target Role on Bus %d", bus);
return (EIO);
}
- SDPARAM(isp, bus)->role |= ISP_ROLE_TARGET;
}
ISP_SET_PC(isp, bus, tm_enabled, 1);
- isp_prt(isp, ISP_LOGINFO, "Target Role added to Bus %d", bus);
+ isp_prt(isp, ISP_LOGINFO, "Target Role enabled on Bus %d", bus);
return (0);
}
-#ifdef NEEDED
static int
isp_disable_target_mode(ispsoftc_t *isp, int bus)
{
- int ct;
+ int tm_enabled;
- ISP_GET_PC(isp, bus, tm_enabled, ct);
- if (ct == 0) {
+ ISP_GET_PC(isp, bus, tm_enabled, tm_enabled);
+ if (tm_enabled == 0) {
return (0);
}
-
if (IS_SCSI(isp)) {
mbreg_t mbs;
-
MBSINIT(&mbs, MBOX_ENABLE_TARGET_MODE, MBLOGALL, 0);
mbs.param[2] = bus << 7;
if (isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs) < 0 || mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_prt(isp, ISP_LOGERR, "Unable to subtract Target Role to Bus %d", bus);
+ isp_prt(isp, ISP_LOGERR, "Unable to disable Target Role on Bus %d", bus);
return (EIO);
}
- SDPARAM(isp, bus)->role &= ~ISP_ROLE_TARGET;
}
ISP_SET_PC(isp, bus, tm_enabled, 0);
- isp_prt(isp, ISP_LOGINFO, "Target Role subtracted from Bus %d", bus);
+ isp_prt(isp, ISP_LOGINFO, "Target Role disabled onon Bus %d", bus);
return (0);
}
-#endif
static void
isp_ledone(ispsoftc_t *isp, lun_entry_t *lep)
@@ -4431,7 +4506,7 @@ isp_action(struct cam_sim *sim, union cc
tptr->atio_count++;
SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h, sim_links.sle);
ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "Put FREE ATIO (tag id 0x%x), count now %d\n",
- ((struct ccb_accept_tio *)ccb)->tag_id, tptr->atio_count);
+ ccb->atio.tag_id, tptr->atio_count);
} else if (ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) {
if (ccb->cin1.tag_id) {
inot_private_data_t *ntp = isp_find_ntpd(isp, tptr, ccb->cin1.tag_id, ccb->cin1.seq_id);
@@ -4442,12 +4517,12 @@ isp_action(struct cam_sim *sim, union cc
tptr->inot_count++;
SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h, sim_links.sle);
ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "Put FREE INOT, (seq id 0x%x) count now %d\n",
- ((struct ccb_immediate_notify *)ccb)->seq_id, tptr->inot_count);
+ ccb->cin1.seq_id, tptr->inot_count);
} else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
tptr->inot_count++;
SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h, sim_links.sle);
ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "Put FREE INOT, (seq id 0x%x) count now %d\n",
- ((struct ccb_immediate_notify *)ccb)->seq_id, tptr->inot_count);
+ ccb->cin1.seq_id, tptr->inot_count);
}
rls_lun_statep(isp, tptr);
ccb->ccb_h.status = CAM_REQ_INPROG;
@@ -4730,7 +4805,6 @@ isp_action(struct cam_sim *sim, union cc
struct ccb_sim_knob *kp = &ccb->knob;
fcparam *fcp;
-
if (!IS_FC(isp)) {
ccb->ccb_h.status = CAM_REQ_INVALID;
xpt_done(ccb);
@@ -4788,11 +4862,12 @@ isp_action(struct cam_sim *sim, union cc
break;
}
if (rchange) {
+ ISP_PATH_PRT(isp, ISP_LOGCONFIG, ccb->ccb_h.path, "changing role on from %d to %d\n", fcp->role, newrole);
if (isp_fc_change_role(isp, bus, newrole) != 0) {
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
#ifdef ISP_TARGET_MODE
} else if (newrole == ISP_ROLE_TARGET || newrole == ISP_ROLE_BOTH) {
- isp_enable_deferred_luns(isp, bus);
+ ccb->ccb_h.status = isp_enable_deferred_luns(isp, bus);
#endif
}
}
@@ -4800,7 +4875,7 @@ isp_action(struct cam_sim *sim, union cc
xpt_done(ccb);
break;
}
- case XPT_GET_SIM_KNOB: /* Set SIM knobs */
+ case XPT_GET_SIM_KNOB: /* Get SIM knobs */
{
struct ccb_sim_knob *kp = &ccb->knob;
Modified: stable/9/sys/dev/isp/isp_freebsd.h
==============================================================================
--- stable/9/sys/dev/isp/isp_freebsd.h Sun Jun 17 21:07:27 2012 (r237207)
+++ stable/9/sys/dev/isp/isp_freebsd.h Sun Jun 17 21:28:11 2012 (r237208)
@@ -121,8 +121,10 @@ typedef struct tstate {
struct ccb_hdr_slist atios;
struct ccb_hdr_slist inots;
uint32_t hold;
- int atio_count;
- int inot_count;
+ uint32_t
+ enabled : 1,
+ atio_count : 15,
+ inot_count : 15;
inot_private_data_t * restart_queue;
inot_private_data_t * ntfree;
inot_private_data_t ntpool[ATPDPSIZE];
Modified: stable/9/sys/dev/isp/ispvar.h
==============================================================================
--- stable/9/sys/dev/isp/ispvar.h Sun Jun 17 21:07:27 2012 (r237207)
+++ stable/9/sys/dev/isp/ispvar.h Sun Jun 17 21:28:11 2012 (r237208)
@@ -724,8 +724,17 @@ struct ispsoftc {
#define ISP_ROLE_BOTH (ISP_ROLE_TARGET|ISP_ROLE_INITIATOR)
#define ISP_ROLE_EITHER ISP_ROLE_BOTH
#ifndef ISP_DEFAULT_ROLES
+/*
+ * Counterintuitively, we prefer to default to role 'none'
+ * if we are enable target mode support. This gives us the
+ * maximum flexibility as to which port will do what.
+ */
+#ifdef ISP_TARGET_MODE
+#define ISP_DEFAULT_ROLES ISP_ROLE_NONE
+#else
#define ISP_DEFAULT_ROLES ISP_ROLE_INITIATOR
#endif
+#endif
/*
More information about the svn-src-stable-9
mailing list