svn commit: r207175 - stable/8/sys/dev/isp

Matt Jacob mjacob at FreeBSD.org
Sat Apr 24 23:20:51 UTC 2010


Author: mjacob
Date: Sat Apr 24 23:20:51 2010
New Revision: 207175
URL: http://svn.freebsd.org/changeset/base/207175

Log:
  This is an MFC of 204050.
  
  Don't try and re-use a handle, even if the firmware tells you that's what is logged in.
  
  PR:             kern/144026

Modified:
  stable/8/sys/dev/isp/isp.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/sys/geom/sched/   (props changed)

Modified: stable/8/sys/dev/isp/isp.c
==============================================================================
--- stable/8/sys/dev/isp/isp.c	Sat Apr 24 23:13:05 2010	(r207174)
+++ stable/8/sys/dev/isp/isp.c	Sat Apr 24 23:20:51 2010	(r207175)
@@ -2167,9 +2167,7 @@ isp_plogx(ispsoftc_t *isp, int chan, uin
 		msg = "no Exchange Control Block";
 		break;
 	case PLOGX_IOCBERR_FAILED:
-		ISP_SNPRINTF(buf, sizeof (buf),
-		    "reason 0x%x (last LOGIN state 0x%x)",
-		    parm1 & 0xff, (parm1 >> 8) & 0xff);
+		ISP_SNPRINTF(buf, sizeof (buf), "reason 0x%x (last LOGIN state 0x%x)", parm1 & 0xff, (parm1 >> 8) & 0xff);
 		msg = buf;
 		break;
 	case PLOGX_IOCBERR_NOFABRIC:
@@ -2179,8 +2177,7 @@ isp_plogx(ispsoftc_t *isp, int chan, uin
 		msg = "firmware not ready";
 		break;
 	case PLOGX_IOCBERR_NOLOGIN:
-		ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)",
-		    parm1);
+		ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)", parm1);
 		msg = buf;
 		rval = MBOX_NOT_LOGGED_IN;
 		break;
@@ -2192,21 +2189,18 @@ isp_plogx(ispsoftc_t *isp, int chan, uin
 		msg = "no PCB allocated";
 		break;
 	case PLOGX_IOCBERR_EINVAL:
-		ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x",
-		    parm1);
+		ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x", parm1);
 		msg = buf;
 		break;
 	case PLOGX_IOCBERR_PORTUSED:
 		lev = ISP_LOGSANCFG|ISP_LOGDEBUG0;
-		ISP_SNPRINTF(buf, sizeof (buf),
-		    "already logged in with N-Port handle 0x%x", parm1);
+		ISP_SNPRINTF(buf, sizeof (buf), "already logged in with N-Port handle 0x%x", parm1);
 		msg = buf;
 		rval = MBOX_PORT_ID_USED | (parm1 << 16);
 		break;
 	case PLOGX_IOCBERR_HNDLUSED:
 		lev = ISP_LOGSANCFG|ISP_LOGDEBUG0;
-		ISP_SNPRINTF(buf, sizeof (buf),
-		    "handle already used for PortID 0x%06x", parm1);
+		ISP_SNPRINTF(buf, sizeof (buf), "handle already used for PortID 0x%06x", parm1);
 		msg = buf;
 		rval = MBOX_LOOP_ID_USED;
 		break;
@@ -2217,15 +2211,12 @@ isp_plogx(ispsoftc_t *isp, int chan, uin
 		msg = "no FLOGI_ACC";
 		break;
 	default:
-		ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x",
-		    plp->plogx_status, flags);
+		ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", plp->plogx_status, flags);
 		msg = buf;
 		break;
 	}
 	if (msg) {
-		isp_prt(isp, ISP_LOGERR,
-		    "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s",
-		    chan, portid, handle, msg);
+		isp_prt(isp, ISP_LOGERR, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s", chan, portid, handle, msg);
 	}
 out:
 	if (gs == 0) {
@@ -3886,8 +3877,7 @@ isp_scan_fabric(ispsoftc_t *isp, int cha
  * Find an unused handle and try and use to login to a port.
  */
 static int
-isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p,
-    uint16_t *ohp)
+isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
 {
 	int lim, i, r;
 	uint16_t handle;
@@ -3907,8 +3897,7 @@ isp_login_device(ispsoftc_t *isp, int ch
 		 */
 		r = isp_getpdb(isp, chan, handle, p, 0);
 		if (r == 0 && p->portid != portid) {
-			(void) isp_plogx(isp, chan, handle, portid,
-			    PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT, 1);
+			(void) isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1);
 		} else if (r == 0) {
 			break;
 		}
@@ -3918,8 +3907,7 @@ isp_login_device(ispsoftc_t *isp, int ch
 		/*
 		 * Now try and log into the device
 		 */
-		r = isp_plogx(isp, chan, handle, portid,
-		    PLOGX_FLG_CMD_PLOGI, 1);
+		r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1);
 		if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
 			return (-1);
 		}
@@ -3927,7 +3915,26 @@ isp_login_device(ispsoftc_t *isp, int ch
 			*ohp = handle;
 			break;
 		} else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
-			handle = r >> 16;
+			/*
+			 * If we get here, then the firmwware still thinks we're logged into this device, but with a different
+			 * handle. We need to break that association. We used to try and just substitute the handle, but then
+			 * failed to get any data via isp_getpdb (below).
+			 */
+			if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1)) {
+				isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16);
+			}
+			if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
+				return (-1);
+			}
+			r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1);
+			if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
+				return (-1);
+			}
+			if (r == 0) {
+				*ohp = handle;
+			} else {
+				i = lim;
+			}
 			break;
 		} else if (r != MBOX_LOOP_ID_USED) {
 			i = lim;
@@ -3941,8 +3948,7 @@ isp_login_device(ispsoftc_t *isp, int ch
 	}
 
 	if (i == lim) {
-		isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed",
-		    chan, portid);
+		isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed", chan, portid);
 		return (-1);
 	}
 
@@ -3956,15 +3962,12 @@ isp_login_device(ispsoftc_t *isp, int ch
 		return (-1);
 	}
 	if (r != 0) {
-		isp_prt(isp, ISP_LOGERR,
-		    "Chan %d new device 0x%06x at 0x%x disappeared",
-		    chan, portid, handle);
+		isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x at 0x%x disappeared", chan, portid, handle);
 		return (-1);
 	}
 
 	if (p->handle != handle || p->portid != portid) {
-		isp_prt(isp, ISP_LOGERR,
-		    "Chan %d new device 0x%06x at 0x%x changed (0x%06x at 0x%0x)",
+		isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x at 0x%x changed (0x%06x at 0x%0x)",
 		    chan, portid, handle, p->portid, p->handle);
 		return (-1);
 	}


More information about the svn-src-all mailing list