Drop discovered targets when initiator role is disabled.

This commit is contained in:
Alexander Motin
2015-07-04 18:38:46 +00:00
parent 68c32d3559
commit 6bef0aa0c6
4 changed files with 75 additions and 25 deletions
+53 -1
View File
@@ -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
View File
@@ -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;
-11
View File
@@ -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) {
+4 -1
View File
@@ -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, ...);