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

Alexander Motin mav at FreeBSD.org
Wed Oct 28 12:35:01 UTC 2015


Author: mav
Date: Wed Oct 28 12:34:59 2015
New Revision: 290104
URL: https://svnweb.freebsd.org/changeset/base/290104

Log:
  Improve/fix loop scanning routine.
  
  For the most of chips (except anscient ones) port handlers have no relation
  to port IDs.  In such situation old code scanning first 125 handlers was
  quite naive.  Instead of doing that, send to chip single request to get full
  list of port handlers available on specific virtual port and scan only them.
  
  Old code had problems with case of several virtual ports enabled, when port
  handlers allocated from global address space could easily go above 125.
  This change was successfully tested on 23xx, 24xx and 25xx chips in loop
  mode with 4 virtual initiator ports, each seing 50 virtual target ports.

Modified:
  head/sys/dev/isp/isp.c
  head/sys/dev/isp/isp_library.c
  head/sys/dev/isp/isp_library.h
  head/sys/dev/isp/ispmbox.h

Modified: head/sys/dev/isp/isp.c
==============================================================================
--- head/sys/dev/isp/isp.c	Wed Oct 28 12:31:29 2015	(r290103)
+++ head/sys/dev/isp/isp.c	Wed Oct 28 12:34:59 2015	(r290104)
@@ -119,6 +119,7 @@ static int isp_plogx(ispsoftc_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);
+static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int, int);
 static void isp_dump_chip_portdb(ispsoftc_t *, int, int);
 static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int);
 static int isp_fclink_test(ispsoftc_t *, int, int);
@@ -2587,7 +2588,7 @@ isp_getpdb(ispsoftc_t *isp, int chan, ui
 		if (dolock) {
 			FC_SCRATCH_RELEASE(isp, chan);
 		}
-		return (mbs.param[0]);
+		return (mbs.param[0] | (mbs.param[1] << 16));
 	}
 	if (IS_24XX(isp)) {
 		isp_get_pdb_24xx(isp, fcp->isp_scratch, &un.bill);
@@ -2618,6 +2619,78 @@ isp_getpdb(ispsoftc_t *isp, int chan, ui
 	return (0);
 }
 
+static int
+isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num,
+    int dolock, int loop)
+{
+	fcparam *fcp = FCPARAM(isp, chan);
+	mbreg_t mbs;
+	isp_pnhle_21xx_t el1, *elp1;
+	isp_pnhle_23xx_t el3, *elp3;
+	isp_pnhle_24xx_t el4, *elp4;
+	int i, j;
+	uint32_t p;
+	uint16_t h;
+
+	MBSINIT(&mbs, MBOX_GET_ID_LIST, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR, 250000);
+	if (IS_24XX(isp)) {
+		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);
+		mbs.param[8] = ISP_FC_SCRLEN;
+		mbs.param[9] = chan;
+	} else {
+		mbs.ibits = (1 << 1)|(1 << 2)|(1 << 3)|(1 << 6);
+		mbs.param[1] = DMA_WD1(fcp->isp_scdma);
+		mbs.param[2] = DMA_WD0(fcp->isp_scdma);
+		mbs.param[3] = DMA_WD3(fcp->isp_scdma);
+		mbs.param[6] = DMA_WD2(fcp->isp_scdma);
+	}
+	if (dolock) {
+		if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+			isp_prt(isp, ISP_LOGERR, sacq);
+			return (-1);
+		}
+	}
+	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, ISP_FC_SCRLEN, chan);
+	isp_mboxcmd(isp, &mbs);
+	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+		if (dolock) {
+			FC_SCRATCH_RELEASE(isp, chan);
+		}
+		return (mbs.param[0] | (mbs.param[1] << 16));
+	}
+	elp1 = fcp->isp_scratch;
+	elp3 = fcp->isp_scratch;
+	elp4 = fcp->isp_scratch;
+	for (i = 0, j = 0; i < mbs.param[1] && j < *num; i++) {
+		if (IS_24XX(isp)) {
+			isp_get_pnhle_24xx(isp, &elp4[i], &el4);
+			p = el4.pnhle_port_id_lo |
+			    (el4.pnhle_port_id_hi << 16);
+			h = el4.pnhle_handle;
+		} else if (IS_23XX(isp)) {
+			isp_get_pnhle_23xx(isp, &elp3[i], &el3);
+			p = el3.pnhle_port_id_lo |
+			    (el3.pnhle_port_id_hi << 16);
+			h = el3.pnhle_handle;
+		} else { /* 21xx */
+			isp_get_pnhle_21xx(isp, &elp1[i], &el1);
+			p = el1.pnhle_port_id_lo |
+			    ((el1.pnhle_port_id_hi_handle & 0xff) << 16);
+			h = el1.pnhle_port_id_hi_handle >> 8;
+		}
+		if (loop && (p >> 8) != (fcp->isp_portid >> 8))
+			continue;
+		handles[j++] = h;
+	}
+	*num = j;
+	if (dolock)
+		FC_SCRATCH_RELEASE(isp, chan);
+	return (0);
+}
+
 static void
 isp_dump_chip_portdb(ispsoftc_t *isp, int chan, int dolock)
 {
@@ -3106,79 +3179,68 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
 {
 	fcportdb_t *lp, tmp;
 	fcparam *fcp = FCPARAM(isp, chan);
-	int i;
+	int i, idx, lim, r;
 	isp_pdb_t pdb;
-	uint16_t handle, lim = 0;
+	uint16_t handles[LOCAL_LOOP_LIM];
+	uint16_t handle;
 
 	if (fcp->isp_fwstate < FW_READY ||
 	    fcp->isp_loopstate < LOOP_PDB_RCVD) {
 		return (-1);
 	}
-
 	if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) {
 		return (0);
 	}
-
-	/*
-	 * Check our connection topology.
-	 *
-	 * If we're a public or private loop, we scan 0..125 as handle values.
-	 * The firmware has (typically) peformed a PLOGI for us. We skip this
-	 * step if we're a ISP_24XX in NP-IV mode.
-	 *
-	 * If we're a N-port connection, we treat this is a short loop (0..1).
-	 */
-	switch (fcp->isp_topo) {
-	case TOPO_NL_PORT:
-		lim = LOCAL_LOOP_LIM;
-		break;
-	case TOPO_FL_PORT:
-		if (IS_24XX(isp) && isp->isp_nchan > 1) {
-			isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Skipping Local Loop Scan", chan);
-			fcp->isp_loopstate = LOOP_LSCAN_DONE;
-			return (0);
-		}
-		lim = LOCAL_LOOP_LIM;
-		break;
-	case TOPO_N_PORT:
-		lim = 2;
-		break;
-	default:
-		isp_prt(isp, ISP_LOG_SANCFG, "Chan %d no loop topology to scan", chan);
+	if (fcp->isp_topo != TOPO_NL_PORT && fcp->isp_topo != TOPO_FL_PORT &&
+	    fcp->isp_topo != TOPO_N_PORT) {
+		isp_prt(isp, ISP_LOG_SANCFG,
+		    "Chan %d no loop topology to scan", chan);
 		fcp->isp_loopstate = LOOP_LSCAN_DONE;
 		return (0);
 	}
 
 	fcp->isp_loopstate = LOOP_SCANNING_LOOP;
 
-	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop 0..%d", chan, lim-1);
+	lim = LOCAL_LOOP_LIM;
+	r = isp_gethandles(isp, chan, handles, &lim, 1, 1);
+	if (r != 0) {
+		isp_prt(isp, ISP_LOG_SANCFG,
+		    "Chan %d getting list of handles failed with %x", chan, r);
+fail:
+		ISP_MARK_PORTDB(isp, chan, 1);
+		isp_prt(isp, ISP_LOG_SANCFG,
+		    "Chan %d FC scan loop DONE (bad)", chan);
+		return (-1);
+	}
+
+	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop -- %d ports",
+	    chan, lim);
 
 	/*
 	 * Run through the list and get the port database info for each one.
 	 */
-	for (handle = 0; handle < lim; handle++) {
-		int r;
+	for (idx = 0; idx < lim; idx++) {
+		handle = handles[idx];
+
 		/*
 		 * Don't scan "special" ids.
 		 */
-		if (handle >= FL_ID && handle <= SNS_ID) {
-			continue;
-		}
 		if (ISP_CAP_2KLOGIN(isp)) {
-			if (handle >= NPH_RESERVED && handle <= NPH_IP_BCST) {
+			if (handle >= NPH_RESERVED - isp->isp_nchan)
+				continue;
+		} else {
+			if (handle >= FL_ID && handle <= SNS_ID)
 				continue;
-			}
 		}
+
 		/*
 		 * In older cards with older f/w GET_PORT_DATABASE has been
 		 * known to hang. This trick gets around that problem.
 		 */
 		if (IS_2100(isp) || IS_2200(isp)) {
 			uint64_t node_wwn = isp_get_wwn(isp, chan, handle, 1);
-			if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
-				isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop DONE (bad)", chan);
-				return (-1);
-			}
+			if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
+				goto fail;
 			if (node_wwn == INI_NONE) {
 				continue;
 			}
@@ -3192,19 +3254,13 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
 			isp_prt(isp, ISP_LOGDEBUG1,
 			    "Chan %d FC scan loop handle %d returned %x",
 			    chan, handle, r);
-			if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
-				ISP_MARK_PORTDB(isp, chan, 1);
-				isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop DONE (bad)", chan);
-				return (-1);
-			}
+			if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
+				goto fail;
 			continue;
 		}
 
-		if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
-			ISP_MARK_PORTDB(isp, chan, 1);
-			isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop DONE (bad)", chan);
-			return (-1);
-		}
+		if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
+			goto fail;
 
 		/*
 		 * On *very* old 2100 firmware we would end up sometimes
@@ -3214,10 +3270,9 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
 		 */
 		if (IS_2100(isp) && pdb.handle != handle) {
 			isp_prt(isp, ISP_LOGWARN,
-			    "Chan %d cannot synchronize port database", chan);
-			ISP_MARK_PORTDB(isp, chan, 1);
-			isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop DONE (bad)", chan);
-			return (-1);
+			    "Chan %d getpdb() returned wrong handle %x != %x",
+			    chan, pdb.handle, handle);
+			goto fail;
 		}
 
 		/*
@@ -3273,9 +3328,7 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
 				    "Chan %d [%d] not probational/zombie (0x%x)",
 				    chan, FC_PORTDB_TGT(isp, chan, lp), lp->state);
 				isp_dump_portdb(isp, chan);
-				ISP_MARK_PORTDB(isp, chan, 1);
-				isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop DONE (bad)", chan);
-				return (-1);
+				goto fail;
 			}
 
 			/*
@@ -3561,7 +3614,7 @@ isp_scan_fabric(ispsoftc_t *isp, int cha
 		loopid = FL_ID;
 	}
 	r = isp_getpdb(isp, chan, loopid, &pdb, 0);
-	if (r == MBOX_NOT_LOGGED_IN) {
+	if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) {
 		isp_dump_chip_portdb(isp, chan, 0);
 	}
 	if (r) {
@@ -7096,7 +7149,7 @@ static const uint32_t mbpfc[] = {
 	ISP_FC_OPMAP(0x07, 0x03),	/* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x1e: */
 	ISP_FC_OPMAP(0x01, 0x07),	/* 0x1f: MBOX_GET_FIRMWARE_STATUS */
-	ISP_FC_OPMAP_HALF(0x2, 0x01, 0x0, 0xcf),	/* 0x20: MBOX_GET_LOOP_ID */
+	ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf),	/* 0x20: MBOX_GET_LOOP_ID */
 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x21: */
 	ISP_FC_OPMAP(0x01, 0x07),	/* 0x22: MBOX_GET_RETRY_COUNT	*/
 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x23: */
@@ -7181,14 +7234,14 @@ static const uint32_t mbpfc[] = {
 	ISP_FC_OPMAP(0x0f, 0x0f),	/* 0x72: MBOX_INIT_LIP_LOGIN */
 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x73: */
 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x74: LOGIN LOOP PORT */
-	ISP_FC_OPMAP(0xcf, 0x03),	/* 0x75: GET PORT/NODE NAME LIST */
+	ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07),	/* 0x75: GET PORT/NODE NAME LIST */
 	ISP_FC_OPMAP(0x4f, 0x01),	/* 0x76: SET VENDOR ID */
 	ISP_FC_OPMAP(0xcd, 0x01),	/* 0x77: INITIALIZE IP MAILBOX */
 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x78: */
 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x79: */
 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x7a: */
 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x7b: */
-	ISP_FC_OPMAP(0x4f, 0x03),	/* 0x7c: Get ID List */
+	ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07),	/* 0x7c: Get ID List */
 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x7d: SEND LFA */
 	ISP_FC_OPMAP(0x0f, 0x01)	/* 0x7e: LUN RESET */
 };

Modified: head/sys/dev/isp/isp_library.c
==============================================================================
--- head/sys/dev/isp/isp_library.c	Wed Oct 28 12:31:29 2015	(r290103)
+++ head/sys/dev/isp/isp_library.c	Wed Oct 28 12:34:59 2015	(r290104)
@@ -1646,6 +1646,44 @@ isp_get_pdb_24xx(ispsoftc_t *isp, isp_pd
 	}
 }
 
+void
+isp_get_pnhle_21xx(ispsoftc_t *isp, isp_pnhle_21xx_t *src, isp_pnhle_21xx_t *dst)
+{
+
+	ISP_IOXGET_16(isp, &src->pnhle_port_id_lo, dst->pnhle_port_id_lo);
+	ISP_IOXGET_16(isp, &src->pnhle_port_id_hi_handle, dst->pnhle_port_id_hi_handle);
+}
+
+void
+isp_get_pnhle_23xx(ispsoftc_t *isp, isp_pnhle_23xx_t *src, isp_pnhle_23xx_t *dst)
+{
+
+	ISP_IOXGET_16(isp, &src->pnhle_port_id_lo, dst->pnhle_port_id_lo);
+	ISP_IOXGET_16(isp, &src->pnhle_port_id_hi, dst->pnhle_port_id_hi);
+	ISP_IOXGET_16(isp, &src->pnhle_handle, dst->pnhle_handle);
+}
+
+void
+isp_get_pnhle_24xx(ispsoftc_t *isp, isp_pnhle_24xx_t *src, isp_pnhle_24xx_t *dst)
+{
+
+	ISP_IOXGET_16(isp, &src->pnhle_port_id_lo, dst->pnhle_port_id_lo);
+	ISP_IOXGET_16(isp, &src->pnhle_port_id_hi, dst->pnhle_port_id_hi);
+	ISP_IOXGET_16(isp, &src->pnhle_handle, dst->pnhle_handle);
+	ISP_IOXGET_16(isp, &src->pnhle_reserved, dst->pnhle_reserved);
+}
+
+void
+isp_get_pnnle(ispsoftc_t *isp, isp_pnnle_t *src, isp_pnnle_t *dst)
+{
+	int i;
+
+	for (i = 0; i < 8; i++)
+		ISP_IOXGET_8(isp, &src->pnnle_name[i], dst->pnnle_name[i]);
+	ISP_IOXGET_16(isp, &src->pnnle_handle, dst->pnnle_handle);
+	ISP_IOXGET_16(isp, &src->pnnle_reserved, dst->pnnle_reserved);
+}
+
 /*
  * PLOGI/LOGO IOCB canonicalization
  */

Modified: head/sys/dev/isp/isp_library.h
==============================================================================
--- head/sys/dev/isp/isp_library.h	Wed Oct 28 12:31:29 2015	(r290103)
+++ head/sys/dev/isp/isp_library.h	Wed Oct 28 12:34:59 2015	(r290104)
@@ -123,6 +123,10 @@ void isp_put_vp_modify(ispsoftc_t *, vp_
 void isp_get_vp_modify(ispsoftc_t *, vp_modify_t *, vp_modify_t *);
 void isp_get_pdb_21xx(ispsoftc_t *, isp_pdb_21xx_t *, isp_pdb_21xx_t *);
 void isp_get_pdb_24xx(ispsoftc_t *, isp_pdb_24xx_t *, isp_pdb_24xx_t *);
+void isp_get_pnhle_21xx(ispsoftc_t *, isp_pnhle_21xx_t *, isp_pnhle_21xx_t *);
+void isp_get_pnhle_23xx(ispsoftc_t *, isp_pnhle_23xx_t *, isp_pnhle_23xx_t *);
+void isp_get_pnhle_24xx(ispsoftc_t *, isp_pnhle_24xx_t *, isp_pnhle_24xx_t *);
+void isp_get_pnnle(ispsoftc_t *, isp_pnnle_t *, isp_pnnle_t *);
 void isp_get_ridacq(ispsoftc_t *, isp_ridacq_t *, isp_ridacq_t *);
 void isp_get_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *);
 void isp_put_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *);

Modified: head/sys/dev/isp/ispmbox.h
==============================================================================
--- head/sys/dev/isp/ispmbox.h	Wed Oct 28 12:31:29 2015	(r290103)
+++ head/sys/dev/isp/ispmbox.h	Wed Oct 28 12:34:59 2015	(r290104)
@@ -156,6 +156,8 @@
 #define	MBOX_SEND_CHANGE_REQUEST	0x0070
 #define	MBOX_FABRIC_LOGOUT		0x0071
 #define	MBOX_INIT_LIP_LOGIN		0x0072
+#define	MBOX_GET_PORT_NODE_NAME_LIST	0x0075
+#define	MBOX_GET_ID_LIST		0x007C
 #define	MBOX_LUN_RESET			0x007E
 
 #define	MBOX_DRIVER_HEARTBEAT		0x005B
@@ -1342,6 +1344,40 @@ typedef struct {
 } isp_pdb_t;
 
 /*
+ * Port/Node Name List Element
+ */
+typedef struct {
+	uint8_t		pnnle_name[8];
+	uint16_t	pnnle_handle;
+	uint16_t	pnnle_reserved;
+} isp_pnnle_t;
+
+#define	PNNL_OPTIONS_NODE_NAMES	(1<<0)
+#define	PNNL_OPTIONS_PORT_DATA	(1<<2)
+#define	PNNL_OPTIONS_INITIATORS	(1<<3)
+
+/*
+ * Port and N-Port Handle List Element
+ */
+typedef struct {
+	uint16_t	pnhle_port_id_lo;
+	uint16_t	pnhle_port_id_hi_handle;
+} isp_pnhle_21xx_t;
+
+typedef struct {
+	uint16_t	pnhle_port_id_lo;
+	uint16_t	pnhle_port_id_hi;
+	uint16_t	pnhle_handle;
+} isp_pnhle_23xx_t;
+
+typedef struct {
+	uint16_t	pnhle_port_id_lo;
+	uint16_t	pnhle_port_id_hi;
+	uint16_t	pnhle_handle;
+	uint16_t	pnhle_reserved;
+} isp_pnhle_24xx_t;
+
+/*
  * Port Database Changed Async Event information for 24XX cards
  */
 #define	PDB24XX_AE_OK		0x00


More information about the svn-src-head mailing list