From owner-svn-src-stable-10@freebsd.org Mon Nov 30 21:28:54 2015 Return-Path: Delivered-To: svn-src-stable-10@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id BB9FEA3DDB4; Mon, 30 Nov 2015 21:28:54 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 87F7817A7; Mon, 30 Nov 2015 21:28:54 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tAULSrWe066707; Mon, 30 Nov 2015 21:28:53 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tAULSrU8066702; Mon, 30 Nov 2015 21:28:53 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201511302128.tAULSrU8066702@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Mon, 30 Nov 2015 21:28:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r291498 - stable/10/sys/dev/isp X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 Nov 2015 21:28:54 -0000 Author: mav Date: Mon Nov 30 21:28:53 2015 New Revision: 291498 URL: https://svnweb.freebsd.org/changeset/base/291498 Log: MFC r290104: 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: stable/10/sys/dev/isp/isp.c stable/10/sys/dev/isp/isp_library.c stable/10/sys/dev/isp/isp_library.h stable/10/sys/dev/isp/ispmbox.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/isp/isp.c ============================================================================== --- stable/10/sys/dev/isp/isp.c Mon Nov 30 21:23:30 2015 (r291497) +++ stable/10/sys/dev/isp/isp.c Mon Nov 30 21:28:53 2015 (r291498) @@ -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: stable/10/sys/dev/isp/isp_library.c ============================================================================== --- stable/10/sys/dev/isp/isp_library.c Mon Nov 30 21:23:30 2015 (r291497) +++ stable/10/sys/dev/isp/isp_library.c Mon Nov 30 21:28:53 2015 (r291498) @@ -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: stable/10/sys/dev/isp/isp_library.h ============================================================================== --- stable/10/sys/dev/isp/isp_library.h Mon Nov 30 21:23:30 2015 (r291497) +++ stable/10/sys/dev/isp/isp_library.h Mon Nov 30 21:28:53 2015 (r291498) @@ -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: stable/10/sys/dev/isp/ispmbox.h ============================================================================== --- stable/10/sys/dev/isp/ispmbox.h Mon Nov 30 21:23:30 2015 (r291497) +++ stable/10/sys/dev/isp/ispmbox.h Mon Nov 30 21:28:53 2015 (r291498) @@ -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