Drop discovered targets when initiator role is disabled.
This commit is contained in:
+53
-1
@@ -2222,6 +2222,36 @@ isp_fibre_init_2400(ispsoftc_t *isp)
|
||||
isp->isp_state = ISP_INITSTATE;
|
||||
}
|
||||
|
||||
static void
|
||||
isp_del_all_init_entries(ispsoftc_t *isp, int chan)
|
||||
{
|
||||
fcparam *fcp = FCPARAM(isp, chan);
|
||||
fcportdb_t *lp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_FC_TARG; i++) {
|
||||
lp = &fcp->portdb[i];
|
||||
if (lp->state == FC_PORTDB_STATE_NIL || lp->target_mode)
|
||||
continue;
|
||||
/*
|
||||
* It's up to the outer layers to clear isp_dev_map.
|
||||
*/
|
||||
lp->state = FC_PORTDB_STATE_NIL;
|
||||
isp_async(isp, ISPASYNC_DEV_GONE, chan, lp, 1);
|
||||
if (lp->autologin == 0) {
|
||||
(void) isp_plogx(isp, chan, lp->handle,
|
||||
lp->portid,
|
||||
PLOGX_FLG_CMD_LOGO |
|
||||
PLOGX_FLG_IMPLICIT |
|
||||
PLOGX_FLG_FREE_NPHDL, 0);
|
||||
} else {
|
||||
lp->autologin = 0;
|
||||
}
|
||||
lp->new_prli_word3 = 0;
|
||||
lp->new_portid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isp_mark_portdb(ispsoftc_t *isp, int chan, int disposition)
|
||||
{
|
||||
@@ -2981,7 +3011,7 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
|
||||
* It's up to the outer layers to clear isp_dev_map.
|
||||
*/
|
||||
lp->state = FC_PORTDB_STATE_NIL;
|
||||
isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
|
||||
isp_async(isp, ISPASYNC_DEV_GONE, chan, lp, 0);
|
||||
if (lp->autologin == 0) {
|
||||
(void) isp_plogx(isp, chan, lp->handle,
|
||||
lp->portid,
|
||||
@@ -4990,6 +5020,28 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, ...)
|
||||
} while ((r & 0xffff) == MBOX_LOOP_ID_USED);
|
||||
return (r);
|
||||
}
|
||||
case ISPCTL_CHANGE_ROLE:
|
||||
{
|
||||
int role, r;
|
||||
|
||||
va_start(ap, ctl);
|
||||
chan = va_arg(ap, int);
|
||||
role = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
if (IS_FC(isp)) {
|
||||
#ifdef ISP_TARGET_MODE
|
||||
if ((role & ISP_ROLE_TARGET) == 0)
|
||||
isp_del_all_wwn_entries(isp, chan);
|
||||
#endif
|
||||
if ((role & ISP_ROLE_INITIATOR) == 0)
|
||||
isp_del_all_init_entries(isp, chan);
|
||||
r = isp_fc_change_role(isp, chan, role);
|
||||
} else {
|
||||
SDPARAM(isp, chan)->role = role;
|
||||
r = 0;
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
default:
|
||||
isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
|
||||
break;
|
||||
|
||||
+18
-12
@@ -115,7 +115,7 @@ isp_role_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
|
||||
/* Actually change the role. */
|
||||
error = isp_fc_change_role(isp, chan, value);
|
||||
error = isp_control(isp, ISPCTL_CHANGE_ROLE, chan, value);
|
||||
ISP_UNLOCK(isp);
|
||||
return (error);
|
||||
}
|
||||
@@ -474,18 +474,14 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td)
|
||||
retval = EINVAL;
|
||||
break;
|
||||
}
|
||||
*(int *)addr = FCPARAM(isp, chan)->role;
|
||||
#ifdef ISP_INTERNAL_TARGET
|
||||
ISP_LOCK(isp);
|
||||
retval = isp_fc_change_role(isp, chan, nr);
|
||||
ISP_UNLOCK(isp);
|
||||
#else
|
||||
FCPARAM(isp, chan)->role = nr;
|
||||
#endif
|
||||
*(int *)addr = FCPARAM(isp, chan)->role;
|
||||
} else {
|
||||
ISP_LOCK(isp);
|
||||
*(int *)addr = SDPARAM(isp, chan)->role;
|
||||
SDPARAM(isp, chan)->role = nr;
|
||||
}
|
||||
retval = isp_control(isp, ISPCTL_CHANGE_ROLE, chan, nr);
|
||||
ISP_UNLOCK(isp);
|
||||
retval = 0;
|
||||
break;
|
||||
|
||||
@@ -5478,7 +5474,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||
ISP_SET_PC(isp, bus, tm_enabled, 0);
|
||||
ISP_SET_PC(isp, bus, tm_luns_enabled, 0);
|
||||
#endif
|
||||
if (isp_fc_change_role(isp, bus, newrole) != 0) {
|
||||
if (isp_control(isp, ISPCTL_CHANGE_ROLE,
|
||||
bus, newrole) != 0) {
|
||||
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
|
||||
xpt_done(ccb);
|
||||
break;
|
||||
@@ -5668,7 +5665,7 @@ isp_done(XS_T *sccb)
|
||||
void
|
||||
isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
{
|
||||
int bus;
|
||||
int bus, now;
|
||||
static const char prom0[] = "Chan %d PortID 0x%06x handle 0x%x %s %s WWPN 0x%08x%08x";
|
||||
static const char prom2[] = "Chan %d PortID 0x%06x handle 0x%x %s %s tgt %u WWPN 0x%08x%08x";
|
||||
char buf[64];
|
||||
@@ -5909,6 +5906,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
va_start(ap, cmd);
|
||||
bus = va_arg(ap, int);
|
||||
lp = va_arg(ap, fcportdb_t *);
|
||||
now = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
fc = ISP_FC_PC(isp, bus);
|
||||
/*
|
||||
@@ -5921,7 +5919,15 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
*
|
||||
*/
|
||||
isp_gen_role_str(buf, sizeof (buf), lp->prli_word3);
|
||||
if (lp->dev_map_idx && lp->announced == 0) {
|
||||
if (lp->dev_map_idx && lp->announced == 0 && now) {
|
||||
lp->announced = 1;
|
||||
tgt = lp->dev_map_idx - 1;
|
||||
FCPARAM(isp, bus)->isp_dev_map[tgt] = 0;
|
||||
lp->dev_map_idx = 0;
|
||||
isp_make_gone(isp, lp, bus, tgt);
|
||||
isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, buf, "gone at", tgt, (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
|
||||
isp_fcp_reset_crn(fc, tgt, /*tgt_set*/ 1);
|
||||
} else if (lp->dev_map_idx && lp->announced == 0) {
|
||||
lp->announced = 1;
|
||||
lp->state = FC_PORTDB_STATE_ZOMBIE;
|
||||
lp->gone_timer = ISP_FC_PC(isp, bus)->gone_device_time;
|
||||
|
||||
@@ -603,9 +603,6 @@ isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
|
||||
return (ENXIO);
|
||||
}
|
||||
if (chan == 0) {
|
||||
#ifdef ISP_TARGET_MODE
|
||||
isp_del_all_wwn_entries(isp, chan);
|
||||
#endif
|
||||
isp_clear_commands(isp);
|
||||
isp_reset(isp, 0);
|
||||
if (isp->isp_state != ISP_RESETSTATE) {
|
||||
@@ -626,8 +623,6 @@ isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
|
||||
uint8_t qe[QENTRY_LEN], *scp;
|
||||
|
||||
ISP_MEMZERO(qe, QENTRY_LEN);
|
||||
/* Acquire Scratch */
|
||||
|
||||
if (FC_SCRATCH_ACQUIRE(isp, chan)) {
|
||||
return (EBUSY);
|
||||
}
|
||||
@@ -671,12 +666,6 @@ isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
|
||||
MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
|
||||
isp_get_vp_modify(isp, (vp_modify_t *)&scp[QENTRY_LEN], vp);
|
||||
|
||||
#ifdef ISP_TARGET_MODE
|
||||
isp_del_all_wwn_entries(isp, chan);
|
||||
#endif
|
||||
/*
|
||||
* Release Scratch
|
||||
*/
|
||||
FC_SCRATCH_RELEASE(isp, chan);
|
||||
|
||||
if (vp->vp_mod_status != VP_STS_OK) {
|
||||
|
||||
@@ -915,6 +915,8 @@ void isp_done(XS_T *);
|
||||
* Get PDB on this channel for this N-port handle
|
||||
* ... ISPCTL_PLOGX, isp_plcmd_t *)
|
||||
* Performa a port login/logout
|
||||
* ... ISPCTL_CHANGE_ROLE, int channel, int role);
|
||||
* Change role of specified channel
|
||||
*
|
||||
* ISPCTL_PDB_SYNC is somewhat misnamed. It actually is the final step, in
|
||||
* order, of ISPCTL_FCLINK_TEST, ISPCTL_SCAN_FABRIC, and ISPCTL_SCAN_LOOP.
|
||||
@@ -937,7 +939,8 @@ typedef enum {
|
||||
ISPCTL_GET_NAMES,
|
||||
ISPCTL_RUN_MBOXCMD,
|
||||
ISPCTL_GET_PDB,
|
||||
ISPCTL_PLOGX
|
||||
ISPCTL_PLOGX,
|
||||
ISPCTL_CHANGE_ROLE
|
||||
} ispctl_t;
|
||||
int isp_control(ispsoftc_t *, ispctl_t, ...);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user