diff options
author | mav <mav@FreeBSD.org> | 2015-10-05 08:16:10 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2015-10-05 08:16:10 +0000 |
commit | df85f2e52d7764efbf42714f778628c84114f7d0 (patch) | |
tree | 03be66425973ff5f61bd2e437027311474e2249e /sys/dev/isp | |
parent | 2df2e7b59b17e6fd90cf75a9821081a7ac775566 (diff) | |
download | FreeBSD-src-df85f2e52d7764efbf42714f778628c84114f7d0.zip FreeBSD-src-df85f2e52d7764efbf42714f778628c84114f7d0.tar.gz |
MFC r285146: Drop discovered targets when initiator role is disabled.
Diffstat (limited to 'sys/dev/isp')
-rw-r--r-- | sys/dev/isp/isp.c | 54 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 30 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.c | 11 | ||||
-rw-r--r-- | sys/dev/isp/ispvar.h | 5 |
4 files changed, 75 insertions, 25 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index a347143..dd203a4 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -2223,6 +2223,36 @@ isp_fibre_init_2400(ispsoftc_t *isp) } 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) { fcparam *fcp = FCPARAM(isp, chan); @@ -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; diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 5481c99..97dd7ae 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -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; diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index b56b1dc..2f7dc4e 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -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) { diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index 4ac91b9..150073e 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -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, ...); |