Index: head/sys/dev/isp/isp.c =================================================================== --- head/sys/dev/isp/isp.c +++ head/sys/dev/isp/isp.c @@ -2791,6 +2791,7 @@ 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 @@ } 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 @@ 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 @@ /* 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 @@ 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", Index: head/sys/dev/isp/isp_freebsd.c =================================================================== --- head/sys/dev/isp/isp_freebsd.c +++ head/sys/dev/isp/isp_freebsd.c @@ -3742,6 +3742,10 @@ 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 @@ (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 @@ 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); Index: head/sys/dev/isp/isp_stds.h =================================================================== --- head/sys/dev/isp/isp_stds.h +++ head/sys/dev/isp/isp_stds.h @@ -284,6 +284,14 @@ #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 */ Index: head/sys/dev/isp/ispmbox.h =================================================================== --- head/sys/dev/isp/ispmbox.h +++ head/sys/dev/isp/ispmbox.h @@ -1384,6 +1384,7 @@ */ typedef struct { uint16_t handle; + uint16_t prli_word0; uint16_t prli_word3; uint32_t : 8, portid : 24; Index: head/sys/dev/isp/ispvar.h =================================================================== --- head/sys/dev/isp/ispvar.h +++ head/sys/dev/isp/ispvar.h @@ -381,6 +381,9 @@ 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 @@ * 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,