Author: mav
Date: Sat Jul  4 18:38:46 2015
New Revision: 285146
URL: https://svnweb.freebsd.org/changeset/base/285146

Log:
  Drop discovered targets when initiator role is disabled.

Modified:
  head/sys/dev/isp/isp.c
  head/sys/dev/isp/isp_freebsd.c
  head/sys/dev/isp/isp_library.c
  head/sys/dev/isp/ispvar.h

Modified: head/sys/dev/isp/isp.c
==============================================================================
--- head/sys/dev/isp/isp.c      Sat Jul  4 18:36:02 2015        (r285145)
+++ head/sys/dev/isp/isp.c      Sat Jul  4 18:38:46 2015        (r285146)
@@ -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 ct
                } 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;

Modified: head/sys/dev/isp/isp_freebsd.c
==============================================================================
--- head/sys/dev/isp/isp_freebsd.c      Sat Jul  4 18:36:02 2015        
(r285145)
+++ head/sys/dev/isp/isp_freebsd.c      Sat Jul  4 18:38:46 2015        
(r285146)
@@ -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, cad
                                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 cc
                                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 cm
                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 cm
                 *
                 */
                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;

Modified: head/sys/dev/isp/isp_library.c
==============================================================================
--- head/sys/dev/isp/isp_library.c      Sat Jul  4 18:36:02 2015        
(r285145)
+++ head/sys/dev/isp/isp_library.c      Sat Jul  4 18:38:46 2015        
(r285146)
@@ -603,9 +603,6 @@ isp_fc_change_role(ispsoftc_t *isp, int 
                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 
                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 
                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) {

Modified: head/sys/dev/isp/ispvar.h
==============================================================================
--- head/sys/dev/isp/ispvar.h   Sat Jul  4 18:36:02 2015        (r285145)
+++ head/sys/dev/isp/ispvar.h   Sat Jul  4 18:38:46 2015        (r285146)
@@ -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, ...);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to