From owner-svn-src-all@freebsd.org Fri May 17 14:29:58 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 182101596B07; Fri, 17 May 2019 14:29:58 +0000 (UTC) (envelope-from ken@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id AEF7D75B63; Fri, 17 May 2019 14:29:57 +0000 (UTC) (envelope-from ken@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 mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 7D35897B6; Fri, 17 May 2019 14:29:57 +0000 (UTC) (envelope-from ken@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x4HETv2G074060; Fri, 17 May 2019 14:29:57 GMT (envelope-from ken@FreeBSD.org) Received: (from ken@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x4HETuLc074054; Fri, 17 May 2019 14:29:56 GMT (envelope-from ken@FreeBSD.org) Message-Id: <201905171429.x4HETuLc074054@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ken set sender to ken@FreeBSD.org using -f From: "Kenneth D. Merry" Date: Fri, 17 May 2019 14:29:56 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r347906 - stable/12/sys/dev/isp X-SVN-Group: stable-12 X-SVN-Commit-Author: ken X-SVN-Commit-Paths: stable/12/sys/dev/isp X-SVN-Commit-Revision: 347906 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: AEF7D75B63 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.98 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.998,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.98)[-0.982,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 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: Fri, 17 May 2019 14:29:58 -0000 Author: ken Date: Fri May 17 14:29:56 2019 New Revision: 347906 URL: https://svnweb.freebsd.org/changeset/base/347906 Log: MFC r345008: ------------------------------------------------------------------------ r345008 | ken | 2019-03-11 10:21:14 -0400 (Mon, 11 Mar 2019) | 59 lines Fix CRN resets in the isp(4) driver in certain situations. The Command Reference Number (CRN) is part of the FC-Tape features that we enable when talking to tape drives. It starts at 1, and goes to 255 and wraps around to 1. There are a number of reset type conditions that result in the CRN getting reset to 1. These are detailed in section 4.10 (table 8) of the FCP-4r02b specification. One of the conditions is when a PRLI (Process Login) is sent by the initiator, and the Establish Image Pair bit is set in Word 0 of the PRLI. Previously, the isp(4) driver core sent a notification via isp_async() that the target had changed or stayed in place, but there was no indication of whether a PRLI was sent and whether the Establish Image Pair bit was set. The result of this was that in some situations, notably switching back and forth between a direct connection and a switch connection to a tape drive, the isp(4) driver would fail to reset the CRN in situations that require it according to the spec. When the CRN isn't reset in a situation that requires it, the tape drive then rejects every subsequent command that is sent to the drive. It is assuming that the commands are being sent out of order. So, modify the isp(4) driver to include Word 0 of the PRLI command when it sends isp_async() notifications of target changes. Look at the Establish Image Pair bit, and reset the CRN if that bit is set. With this change, I am able to switch a tape drive back and forth between a direct connection and a switch connection, and the isp(4) driver resets the CRN when it should. sys/dev/isp_stds.h: Add bit definitions for PRLI Word 0. sys/dev/ispmbox.h: Add PRLI Word 0 to the port database type, isp_pdb_t. sys/dev/ispvar.h Add PRLI Word 0 to fcportdb_t. sys/dev/isp.c: Populate the new prli_word0 parameter in the port database. In isp_pdb_add_update(), add a check to see if the Establish Image Pair bit is set in PRLI Word 0. If it is, then that is an additional reason to create a change notification. sys/dev/isp_freebsd.c: In isp_async(), if the device changed or stayed, look at PRLI Word 0 to see if the Establish Image Pair bit is set. If it is, reset the CRN if we haven't already. Sponsored by: Spectra Logic ------------------------------------------------------------------------ Differential Revision: https://reviews.freebsd.org/D19472 Modified: stable/12/sys/dev/isp/isp.c stable/12/sys/dev/isp/isp_freebsd.c stable/12/sys/dev/isp/isp_stds.h stable/12/sys/dev/isp/ispmbox.h stable/12/sys/dev/isp/ispvar.h Modified: stable/12/sys/dev/isp/isp.c ============================================================================== --- stable/12/sys/dev/isp/isp.c Fri May 17 14:09:33 2019 (r347905) +++ stable/12/sys/dev/isp/isp.c Fri May 17 14:29:56 2019 (r347906) @@ -2791,6 +2791,7 @@ isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp if (IS_24XX(isp)) { isp_get_pdb_24xx(isp, isp->isp_iocb, &un.bill); pdb->handle = un.bill.pdb_handle; + pdb->prli_word0 = un.bill.pdb_prli_svc0; pdb->prli_word3 = un.bill.pdb_prli_svc3; pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits); ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8); @@ -2807,6 +2808,7 @@ isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp } else { isp_get_pdb_21xx(isp, isp->isp_iocb, &un.fred); pdb->handle = un.fred.pdb_loopid; + pdb->prli_word0 = un.fred.pdb_prli_svc0; pdb->prli_word3 = un.fred.pdb_prli_svc3; pdb->portid = BITS2WORD(un.fred.pdb_portid_bits); ISP_MEMCPY(pdb->portname, un.fred.pdb_portname, 8); @@ -3196,6 +3198,7 @@ isp_pdb_sync(ispsoftc_t *isp, int chan) lp->state = FC_PORTDB_STATE_VALID; isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp); lp->portid = lp->new_portid; + lp->prli_word0 = lp->new_prli_word0; lp->prli_word3 = lp->new_prli_word3; break; case FC_PORTDB_STATE_VALID: @@ -3247,7 +3250,8 @@ isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_ /* Old device, nothing new. */ if (lp->portid == pdb->portid && lp->handle == pdb->handle && - lp->prli_word3 == pdb->prli_word3) { + lp->prli_word3 == pdb->prli_word3 && + ((pdb->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR) == 0)) { if (lp->state != FC_PORTDB_STATE_NEW) lp->state = FC_PORTDB_STATE_VALID; isp_prt(isp, ISP_LOG_SANCFG, @@ -3260,6 +3264,7 @@ isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_ lp->state = FC_PORTDB_STATE_CHANGED; lp->handle = pdb->handle; lp->new_portid = pdb->portid; + lp->new_prli_word0 = pdb->prli_word0; lp->new_prli_word3 = pdb->prli_word3; isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is changed", Modified: stable/12/sys/dev/isp/isp_freebsd.c ============================================================================== --- stable/12/sys/dev/isp/isp_freebsd.c Fri May 17 14:09:33 2019 (r347905) +++ stable/12/sys/dev/isp/isp_freebsd.c Fri May 17 14:29:56 2019 (r347906) @@ -3742,6 +3742,10 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) break; case ISPASYNC_DEV_CHANGED: case ISPASYNC_DEV_STAYED: + { + int crn_reset_done; + + crn_reset_done = 0; va_start(ap, cmd); bus = va_arg(ap, int); lp = va_arg(ap, fcportdb_t *); @@ -3759,13 +3763,17 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) (lp->new_prli_word3 & PRLI_WD3_TARGET_FUNCTION))) { lp->is_target = !lp->is_target; if (lp->is_target) { - if (cmd == ISPASYNC_DEV_CHANGED) + if (cmd == ISPASYNC_DEV_CHANGED) { isp_fcp_reset_crn(isp, bus, tgt, /*tgt_set*/ 1); + crn_reset_done = 1; + } isp_make_here(isp, lp, bus, tgt); } else { isp_make_gone(isp, lp, bus, tgt); - if (cmd == ISPASYNC_DEV_CHANGED) + if (cmd == ISPASYNC_DEV_CHANGED) { isp_fcp_reset_crn(isp, bus, tgt, /*tgt_set*/ 1); + crn_reset_done = 1; + } } } if (lp->is_initiator != @@ -3780,7 +3788,13 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) adc->arrived = lp->is_initiator; xpt_async(AC_CONTRACT, fc->path, &ac); } + + if ((lp->new_prli_word0 & PRLI_WD0_EST_IMAGE_PAIR) && + (crn_reset_done == 0)) + isp_fcp_reset_crn(isp, bus, tgt, /*tgt_set*/ 1); + break; + } case ISPASYNC_DEV_GONE: va_start(ap, cmd); bus = va_arg(ap, int); Modified: stable/12/sys/dev/isp/isp_stds.h ============================================================================== --- stable/12/sys/dev/isp/isp_stds.h Fri May 17 14:09:33 2019 (r347905) +++ stable/12/sys/dev/isp/isp_stds.h Fri May 17 14:29:56 2019 (r347906) @@ -284,6 +284,14 @@ typedef struct { #define RNC 0x53 /* + * PRLI Word 0 definitions + * FPC4-r02b January, 2011 + */ +#define PRLI_WD0_TYPE_MASK 0xff000000 +#define PRLI_WD0_TC_EXT_MASK 0x00ff0000 +#define PRLI_WD0_EST_IMAGE_PAIR (1 << 13) + +/* * PRLI Word 3 definitions * FPC4-r02b January, 2011 */ Modified: stable/12/sys/dev/isp/ispmbox.h ============================================================================== --- stable/12/sys/dev/isp/ispmbox.h Fri May 17 14:09:33 2019 (r347905) +++ stable/12/sys/dev/isp/ispmbox.h Fri May 17 14:29:56 2019 (r347906) @@ -1384,6 +1384,7 @@ typedef struct { */ typedef struct { uint16_t handle; + uint16_t prli_word0; uint16_t prli_word3; uint32_t : 8, portid : 24; Modified: stable/12/sys/dev/isp/ispvar.h ============================================================================== --- stable/12/sys/dev/isp/ispvar.h Fri May 17 14:09:33 2019 (r347905) +++ stable/12/sys/dev/isp/ispvar.h Fri May 17 14:29:56 2019 (r347906) @@ -381,6 +381,9 @@ typedef struct { uint16_t handle; /* + * PRLI word 0 contains the Establish Image Pair bit, which is + * important for knowing when to reset the CRN. + * * PRLI word 3 parameters contains role as well as other things. * * The state is the current state of this entry. @@ -392,7 +395,9 @@ typedef struct { * Portid is obvious, as are node && port WWNs. The new_role and * new_portid is for when we are pending a change. */ + uint16_t prli_word0; /* PRLI parameters */ uint16_t prli_word3; /* PRLI parameters */ + uint16_t new_prli_word0; /* Incoming new PRLI parameters */ uint16_t new_prli_word3; /* Incoming new PRLI parameters */ uint16_t : 12, probational : 1,