From owner-svn-src-all@freebsd.org Mon Oct 5 08:31:49 2015 Return-Path: Delivered-To: svn-src-all@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 98B08A0F72E; Mon, 5 Oct 2015 08:31:49 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::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 88F53209; Mon, 5 Oct 2015 08:31:49 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t958VnaA009269; Mon, 5 Oct 2015 08:31:49 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t958VnYU009266; Mon, 5 Oct 2015 08:31:49 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201510050831.t958VnYU009266@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Mon, 5 Oct 2015 08:31:49 +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: r288714 - 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-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 05 Oct 2015 08:31:49 -0000 Author: mav Date: Mon Oct 5 08:31:48 2015 New Revision: 288714 URL: https://svnweb.freebsd.org/changeset/base/288714 Log: MFC r285459: Unify port database use for target and initiator roles. Aside from cleaner and more consistent code, this allows ports to be both target and initiator same time, and easily switch from any role to any. Modified: stable/10/sys/dev/isp/isp.c stable/10/sys/dev/isp/isp_freebsd.c stable/10/sys/dev/isp/isp_library.c stable/10/sys/dev/isp/isp_library.h stable/10/sys/dev/isp/isp_target.h stable/10/sys/dev/isp/ispvar.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/isp/isp.c ============================================================================== --- stable/10/sys/dev/isp/isp.c Mon Oct 5 08:30:49 2015 (r288713) +++ stable/10/sys/dev/isp/isp.c Mon Oct 5 08:31:48 2015 (r288714) @@ -65,16 +65,18 @@ __FBSDID("$FreeBSD$"); */ #define MBOX_DELAY_COUNT 1000000 / 100 #define ISP_MARK_PORTDB(a, b, c) \ - isp_prt(isp, ISP_LOG_SANCFG, \ - "Chan %d ISP_MARK_PORTDB@LINE %d", b, __LINE__); \ - isp_mark_portdb(a, b, c) + do { \ + isp_prt(isp, ISP_LOG_SANCFG, \ + "Chan %d ISP_MARK_PORTDB@LINE %d", (b), __LINE__); \ + isp_mark_portdb((a), (b), (c)); \ + } while (0) /* * Local static data */ static const char fconf[] = "Chan %d PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)"; static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d"; -static const char topology[] = "Chan %d WWPN 0x%08x%08x PortID 0x%06x N-Port Handle %d, Connection '%s'"; +static const char topology[] = "Chan %d WWPN 0x%08x%08x PortID 0x%06x handle 0x%x, Connection '%s'"; static const char bun[] = "bad underrun (count %d, resid %d, status %s)"; static const char lipd[] = "Chan %d LIP destroyed %d active commands"; static const char sacq[] = "unable to acquire scratch area"; @@ -2223,36 +2225,10 @@ 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; - 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); + fcportdb_t *lp; int i; if (chan < 0 || chan >= isp->isp_nchan) { @@ -2260,32 +2236,28 @@ isp_mark_portdb(ispsoftc_t *isp, int cha return; } for (i = 0; i < MAX_FC_TARG; i++) { - if (fcp->portdb[i].target_mode) { - if (disposition < 0) { - isp_prt(isp, ISP_LOGTINFO, "isp_mark_portdb: Chan %d zeroing handle 0x" "%04x port 0x%06x", chan, - fcp->portdb[i].handle, fcp->portdb[i].portid); - ISP_MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t)); - } - continue; - } - if (disposition == 0) { - ISP_MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t)); - } else { - switch (fcp->portdb[i].state) { - case FC_PORTDB_STATE_CHANGED: - case FC_PORTDB_STATE_PENDING_VALID: - case FC_PORTDB_STATE_VALID: - case FC_PORTDB_STATE_PROBATIONAL: - fcp->portdb[i].state = FC_PORTDB_STATE_PROBATIONAL; - break; - case FC_PORTDB_STATE_ZOMBIE: - break; - case FC_PORTDB_STATE_NIL: - default: - ISP_MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t)); - fcp->portdb[i].state = FC_PORTDB_STATE_NIL; - break; + lp = &fcp->portdb[i]; + switch (lp->state) { + case FC_PORTDB_STATE_PROBATIONAL: + case FC_PORTDB_STATE_DEAD: + case FC_PORTDB_STATE_CHANGED: + case FC_PORTDB_STATE_PENDING_VALID: + case FC_PORTDB_STATE_VALID: + if (disposition > 0) + lp->state = FC_PORTDB_STATE_PROBATIONAL; + else { + lp->state = FC_PORTDB_STATE_NIL; + isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); } + break; + case FC_PORTDB_STATE_ZOMBIE: + break; + case FC_PORTDB_STATE_NIL: + case FC_PORTDB_STATE_NEW: + default: + ISP_MEMZERO(lp, sizeof(*lp)); + lp->state = FC_PORTDB_STATE_NIL; + break; } } } @@ -2473,7 +2445,7 @@ isp_port_login(ispsoftc_t *isp, uint16_t return (MBOX_PORT_ID_USED | (mbs.param[1] << 16)); case MBOX_LOOP_ID_USED: - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, "isp_port_login: handle 0x%04x in use for port id 0x%02xXXXX", handle, mbs.param[1] & 0xff); + isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, "isp_port_login: handle 0x%x in use for port id 0x%02xXXXX", handle, mbs.param[1] & 0xff); return (MBOX_LOOP_ID_USED); case MBOX_COMMAND_COMPLETE: @@ -2559,7 +2531,7 @@ isp_getpdb(ispsoftc_t *isp, int chan, ui pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits); ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8); ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8); - isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x flags 0x%x curstate %x", chan, pdb->portid, un.bill.pdb_flags, un.bill.pdb_curstate); + isp_prt(isp, ISP_LOG_SANCFG, "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x", chan, id, pdb->portid, un.bill.pdb_flags, un.bill.pdb_curstate); if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) { mbs.param[0] = MBOX_NOT_LOGGED_IN; if (dolock) { @@ -2587,6 +2559,7 @@ isp_dump_chip_portdb(ispsoftc_t *isp, in isp_pdb_t pdb; int lim, loopid; + isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d chip port dump", chan); if (ISP_CAP_2KLOGIN(isp)) { lim = NPH_MAX_2K; } else { @@ -2988,16 +2961,8 @@ isp_pdb_sync(ispsoftc_t *isp, int chan) for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { lp = &fcp->portdb[dbidx]; - if (lp->state == FC_PORTDB_STATE_NIL || lp->target_mode) { - continue; - } - - if (lp->state == FC_PORTDB_STATE_VALID) { - if (dbidx != FL_ID) { - isp_prt(isp, - ISP_LOGERR, "portdb idx %d already valid", - dbidx); - } + if (lp->state == FC_PORTDB_STATE_NIL || + lp->state == FC_PORTDB_STATE_VALID) { continue; } @@ -3005,7 +2970,7 @@ isp_pdb_sync(ispsoftc_t *isp, int chan) case FC_PORTDB_STATE_PROBATIONAL: case FC_PORTDB_STATE_DEAD: lp->state = FC_PORTDB_STATE_NIL; - isp_async(isp, ISPASYNC_DEV_GONE, chan, lp, 0); + isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); if (lp->autologin == 0) { (void) isp_plogx(isp, chan, lp->handle, lp->portid, @@ -3029,17 +2994,14 @@ isp_pdb_sync(ispsoftc_t *isp, int chan) isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp); lp->new_prli_word3 = 0; lp->new_portid = 0; - lp->announced = 0; break; case FC_PORTDB_STATE_CHANGED: -/* - * XXXX FIX THIS - */ lp->state = FC_PORTDB_STATE_VALID; isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp); + lp->portid = lp->new_portid; + lp->prli_word3 = lp->new_prli_word3; lp->new_prli_word3 = 0; lp->new_portid = 0; - lp->announced = 0; break; case FC_PORTDB_STATE_PENDING_VALID: lp->portid = lp->new_portid; @@ -3050,13 +3012,12 @@ isp_pdb_sync(ispsoftc_t *isp, int chan) lp->new_prli_word3 = 0; lp->new_portid = 0; } - lp->announced = 0; break; case FC_PORTDB_STATE_ZOMBIE: break; default: isp_prt(isp, ISP_LOGWARN, - "isp_scan_loop: state %d for idx %d", + "isp_pdb_sync: state %d for idx %d", lp->state, dbidx); isp_dump_portdb(isp, chan); } @@ -3127,7 +3088,6 @@ isp_scan_loop(ispsoftc_t *isp, int chan) isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop 0..%d", chan, lim-1); - /* * Run through the list and get the port database info for each one. */ @@ -3211,6 +3171,9 @@ isp_scan_loop(ispsoftc_t *isp, int chan) */ if (tmp.node_wwn == 0 || tmp.port_wwn == 0 || tmp.portid == 0) { int a, b, c; + isp_prt(isp, ISP_LOGWARN, + "Chan %d bad pdb (WWNN %016jx, WWPN %016jx, PortID %06x, W3 0x%x, H 0x%x) @ handle 0x%x", + chan, tmp.node_wwn, tmp.port_wwn, tmp.portid, tmp.prli_word3, tmp.handle, handle); a = (tmp.node_wwn == 0); b = (tmp.port_wwn == 0); c = (tmp.portid == 0); @@ -3220,13 +3183,10 @@ isp_scan_loop(ispsoftc_t *isp, int chan) tmp.port_wwn = isp_get_wwn(isp, chan, handle, 0); if (tmp.node_wwn && tmp.port_wwn) { - isp_prt(isp, ISP_LOGINFO, "DODGED!"); + isp_prt(isp, ISP_LOGWARN, "DODGED!"); goto cont; } } - isp_prt(isp, ISP_LOGWARN, - "Chan %d bad pdb (%1d%1d%1d) @ handle 0x%x", chan, - a, b, c, handle); isp_dump_portdb(isp, chan); continue; } @@ -3234,30 +3194,19 @@ isp_scan_loop(ispsoftc_t *isp, int chan) /* * Now search the entire port database - * for the same Port and Node WWN. + * for the same Port WWN. */ - for (i = 0; i < MAX_FC_TARG; i++) { - lp = &fcp->portdb[i]; - - if (lp->state == FC_PORTDB_STATE_NIL || lp->target_mode) { - continue; - } - if (lp->node_wwn != tmp.node_wwn) { - continue; - } - if (lp->port_wwn != tmp.port_wwn) { - continue; - } - + if (isp_find_pdb_by_wwn(isp, chan, tmp.port_wwn, &lp)) { /* * Okay- we've found a non-nil entry that matches. * Check to make sure it's probational or a zombie. */ if (lp->state != FC_PORTDB_STATE_PROBATIONAL && - lp->state != FC_PORTDB_STATE_ZOMBIE) { + lp->state != FC_PORTDB_STATE_ZOMBIE && + lp->state != FC_PORTDB_STATE_VALID) { isp_prt(isp, ISP_LOGERR, "Chan %d [%d] not probational/zombie (0x%x)", - chan, i, lp->state); + 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); @@ -3269,6 +3218,7 @@ isp_scan_loop(ispsoftc_t *isp, int chan) * automatically. */ lp->autologin = 1; + lp->node_wwn = tmp.node_wwn; /* * Check to make see if really still the same @@ -3279,7 +3229,7 @@ isp_scan_loop(ispsoftc_t *isp, int chan) lp->new_prli_word3 = tmp.prli_word3; lp->state = FC_PORTDB_STATE_PENDING_VALID; isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Loop Port 0x%06x@0x%04x Pending Valid", chan, tmp.portid, tmp.handle); - break; + continue; } /* @@ -3296,13 +3246,6 @@ isp_scan_loop(ispsoftc_t *isp, int chan) lp->state = FC_PORTDB_STATE_CHANGED; lp->new_portid = tmp.portid; lp->new_prli_word3 = tmp.prli_word3; - break; - } - - /* - * Did we find and update an old entry? - */ - if (i < MAX_FC_TARG) { continue; } @@ -3311,9 +3254,6 @@ isp_scan_loop(ispsoftc_t *isp, int chan) * for it and save info for later disposition. */ for (i = 0; i < MAX_FC_TARG; i++) { - if (fcp->portdb[i].target_mode) { - continue; - } if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) { break; } @@ -3739,7 +3679,7 @@ isp_scan_fabric(ispsoftc_t *isp, int cha for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { lp = &fcp->portdb[dbidx]; - if (lp->state != FC_PORTDB_STATE_PROBATIONAL || lp->target_mode) { + if (lp->state != FC_PORTDB_STATE_PROBATIONAL) { continue; } if (lp->portid == portid) { @@ -3781,7 +3721,7 @@ isp_scan_fabric(ispsoftc_t *isp, int cha if (r != 0) { lp->new_portid = portid; lp->state = FC_PORTDB_STATE_DEAD; - isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric Port 0x%06x is dead", chan, portid); + isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric PortID 0x%06x handle 0x%x is dead (%d)", chan, portid, lp->handle, r); continue; } @@ -3797,7 +3737,7 @@ isp_scan_fabric(ispsoftc_t *isp, int cha if (pdb.handle != lp->handle || pdb.portid != portid || wwpn != lp->port_wwn || - wwnn != lp->node_wwn) { + (lp->node_wwn != 0 && wwnn != lp->node_wwn)) { isp_prt(isp, ISP_LOG_SANCFG, fconf, chan, dbidx, pdb.handle, pdb.portid, (uint32_t) (wwnn >> 32), (uint32_t) wwnn, @@ -3815,8 +3755,9 @@ isp_scan_fabric(ispsoftc_t *isp, int cha * portid consistency after re-login. * */ - if (isp_login_device(isp, chan, portid, &pdb, - &oldhandle)) { + if ((fcp->role & ISP_ROLE_INITIATOR) == 0 || + isp_login_device(isp, chan, portid, &pdb, + &oldhandle)) { lp->new_portid = portid; lp->state = FC_PORTDB_STATE_DEAD; if (fcp->isp_loopstate != @@ -3837,7 +3778,7 @@ isp_scan_fabric(ispsoftc_t *isp, int cha MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename); MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); if (wwpn != lp->port_wwn || - wwnn != lp->node_wwn) { + (lp->node_wwn != 0 && wwnn != lp->node_wwn)) { isp_prt(isp, ISP_LOGWARN, "changed WWN" " after relogin"); lp->new_portid = portid; @@ -3875,6 +3816,9 @@ isp_scan_fabric(ispsoftc_t *isp, int cha continue; } + if ((fcp->role & ISP_ROLE_INITIATOR) == 0) + continue; + /* * Ah- a new entry. Search the database again for all non-NIL * entries to make sure we never ever make a new database entry @@ -3888,12 +3832,6 @@ isp_scan_fabric(ispsoftc_t *isp, int cha lp <= &fcp->portdb[SNS_ID]) { continue; } - /* - * Skip any target mode entries. - */ - if (lp->target_mode) { - continue; - } if (lp->state == FC_PORTDB_STATE_NIL) { if (dbidx == MAX_FC_TARG) { dbidx = lp - fcp->portdb; @@ -3966,10 +3904,9 @@ isp_scan_fabric(ispsoftc_t *isp, int cha if (dbidx >= FL_ID && dbidx <= SNS_ID) { continue; } - if (fcp->portdb[dbidx].target_mode) { - continue; - } - if (fcp->portdb[dbidx].node_wwn == wwnn && fcp->portdb[dbidx].port_wwn == wwpn) { + if ((fcp->portdb[dbidx].node_wwn == wwnn || + fcp->portdb[dbidx].node_wwn == 0) && + fcp->portdb[dbidx].port_wwn == wwpn) { break; } } @@ -4007,6 +3944,7 @@ isp_scan_fabric(ispsoftc_t *isp, int cha */ lp = &fcp->portdb[dbidx]; lp->handle = handle; + lp->node_wwn = wwnn; lp->new_portid = portid; lp->new_prli_word3 = nr; if (lp->portid != portid || lp->prli_word3 != nr) { @@ -4393,7 +4331,7 @@ isp_start(XS_T *xs) isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d", target); lp = &fcp->portdb[target]; if (target < 0 || target >= MAX_FC_TARG || - lp->dev_map_idx == 0) { + lp->is_target == 0) { XS_SETERR(xs, HBA_SELTIMEOUT); return (CMD_COMPLETE); } @@ -4406,7 +4344,6 @@ isp_start(XS_T *xs) XS_SETERR(xs, HBA_SELTIMEOUT); return (CMD_COMPLETE); } - lp->dirty = 1; } else { sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs)); if ((sdp->role & ISP_ROLE_INITIATOR) == 0) { @@ -4417,6 +4354,7 @@ isp_start(XS_T *xs) if (sdp->update) { isp_spi_update(isp, XS_CHANNEL(xs)); } + lp = NULL; } start_again: @@ -4703,7 +4641,7 @@ isp_control(ispsoftc_t *isp, ispctl_t ct break; } lp = &fcp->portdb[tgt]; - if (lp->dev_map_idx == 0 || + if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) { isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt); break; @@ -4793,7 +4731,7 @@ isp_control(ispsoftc_t *isp, ispctl_t ct break; } lp = &fcp->portdb[tgt]; - if (lp->dev_map_idx == 0 || + if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) { isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt); break; @@ -5004,12 +4942,6 @@ isp_control(ispsoftc_t *isp, ispctl_t ct 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; @@ -7887,26 +7819,26 @@ isp_setdfltfcparm(ispsoftc_t *isp, int c * not disturb an already active list of commands. */ -void +int isp_reinit(ispsoftc_t *isp, int do_load_defaults) { - int i; + int i, res = 0; isp_reset(isp, do_load_defaults); - if (isp->isp_state != ISP_RESETSTATE) { + res = EIO; isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__); ISP_DISABLE_INTS(isp); goto cleanup; } isp_init(isp); - if (isp->isp_state == ISP_INITSTATE) { isp->isp_state = ISP_RUNSTATE; } if (isp->isp_state != ISP_RUNSTATE) { + res = EIO; #ifndef ISP_TARGET_MODE isp_prt(isp, ISP_LOGWARN, "%s: not at runstate", __func__); #endif @@ -7923,18 +7855,16 @@ isp_reinit(ispsoftc_t *isp, int do_load_ ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); } } - } + } cleanup: - isp->isp_nactive = 0; - isp_clear_commands(isp); if (IS_FC(isp)) { - for (i = 0; i < isp->isp_nchan; i++) { + for (i = 0; i < isp->isp_nchan; i++) ISP_MARK_PORTDB(isp, i, -1); - } } + return (res); } /* Modified: stable/10/sys/dev/isp/isp_freebsd.c ============================================================================== --- stable/10/sys/dev/isp/isp_freebsd.c Mon Oct 5 08:30:49 2015 (r288713) +++ stable/10/sys/dev/isp/isp_freebsd.c Mon Oct 5 08:31:48 2015 (r288714) @@ -52,11 +52,10 @@ MODULE_DEPEND(isp, cam, 1, 1, 1); int isp_announced = 0; int isp_fabric_hysteresis = 5; int isp_loop_down_limit = 60; /* default loop down limit */ -int isp_change_is_bad = 0; /* "changed" devices are bad */ int isp_quickboot_time = 7; /* don't wait more than N secs for loop up */ int isp_gone_device_time = 30; /* grace time before reporting device lost */ int isp_autoconfig = 1; /* automatically attach/detach devices */ -static const char prom3[] = "Chan %d PortID 0x%06x Departed from Target %u because of %s"; +static const char prom3[] = "Chan %d [%u] PortID 0x%06x Departed because of %s"; static void isp_freeze_loopdown(ispsoftc_t *, int, char *); static d_ioctl_t ispioctl; @@ -474,9 +473,6 @@ ispioctl(struct cdev *dev, u_long c, cad case ISP_RESETHBA: ISP_LOCK(isp); -#ifdef ISP_TARGET_MODE - isp_del_all_wwn_entries(isp, ISP_NOCHAN); -#endif isp_reinit(isp, 0); ISP_UNLOCK(isp); retval = 0; @@ -528,7 +524,7 @@ ispioctl(struct cdev *dev, u_long c, cad break; } lp = &FCPARAM(isp, ifc->chan)->portdb[ifc->loopid]; - if (lp->state == FC_PORTDB_STATE_VALID || lp->target_mode) { + if (lp->state != FC_PORTDB_STATE_NIL) { ifc->role = (lp->prli_word3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; ifc->loopid = lp->handle; ifc->portid = lp->portid; @@ -1512,13 +1508,7 @@ isp_disable_lun(ispsoftc_t *isp, union c done: if (status == CAM_REQ_CMP) { tptr->enabled = 0; - /* - * If we have no more luns enabled for this bus, - * delete all tracked wwns for it (if we are FC), - * and disable target mode. - */ if (is_any_lun_enabled(isp, bus) == 0) { - isp_del_all_wwn_entries(isp, bus); if (isp_disable_target_mode(isp, bus)) { status = CAM_REQ_CMP_ERR; } @@ -2467,7 +2457,9 @@ isp_handle_platform_atio2(ispsoftc_t *is /* * If we're not in the port database, add ourselves. */ - if (!IS_2100(isp) && isp_find_pdb_by_loopid(isp, 0, atiop->init_id, &lp) == 0) { + if (!IS_2100(isp) && + (isp_find_pdb_by_handle(isp, 0, atiop->init_id, &lp) == 0 || + lp->state == FC_PORTDB_STATE_ZOMBIE)) { uint64_t iid = (((uint64_t) aep->at_wwpn[0]) << 48) | (((uint64_t) aep->at_wwpn[1]) << 32) | @@ -2594,6 +2586,7 @@ isp_handle_platform_atio7(ispsoftc_t *is */ isp_prt(isp, ISP_LOGTINFO, "%s: [RX_ID 0x%x] D_ID 0x%06x found on Chan %d for S_ID 0x%06x wasn't in PDB already", __func__, aep->at_rxid, did, chan, sid); + isp_dump_portdb(isp, chan); isp_endcmd(isp, aep, NIL_HANDLE, chan, ECMD_TERMINATE, 0); return; } @@ -3116,7 +3109,7 @@ isp_handle_platform_notify_fc(ispsoftc_t } else { loopid = inp->in_iid; } - if (isp_find_pdb_by_loopid(isp, 0, loopid, &lp)) { + if (isp_find_pdb_by_handle(isp, 0, loopid, &lp)) { wwn = lp->port_wwn; } else { wwn = INI_ANY; @@ -3270,7 +3263,7 @@ isp_handle_platform_notify_24xx(ispsoftc case IN24XX_PORT_LOGOUT: ptr = "PORT LOGOUT"; - if (isp_find_pdb_by_loopid(isp, ISP_GET_VPIDX(isp, inot->in_vpidx), nphdl, &lp)) { + if (isp_find_pdb_by_handle(isp, ISP_GET_VPIDX(isp, inot->in_vpidx), nphdl, &lp)) { isp_del_wwn_entry(isp, ISP_GET_VPIDX(isp, inot->in_vpidx), lp->port_wwn, nphdl, lp->portid); } /* FALLTHROUGH */ @@ -4606,13 +4599,6 @@ isp_make_here(ispsoftc_t *isp, fcportdb_ xpt_free_ccb(ccb); return; } - - /* - * Since we're about to issue a rescan, mark this device as not - * reported gone. - */ - fcp->reported_gone = 0; - xpt_rescan(ccb); } @@ -4626,11 +4612,6 @@ isp_make_gone(ispsoftc_t *isp, fcportdb_ return; } if (xpt_create_path(&tp, NULL, cam_sim_path(fc->sim), tgt, CAM_LUN_WILDCARD) == CAM_REQ_CMP) { - /* - * We're about to send out the lost device async - * notification, so indicate that we have reported it gone. - */ - fcp->reported_gone = 1; xpt_async(AC_LOST_DEVICE, tp, NULL); xpt_free_path(tp); } @@ -4660,6 +4641,8 @@ isp_gdt_task(void *arg, int pending) ispsoftc_t *isp = fc->isp; int chan = fc - isp->isp_osinfo.pc.fc; fcportdb_t *lp; + struct ac_contract ac; + struct ac_device_changed *adc; int dbidx, more_to_do = 0; ISP_LOCK(isp); @@ -4670,19 +4653,27 @@ isp_gdt_task(void *arg, int pending) if (lp->state != FC_PORTDB_STATE_ZOMBIE) { continue; } - if (lp->dev_map_idx == 0 || lp->target_mode) { - continue; - } if (lp->gone_timer != 0) { - isp_prt(isp, ISP_LOG_SANCFG, "%s: Chan %d more to do for target %u (timer=%u)", __func__, chan, lp->dev_map_idx - 1, lp->gone_timer); lp->gone_timer -= 1; more_to_do++; continue; } - lp->dev_map_idx = 0; + isp_prt(isp, ISP_LOGCONFIG, prom3, chan, dbidx, lp->portid, "Gone Device Timeout"); + if (lp->is_target) { + lp->is_target = 0; + isp_make_gone(isp, lp, chan, dbidx); + } + if (lp->is_initiator) { + lp->is_initiator = 0; + ac.contract_number = AC_CONTRACT_DEV_CHG; + adc = (struct ac_device_changed *) ac.contract_data; + adc->wwpn = lp->port_wwn; + adc->port = lp->portid; + adc->target = lp->handle; + adc->arrived = 0; + xpt_async(AC_CONTRACT, fc->path, &ac); + } lp->state = FC_PORTDB_STATE_NIL; - isp_prt(isp, ISP_LOGCONFIG, prom3, chan, lp->portid, dbidx, "Gone Device Timeout"); - isp_make_gone(isp, lp, chan, dbidx); } if (fc->ready) { if (more_to_do) { @@ -4718,6 +4709,8 @@ isp_ldt_task(void *arg, int pending) ispsoftc_t *isp = fc->isp; int chan = fc - isp->isp_osinfo.pc.fc; fcportdb_t *lp; + struct ac_contract ac; + struct ac_device_changed *adc; int dbidx, i; ISP_LOCK(isp); @@ -4730,18 +4723,12 @@ isp_ldt_task(void *arg, int pending) for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { lp = &FCPARAM(isp, chan)->portdb[dbidx]; - if (lp->state != FC_PORTDB_STATE_PROBATIONAL) { - continue; - } - if (lp->dev_map_idx == 0 || lp->target_mode) { + if (lp->state == FC_PORTDB_STATE_NIL) continue; - } /* * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST! */ - - for (i = 0; i < isp->isp_maxcmds; i++) { struct ccb_scsiio *xs; @@ -4758,19 +4745,24 @@ isp_ldt_task(void *arg, int pending) isp->isp_xflist[i].handle, chan, XS_TGT(xs), XS_LUN(xs)); } - /* - * Mark that we've announced that this device is gone.... - */ - lp->announced = 1; - lp->dev_map_idx = 0; - lp->state = FC_PORTDB_STATE_NIL; - isp_prt(isp, ISP_LOGCONFIG, prom3, chan, lp->portid, dbidx, "Loop Down Timeout"); - isp_make_gone(isp, lp, chan, dbidx); + isp_prt(isp, ISP_LOGCONFIG, prom3, chan, dbidx, lp->portid, "Loop Down Timeout"); + if (lp->is_target) { + lp->is_target = 0; + isp_make_gone(isp, lp, chan, dbidx); + } + if (lp->is_initiator) { + lp->is_initiator = 0; + ac.contract_number = AC_CONTRACT_DEV_CHG; + adc = (struct ac_device_changed *) ac.contract_data; + adc->wwpn = lp->port_wwn; + adc->port = lp->portid; + adc->target = lp->handle; + adc->arrived = 0; + xpt_async(AC_CONTRACT, fc->path, &ac); + } } - if (FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR) { - isp_unfreeze_loopdown(isp, chan); - } + isp_unfreeze_loopdown(isp, chan); /* * The loop down timer has expired. Wake up the kthread * to notice that fact (or make it false). @@ -5585,7 +5577,7 @@ isp_done(XS_T *sccb) fcparam *fcp; fcp = FCPARAM(isp, XS_CHANNEL(sccb)); - fcp->portdb[XS_TGT(sccb)].reported_gone = 1; + fcp->portdb[XS_TGT(sccb)].is_target = 0; } if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { sccb->ccb_h.status |= CAM_DEV_QFRZN; @@ -5608,15 +5600,16 @@ isp_done(XS_T *sccb) void isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) { - 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"; + int bus; + static const char prom[] = "Chan %d [%d] WWPN 0x%16jx PortID 0x%06x handle 0x%x %s %s"; char buf[64]; char *msg = NULL; target_id_t tgt; fcportdb_t *lp; struct isp_fc *fc; struct cam_path *tmppath; + struct ac_contract ac; + struct ac_device_changed *adc; va_list ap; switch (cmd) { @@ -5718,10 +5711,10 @@ isp_async(ispsoftc_t *isp, ispasync_t cm if (fc->path) { isp_freeze_loopdown(isp, bus, msg); } - if (!callout_active(&fc->ldt)) { - callout_reset(&fc->ldt, fc->loop_down_limit * hz, isp_ldt, fc); - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Starting Loop Down Timer @ %lu", (unsigned long) time_uptime); - } + } + if (!callout_active(&fc->ldt)) { + callout_reset(&fc->ldt, fc->loop_down_limit * hz, isp_ldt, fc); + isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Starting Loop Down Timer @ %lu", (unsigned long) time_uptime); } } isp_fcp_reset_crn(fc, /*tgt*/0, /*tgt_set*/ 0); @@ -5751,19 +5744,25 @@ isp_async(ispsoftc_t *isp, ispasync_t cm lp = va_arg(ap, fcportdb_t *); va_end(ap); fc = ISP_FC_PC(isp, bus); - lp->announced = 0; - lp->gone_timer = 0; - if ((FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) && (lp->prli_word3 & PRLI_WD3_TARGET_FUNCTION)) { - lp->dev_map_idx = (lp - FCPARAM(isp, bus)->portdb) + 1; - } + tgt = FC_PORTDB_TGT(isp, bus, lp); isp_gen_role_str(buf, sizeof (buf), lp->prli_word3); - if (lp->dev_map_idx) { - tgt = lp->dev_map_idx - 1; - isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, buf, "arrived at", tgt, (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn); + isp_prt(isp, ISP_LOGCONFIG, prom, bus, tgt, lp->port_wwn, lp->portid, lp->handle, buf, "arrived"); + if ((FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) && + (lp->prli_word3 & PRLI_WD3_TARGET_FUNCTION)) { + lp->is_target = 1; isp_fcp_reset_crn(fc, tgt, /*tgt_set*/ 1); isp_make_here(isp, lp, bus, tgt); - } else { - isp_prt(isp, ISP_LOGCONFIG, prom0, bus, lp->portid, lp->handle, buf, "arrived", (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn); + } + if ((FCPARAM(isp, bus)->role & ISP_ROLE_TARGET) && + (lp->prli_word3 & PRLI_WD3_INITIATOR_FUNCTION)) { + lp->is_initiator = 1; + ac.contract_number = AC_CONTRACT_DEV_CHG; + adc = (struct ac_device_changed *) ac.contract_data; + adc->wwpn = lp->port_wwn; + adc->port = lp->portid; + adc->target = lp->handle; + adc->arrived = 1; + xpt_async(AC_CONTRACT, fc->path, &ac); } break; case ISPASYNC_DEV_CHANGED: @@ -5772,97 +5771,68 @@ isp_async(ispsoftc_t *isp, ispasync_t cm lp = va_arg(ap, fcportdb_t *); va_end(ap); fc = ISP_FC_PC(isp, bus); - lp->announced = 0; - lp->gone_timer = 0; - if (isp_change_is_bad) { - lp->state = FC_PORTDB_STATE_NIL; - if (lp->dev_map_idx) { - tgt = lp->dev_map_idx - 1; - lp->dev_map_idx = 0; - isp_prt(isp, ISP_LOGCONFIG, prom3, bus, lp->portid, tgt, "change is bad"); - isp_make_gone(isp, lp, bus, tgt); - } else { - isp_gen_role_str(buf, sizeof (buf), lp->prli_word3); - isp_prt(isp, ISP_LOGCONFIG, prom0, bus, lp->portid, lp->handle, buf, "changed and departed", - (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn); - } - } else { - lp->portid = lp->new_portid; - lp->prli_word3 = lp->new_prli_word3; - isp_gen_role_str(buf, sizeof (buf), lp->prli_word3); - if (lp->dev_map_idx) { - tgt = lp->dev_map_idx - 1; - isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, buf, "changed at", tgt, - (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn); + tgt = FC_PORTDB_TGT(isp, bus, lp); + isp_gen_role_str(buf, sizeof (buf), lp->new_prli_word3); + isp_prt(isp, ISP_LOGCONFIG, prom, bus, tgt, lp->port_wwn, lp->new_portid, lp->handle, buf, "changed"); +changed: + if (lp->is_target != + ((FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) && + (lp->new_prli_word3 & PRLI_WD3_TARGET_FUNCTION))) { + lp->is_target = !lp->is_target; + if (lp->is_target) { isp_fcp_reset_crn(fc, tgt, /*tgt_set*/ 1); + isp_make_here(isp, lp, bus, tgt); } else { - isp_prt(isp, ISP_LOGCONFIG, prom0, bus, lp->portid, lp->handle, buf, "changed", (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn); + isp_make_gone(isp, lp, bus, tgt); + isp_fcp_reset_crn(fc, tgt, /*tgt_set*/ 1); } } + if (lp->is_initiator != + ((FCPARAM(isp, bus)->role & ISP_ROLE_TARGET) && + (lp->new_prli_word3 & PRLI_WD3_INITIATOR_FUNCTION))) { + lp->is_initiator = !lp->is_initiator; + ac.contract_number = AC_CONTRACT_DEV_CHG; + adc = (struct ac_device_changed *) ac.contract_data; + adc->wwpn = lp->port_wwn; + adc->port = lp->portid; + adc->target = lp->handle; + adc->arrived = lp->is_initiator; + xpt_async(AC_CONTRACT, fc->path, &ac); + } break; case ISPASYNC_DEV_STAYED: va_start(ap, cmd); bus = va_arg(ap, int); lp = va_arg(ap, fcportdb_t *); va_end(ap); + fc = ISP_FC_PC(isp, bus); + tgt = FC_PORTDB_TGT(isp, bus, lp); isp_gen_role_str(buf, sizeof (buf), lp->prli_word3); - if (lp->dev_map_idx) { - fc = ISP_FC_PC(isp, bus); - tgt = lp->dev_map_idx - 1; - isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, buf, "stayed at", tgt, - (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn); - /* - * Only issue a rescan if we've actually reported - * that this device is gone. - */ - if (lp->reported_gone != 0) { - isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, buf, "rescanned at", tgt, - (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn); - isp_make_here(isp, lp, bus, tgt); - } - } else { - isp_prt(isp, ISP_LOGCONFIG, prom0, bus, lp->portid, lp->handle, buf, "stayed", - (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn); - } - break; + isp_prt(isp, ISP_LOGCONFIG, prom, bus, tgt, lp->port_wwn, lp->portid, lp->handle, buf, "stayed"); + goto changed; case ISPASYNC_DEV_GONE: 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); + tgt = FC_PORTDB_TGT(isp, bus, lp); /* - * If this has a virtual target and we haven't marked it - * that we're going to have isp_gdt tell the OS it's gone, - * set the isp_gdt timer running on it. - * - * If it isn't marked that isp_gdt is going to get rid of it, - * announce that it's gone. - * + * If this has a virtual target or initiator set the isp_gdt + * timer running on it to delay its departure. */ isp_gen_role_str(buf, sizeof (buf), lp->prli_word3); - if (lp->dev_map_idx && lp->announced == 0 && now) { - lp->announced = 1; - tgt = lp->dev_map_idx - 1; - 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; + if (lp->is_target || lp->is_initiator) { lp->state = FC_PORTDB_STATE_ZOMBIE; - lp->gone_timer = ISP_FC_PC(isp, bus)->gone_device_time; + lp->gone_timer = fc->gone_device_time; + isp_prt(isp, ISP_LOGCONFIG, prom, bus, tgt, lp->port_wwn, lp->portid, lp->handle, buf, "gone zombie"); if (fc->ready && !callout_active(&fc->gdt)) { isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Starting Gone Device Timer with %u seconds time now %lu", bus, lp->gone_timer, (unsigned long)time_uptime); callout_reset(&fc->gdt, hz, isp_gdt, fc); } - tgt = lp->dev_map_idx - 1; - isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, buf, "gone zombie 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->announced == 0) { - isp_prt(isp, ISP_LOGCONFIG, prom0, bus, lp->portid, lp->handle, buf, "departed", (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn); + break; } + isp_prt(isp, ISP_LOGCONFIG, prom, bus, tgt, lp->port_wwn, lp->portid, lp->handle, buf, "gone"); break; case ISPASYNC_CHANGE_NOTIFY: { @@ -5928,13 +5898,11 @@ isp_async(ispsoftc_t *isp, ispasync_t cm case NT_LIP_RESET: case NT_LINK_UP: case NT_LINK_DOWN: + case NT_HBA_RESET: /* * No action need be taken here. */ break; - case NT_HBA_RESET: - isp_del_all_wwn_entries(isp, ISP_NOCHAN); - break; case NT_GLOBAL_LOGOUT: case NT_LOGOUT: /* @@ -5942,34 +5910,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cm */ isp_handle_platform_target_notify_ack(isp, notify); break; - case NT_ARRIVED: - { - struct ac_contract ac; - struct ac_device_changed *fc; - - ac.contract_number = AC_CONTRACT_DEV_CHG; - fc = (struct ac_device_changed *) ac.contract_data; - fc->wwpn = notify->nt_wwn; - fc->port = notify->nt_sid; - fc->target = notify->nt_nphdl; - fc->arrived = 1; - xpt_async(AC_CONTRACT, ISP_FC_PC(isp, notify->nt_channel)->path, &ac); - break; - } - case NT_DEPARTED: - { - struct ac_contract ac; - struct ac_device_changed *fc; - - ac.contract_number = AC_CONTRACT_DEV_CHG; - fc = (struct ac_device_changed *) ac.contract_data; - fc->wwpn = notify->nt_wwn; - fc->port = notify->nt_sid; - fc->target = notify->nt_nphdl; - fc->arrived = 0; - xpt_async(AC_CONTRACT, ISP_FC_PC(isp, notify->nt_channel)->path, &ac); - break; - } default: *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***