svn commit: r292741 - head/sys/dev/isp

Alexander Motin mav at FreeBSD.org
Sat Dec 26 06:13:02 UTC 2015


Author: mav
Date: Sat Dec 26 06:13:01 2015
New Revision: 292741
URL: https://svnweb.freebsd.org/changeset/base/292741

Log:
  Make port logins asynchronous, following r292739 logic.
  
  This is even more important since it involves more network operations and
  more prone to delays and timeouts.

Modified:
  head/sys/dev/isp/isp.c

Modified: head/sys/dev/isp/isp.c
==============================================================================
--- head/sys/dev/isp/isp.c	Sat Dec 26 06:05:21 2015	(r292740)
+++ head/sys/dev/isp/isp.c	Sat Dec 26 06:13:01 2015	(r292741)
@@ -108,7 +108,7 @@ static void isp_fibre_init(ispsoftc_t *)
 static void isp_fibre_init_2400(ispsoftc_t *);
 static void isp_clear_portdb(ispsoftc_t *, int);
 static void isp_mark_portdb(ispsoftc_t *, int);
-static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int, int);
+static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int);
 static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t);
 static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t);
 static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *, int);
@@ -2550,13 +2550,11 @@ isp_mark_portdb(ispsoftc_t *isp, int cha
  * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
  */
 static int
-isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags, int gs)
+isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags)
 {
-	mbreg_t mbs;
-	uint8_t q[QENTRY_LEN];
-	isp_plogx_t *plp;
-	fcparam *fcp;
-	uint8_t *scp;
+	isp_plogx_t pl;
+	void *reqp;
+	uint8_t resp[QENTRY_LEN];
 	uint32_t sst, parm1;
 	int rval, lev;
 	const char *msg;
@@ -2576,64 +2574,58 @@ isp_plogx(ispsoftc_t *isp, int chan, uin
 		}
 	}
 
-	ISP_MEMZERO(q, QENTRY_LEN);
-	plp = (isp_plogx_t *) q;
-	plp->plogx_header.rqs_entry_count = 1;
-	plp->plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
-	plp->plogx_handle = 0xffffffff;
-	plp->plogx_nphdl = handle;
-	plp->plogx_vphdl = chan;
-	plp->plogx_portlo = portid;
-	plp->plogx_rspsz_porthi = (portid >> 16) & 0xff;
-	plp->plogx_flags = flags;
+	ISP_MEMZERO(&pl, sizeof(pl));
+	pl.plogx_header.rqs_entry_count = 1;
+	pl.plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
+	pl.plogx_nphdl = handle;
+	pl.plogx_vphdl = chan;
+	pl.plogx_portlo = portid;
+	pl.plogx_rspsz_porthi = (portid >> 16) & 0xff;
+	pl.plogx_flags = flags;
 
-	if (isp->isp_dblev & ISP_LOGDEBUG1) {
-		isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, plp);
-	}
-
-	if (gs == 0) {
-		if (FC_SCRATCH_ACQUIRE(isp, chan)) {
-			isp_prt(isp, ISP_LOGERR, sacq);
-			return (-1);
-		}
+	/* Prepare space for response in memory */
+	memset(resp, 0xff, sizeof(resp));
+	pl.plogx_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
+	if (pl.plogx_handle == 0) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: PLOGX of Chan %d out of handles", __func__, chan);
+		return (-1);
 	}
-	fcp = FCPARAM(isp, chan);
-	scp = fcp->isp_scratch;
-	isp_put_plogx(isp, plp, (isp_plogx_t *) scp);
 
-	MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL,
-	    MBCMD_DEFAULT_TIMEOUT + ICB_LOGIN_TOV * 1000000);
-	mbs.param[1] = QENTRY_LEN;
-	mbs.param[2] = DMA_WD1(fcp->isp_scdma);
-	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
-	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
-	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
-	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN, chan);
-	isp_mboxcmd(isp, &mbs);
-	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-		rval = mbs.param[0];
-		goto out;
+	/* Send request and wait for response. */
+	reqp = isp_getrqentry(isp);
+	if (reqp == NULL) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: PLOGX of Chan %d out of rqent", __func__, chan);
+		isp_destroy_handle(isp, pl.plogx_handle);
+		return (-1);
 	}
-	MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
-	scp += QENTRY_LEN;
-	isp_get_plogx(isp, (isp_plogx_t *) scp, plp);
-	if (isp->isp_dblev & ISP_LOGDEBUG1) {
-		isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, plp);
+	if (isp->isp_dblev & ISP_LOGDEBUG1)
+		isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, &pl);
+	isp_put_plogx(isp, &pl, (isp_plogx_t *)reqp);
+	ISP_SYNC_REQUEST(isp);
+	if (msleep(resp, &isp->isp_lock, 0, "PLOGX", 3 * ICB_LOGIN_TOV * hz)
+	    == EWOULDBLOCK) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: PLOGX of Chan %d timed out", __func__, chan);
+		isp_destroy_handle(isp, pl.plogx_handle);
+		return (-1);
 	}
+	isp_get_plogx(isp, (isp_plogx_t *)resp, &pl);
+	if (isp->isp_dblev & ISP_LOGDEBUG1)
+		isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, &pl);
 
-	if (plp->plogx_status == PLOGX_STATUS_OK) {
-		rval = 0;
-		goto out;
-	} else if (plp->plogx_status != PLOGX_STATUS_IOCBERR) {
+	if (pl.plogx_status == PLOGX_STATUS_OK) {
+		return (0);
+	} else if (pl.plogx_status != PLOGX_STATUS_IOCBERR) {
 		isp_prt(isp, ISP_LOGWARN,
 		    "status 0x%x on port login IOCB channel %d",
-		    plp->plogx_status, chan);
-		rval = -1;
-		goto out;
+		    pl.plogx_status, chan);
+		return (-1);
 	}
 
-	sst = plp->plogx_ioparm[0].lo16 | (plp->plogx_ioparm[0].hi16 << 16);
-	parm1 = plp->plogx_ioparm[1].lo16 | (plp->plogx_ioparm[1].hi16 << 16);
+	sst = pl.plogx_ioparm[0].lo16 | (pl.plogx_ioparm[0].hi16 << 16);
+	parm1 = pl.plogx_ioparm[1].lo16 | (pl.plogx_ioparm[1].hi16 << 16);
 
 	rval = -1;
 	lev = ISP_LOGERR;
@@ -2694,17 +2686,13 @@ 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", pl.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);
 	}
-out:
-	if (gs == 0) {
-		FC_SCRATCH_RELEASE(isp, chan);
-	}
 	return (rval);
 }
 
@@ -3196,7 +3184,7 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
 				    lp->portid,
 				    PLOGX_FLG_CMD_LOGO |
 				    PLOGX_FLG_IMPLICIT |
-				    PLOGX_FLG_FREE_NPHDL, 0);
+				    PLOGX_FLG_FREE_NPHDL);
 			}
 			/*
 			 * Note that we might come out of this with our state
@@ -3883,7 +3871,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);
 		if (r == 0) {
 			break;
 		} else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
@@ -3892,12 +3880,12 @@ isp_login_device(ispsoftc_t *isp, int ch
 			 * 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)) {
+			if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL)) {
 				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);
+			r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
 			if (r != 0)
 				i = lim;
 			break;
@@ -4937,11 +4925,11 @@ isp_control(ispsoftc_t *isp, ispctl_t ct
 		va_end(ap);
 
 		if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) {
-			return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags, 0));
+			return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags));
 		}
 		do {
 			isp_next_handle(isp, &p->handle);
-			r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags, 0);
+			r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags);
 			if ((r & 0xffff) == MBOX_PORT_ID_USED) {
 				p->handle = r >> 16;
 				r = 0;
@@ -6170,6 +6158,7 @@ isp_handle_other_response(ispsoftc_t *is
 		return (1);
 	case RQSTYPE_VP_MODIFY:
 	case RQSTYPE_VP_CTRL:
+	case RQSTYPE_LOGIN:
 		ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
 		ptr = isp_find_xs(isp, hdl);
 		if (ptr != NULL) {


More information about the svn-src-all mailing list