diff options
-rw-r--r-- | sys/dev/isp/isp.c | 216 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 274 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.c | 270 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.h | 5 | ||||
-rw-r--r-- | sys/dev/isp/isp_target.h | 2 | ||||
-rw-r--r-- | sys/dev/isp/ispvar.h | 42 |
6 files changed, 301 insertions, 508 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 0e600d1..aaab1c3 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -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 chan, int disposition) 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 handle, uint32_t portid) 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, uint16_t id, isp_pdb_t *pdb, int dolock) 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, int chan, int dolock) 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 chan) 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 chan) 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 chan) 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 chan) * 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 chan) 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 chan) 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 chan) 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 chan) 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 chan) */ 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 ctl, ...) 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 ctl, ...) 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 ctl, ...) 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 chan) * 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_defaults) 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); } /* diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index c3b45cb..e87e79a 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -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, caddr_t addr, int flags, struct thread *td) 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, caddr_t addr, int flags, struct thread *td) 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 ccb *ccb) 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 *isp, at2_entry_t *aep) /* * 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 *isp, at7_entry_t *aep) */ 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 *isp, in_fcentry_t *inp) } 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_t *isp, in_fcentry_24xx_t *inot) 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_t *fcp, int chan, int tgt) 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_t *fcp, int chan, int tgt) 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 cmd, ...) 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 cmd, ...) 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 cmd, ...) 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 cmd, ...) 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 cmd, ...) */ 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: isp_prt(isp, ISP_LOGALL, "target notify code 0x%x", notify->nt_ncode); isp_handle_platform_target_notify_ack(isp, notify); @@ -6060,7 +6000,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) nt->nt_tgt = TGT_ANY; } else { nt->nt_tgt = FCPARAM(isp, chan)->isp_wwpn; - if (isp_find_pdb_by_loopid(isp, chan, abts->abts_nphdl, &lp)) { + if (isp_find_pdb_by_handle(isp, chan, abts->abts_nphdl, &lp)) { nt->nt_wwn = lp->port_wwn; } else { nt->nt_wwn = INI_ANY; diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index 2f7dc4e..f7ee7bb 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -411,10 +411,6 @@ isp_fc_runstate(ispsoftc_t *isp, int chan, int tval) } } - if ((fcp->role & ISP_ROLE_INITIATOR) == 0) { - return (0); - } - if (isp_control(isp, ISPCTL_SCAN_LOOP, chan) != 0) { isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan loop fails on channel %d", chan); return (LOOP_PDB_RCVD); @@ -444,7 +440,7 @@ isp_dump_portdb(ispsoftc_t *isp, int chan) int i; for (i = 0; i < MAX_FC_TARG; i++) { - char mb[4], buf1[64], buf2[64]; + char buf1[64], buf2[64]; const char *dbs[8] = { "NIL ", "PROB", @@ -457,18 +453,13 @@ isp_dump_portdb(ispsoftc_t *isp, int chan) }; fcportdb_t *lp = &fcp->portdb[i]; - if (lp->state == FC_PORTDB_STATE_NIL && lp->target_mode == 0) { + if (lp->state == FC_PORTDB_STATE_NIL) { continue; } - if (lp->dev_map_idx) { - ISP_SNPRINTF(mb, sizeof (mb), "%3d", ((int) lp->dev_map_idx) - 1); - } else { - ISP_SNPRINTF(mb, sizeof (mb), "---"); - } isp_gen_role_str(buf1, sizeof (buf1), lp->prli_word3); isp_gen_role_str(buf2, sizeof (buf2), lp->new_prli_word3); - isp_prt(isp, ISP_LOGALL, "Chan %d [%d]: hdl 0x%x %s al%d tgt %s %s 0x%06x =>%s 0x%06x; WWNN 0x%08x%08x WWPN 0x%08x%08x", - chan, i, lp->handle, dbs[lp->state], lp->autologin, mb, buf1, lp->portid, buf2, lp->new_portid, + isp_prt(isp, ISP_LOGALL, "Chan %d [%d]: hdl 0x%x %s al%d %s 0x%06x =>%s 0x%06x; WWNN 0x%08x%08x WWPN 0x%08x%08x", + chan, i, lp->handle, dbs[lp->state], lp->autologin, buf1, lp->portid, buf2, lp->new_portid, (uint32_t) (lp->node_wwn >> 32), (uint32_t) (lp->node_wwn), (uint32_t) (lp->port_wwn >> 32), (uint32_t) (lp->port_wwn)); } } @@ -603,20 +594,8 @@ isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role) return (ENXIO); } if (chan == 0) { - isp_clear_commands(isp); - isp_reset(isp, 0); - if (isp->isp_state != ISP_RESETSTATE) { - isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__); - return (EIO); - } fcp->role = new_role; - isp_init(isp); - if (isp->isp_state != ISP_INITSTATE) { - isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__); - return (EIO); - } - isp->isp_state = ISP_RUNSTATE; - return (0); + return (isp_reinit(isp, 0)); } else if (ISP_CAP_MULTI_ID(isp)) { mbreg_t mbs; vp_modify_t *vp; @@ -2347,8 +2326,10 @@ isp_destroy_tgt_handle(ispsoftc_t *isp, uint32_t handle) } } +#endif + /* - * Find target mode entries + * Find port database entries */ int isp_find_pdb_by_wwn(ispsoftc_t *isp, int chan, uint64_t wwn, fcportdb_t **lptr) @@ -2359,10 +2340,10 @@ isp_find_pdb_by_wwn(ispsoftc_t *isp, int chan, uint64_t wwn, fcportdb_t **lptr) if (chan >= isp->isp_nchan) return (0); fcp = FCPARAM(isp, chan); - for (i = MAX_FC_TARG - 1; i >= 0; i--) { + for (i = 0; i < MAX_FC_TARG; i++) { fcportdb_t *lp = &fcp->portdb[i]; - if (lp->target_mode == 0) + if (lp->state == FC_PORTDB_STATE_NIL) continue; if (lp->port_wwn == wwn) { *lptr = lp; @@ -2372,8 +2353,10 @@ isp_find_pdb_by_wwn(ispsoftc_t *isp, int chan, uint64_t wwn, fcportdb_t **lptr) return (0); } +#ifdef ISP_TARGET_MODE + int -isp_find_pdb_by_loopid(ispsoftc_t *isp, int chan, uint32_t loopid, fcportdb_t **lptr) +isp_find_pdb_by_handle(ispsoftc_t *isp, int chan, uint32_t handle, fcportdb_t **lptr) { fcparam *fcp; int i; @@ -2381,9 +2364,15 @@ isp_find_pdb_by_loopid(ispsoftc_t *isp, int chan, uint32_t loopid, fcportdb_t ** if (chan >= isp->isp_nchan) return (0); fcp = FCPARAM(isp, chan); - if ((i = fcp->isp_tgt_map[loopid]) > 0) { - *lptr = &fcp->portdb[i - 1]; - return (1); + for (i = 0; i < MAX_FC_TARG; i++) { + fcportdb_t *lp = &fcp->portdb[i]; + + if (lp->state == FC_PORTDB_STATE_NIL) + continue; + if (lp->handle == handle) { + *lptr = lp; + return (1); + } } return (0); } @@ -2397,10 +2386,10 @@ isp_find_pdb_by_sid(ispsoftc_t *isp, int chan, uint32_t sid, fcportdb_t **lptr) if (chan >= isp->isp_nchan) return (0); fcp = FCPARAM(isp, chan); - for (i = MAX_FC_TARG - 1; i >= 0; i--) { + for (i = 0; i < MAX_FC_TARG; i++) { fcportdb_t *lp = &fcp->portdb[i]; - if (lp->target_mode == 0) + if (lp->state == FC_PORTDB_STATE_NIL) continue; if (lp->portid == sid) { *lptr = lp; @@ -2437,14 +2426,13 @@ isp_add_wwn_entry(ispsoftc_t *isp, int chan, uint64_t ini, uint16_t nphdl, uint3 char buf[64]; fcparam *fcp; fcportdb_t *lp; - isp_notify_t nt; - int i, something, take, taken; + int i, change; fcp = FCPARAM(isp, chan); if (nphdl >= MAX_NPORT_HANDLE) { - isp_prt(isp, ISP_LOGWARN, "Chan %d IID 0x%016llx " - "N-Port handle 0x%04x Port ID 0x%06x -- bad handle", - chan, (unsigned long long) ini, nphdl, s_id); + isp_prt(isp, ISP_LOGTINFO|ISP_LOGWARN, "Chan %d WWPN 0x%016llx " + "PortID 0x%06x handle 0x%x -- bad handle", + chan, (unsigned long long) ini, s_id, nphdl); return; } @@ -2453,146 +2441,118 @@ isp_add_wwn_entry(ispsoftc_t *isp, int chan, uint64_t ini, uint16_t nphdl, uint3 * with new parameters. Some cases of update can be suspicious, * so log them verbosely and dump the whole port database. */ - if ((i = fcp->isp_tgt_map[nphdl]) > 0) { - take = taken = i - 1; - lp = &fcp->portdb[taken]; - something = 0; + if ((VALID_INI(ini) && isp_find_pdb_by_wwn(isp, chan, ini, &lp)) || + (s_id != PORT_NONE && isp_find_pdb_by_sid(isp, chan, s_id, &lp))) { + change = 0; + lp->new_portid = lp->portid; + lp->new_prli_word3 = lp->prli_word3; if (s_id != PORT_NONE && lp->portid != s_id) { if (lp->portid == PORT_NONE) { isp_prt(isp, ISP_LOGTINFO, - "Chan %d IID 0x%016llx N-port handle 0x%04x " - "gets Port ID 0x%06x", + "Chan %d WWPN 0x%016llx handle 0x%x " + "gets PortID 0x%06x", chan, (unsigned long long) lp->port_wwn, nphdl, s_id); } else { isp_prt(isp, ISP_LOGTINFO|ISP_LOGWARN, - "Chan %d IID 0x%016llx N-port handle 0x%04x " - "changes Port ID 0x%06x to 0x%06x", + "Chan %d WWPN 0x%016llx handle 0x%x " + "changes PortID 0x%06x to 0x%06x", chan, (unsigned long long) lp->port_wwn, nphdl, lp->portid, s_id); if (isp->isp_dblev & (ISP_LOGTINFO|ISP_LOGWARN)) isp_dump_portdb(isp, chan); } - lp->portid = s_id; - something++; + lp->new_portid = s_id; + change++; } if (VALID_INI(ini) && lp->port_wwn != ini) { if (!VALID_INI(lp->port_wwn)) { isp_prt(isp, ISP_LOGTINFO, - "Chan %d N-port handle 0x%04x Port ID " - "0x%06x gets WWN 0x%016llxx", - chan, nphdl, lp->portid, + "Chan %d PortID 0x%06x handle 0x%x " + "gets WWN 0x%016llxx", + chan, lp->portid, nphdl, (unsigned long long) ini); } else if (lp->port_wwn != ini) { isp_prt(isp, ISP_LOGTINFO|ISP_LOGWARN, - "Chan %d N-port handle 0x%04x Port ID " - "0x%06x changes WWN 0x%016llx to 0x%016llx", - chan, nphdl, lp->portid, + "Chan %d PortID 0x%06x handle 0x%x " + "changes WWN 0x%016llx to 0x%016llx", + chan, lp->portid, nphdl, (unsigned long long) lp->port_wwn, (unsigned long long) ini); if (isp->isp_dblev & (ISP_LOGTINFO|ISP_LOGWARN)) isp_dump_portdb(isp, chan); } lp->port_wwn = ini; - something++; + change++; } - if (lp->prli_word3 != prli_params) { - lp->prli_word3 = prli_params; - isp_gen_role_str(buf, sizeof (buf), lp->prli_word3); + if (prli_params != 0 && lp->prli_word3 != prli_params) { + isp_gen_role_str(buf, sizeof (buf), prli_params); isp_prt(isp, ISP_LOGTINFO|ISP_LOGCONFIG, - "Chan %d IID 0x%016llx N-Port Handle 0x%04x " - "Port ID 0x%06x changes PRLI Word 3 %s", + "Chan %d WWPN 0x%016llx PortID 0x%06x " + "handle 0x%x changes PRLI Word 3 %s", chan, (unsigned long long) lp->port_wwn, - lp->handle, lp->portid, buf); - something++; + lp->portid, lp->handle, buf); + lp->new_prli_word3 = prli_params; + change++; } - if (!something) { - isp_prt(isp, ISP_LOGTINFO, - "Chan %d IID 0x%016llx N-Port Handle 0x%04x " - "Port ID 0x%06x reentered", + if (lp->handle != nphdl) { + isp_prt(isp, ISP_LOGTINFO|ISP_LOGCONFIG, + "Chan %d WWPN 0x%016llx PortID 0x%06x " + "changes handle 0x%x to 0x%x", chan, (unsigned long long) lp->port_wwn, - lp->handle, lp->portid); - } - } else - take = taken = -1; - - /* - * Search for records colliding on handler, Port ID or WWN. - * Remove any found collisions, logging suspicious cases of - * still valid records. - */ - for (i = 0; i < MAX_FC_TARG; i++) { - lp = &fcp->portdb[i]; - if (lp->target_mode == 0 || i == take) - continue; - if (lp->handle != nphdl && lp->portid != s_id && - lp->port_wwn != ini) - continue; - if (lp->state == FC_PORTDB_STATE_VALID) { - isp_prt(isp, ISP_LOGTINFO|ISP_LOGWARN, - "Chan %d IID 0x%016llx N-Port Handle 0x%04x " - "Port ID 0x%06x is conflicting", + lp->portid, lp->handle, nphdl); + lp->handle = nphdl; + change++; + } + lp->state = FC_PORTDB_STATE_VALID; + if (change) { + 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; + } else { + isp_prt(isp, ISP_LOGTINFO, + "Chan %d WWPN 0x%016llx PortID 0x%06x " + "handle 0x%x reentered", chan, (unsigned long long) lp->port_wwn, - lp->handle, lp->portid); - if (isp->isp_dblev & (ISP_LOGTINFO|ISP_LOGWARN)) - isp_dump_portdb(isp, chan); - isp_del_wwn_entry(isp, chan, - lp->port_wwn, lp->handle, lp->portid); + lp->portid, lp->handle); + isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp); } - ISP_MEMZERO(lp, sizeof (fcportdb_t)); - take = i; - } - - /* If valid record already exists -- we are done. */ - if (taken >= 0) return; + } /* Search for room to insert new record. */ - if (take < 0) { - for (i = MAX_FC_TARG - 1; i >= 0; i--) { - if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) { - take = i; - break; - } - } + for (i = 0; i < MAX_FC_TARG; i++) { + if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) + break; } - if (take < 0) { + if (i >= MAX_FC_TARG) { isp_prt(isp, ISP_LOGTINFO|ISP_LOGWARN, - "Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x " + "Chan %d WWPN 0x%016llx PortID 0x%06x handle 0x%x " "-- no room in port database", - chan, (unsigned long long) ini, nphdl, s_id); + chan, (unsigned long long) ini, s_id, nphdl); if (isp->isp_dblev & (ISP_LOGTINFO|ISP_LOGWARN)) isp_dump_portdb(isp, chan); return; } /* Insert new record and mark it valid. */ - lp = &fcp->portdb[take]; + lp = &fcp->portdb[i]; ISP_MEMZERO(lp, sizeof (fcportdb_t)); - lp->target_mode = 1; lp->handle = nphdl; lp->portid = s_id; lp->port_wwn = ini; - lp->prli_word3 = prli_params; + lp->prli_word3 = (prli_params != 0) ? prli_params : PRLI_WD3_INITIATOR_FUNCTION; lp->state = FC_PORTDB_STATE_VALID; - fcp->isp_tgt_map[nphdl] = take + 1; isp_gen_role_str(buf, sizeof (buf), lp->prli_word3); - isp_prt(isp, ISP_LOGTINFO, "Chan %d IID 0x%016llx N-Port Handle 0x%04x" - " Port ID 0x%06x vtgt %d %s added", chan, - (unsigned long long) ini, nphdl, s_id, take, buf); - - /* Notify above levels about new initiator arrival. */ - ISP_MEMZERO(&nt, sizeof (nt)); - nt.nt_hba = isp; - nt.nt_wwn = ini; - nt.nt_tgt = FCPARAM(isp, chan)->isp_wwpn; - nt.nt_sid = s_id; - nt.nt_did = FCPARAM(isp, chan)->isp_portid; - nt.nt_nphdl = nphdl; - nt.nt_channel = chan; - nt.nt_ncode = NT_ARRIVED; - isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); + isp_prt(isp, ISP_LOGTINFO, "Chan %d WWPN 0x%016llx " + "PortID 0x%06x handle 0x%x vtgt %d %s added", chan, + (unsigned long long) ini, s_id, nphdl, i, buf); + + /* Notify above levels about new port arrival. */ + isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp); } /* @@ -2602,45 +2562,27 @@ void isp_del_wwn_entry(ispsoftc_t *isp, int chan, uint64_t ini, uint16_t nphdl, uint32_t s_id) { fcparam *fcp; - isp_notify_t nt; fcportdb_t *lp; if (nphdl >= MAX_NPORT_HANDLE) { - isp_prt(isp, ISP_LOGWARN, "Chan %d IID 0x%016llx bad N-Port handle 0x%04x Port ID 0x%06x", - chan, (unsigned long long) ini, nphdl, s_id); + isp_prt(isp, ISP_LOGWARN, "Chan %d WWPN 0x%016llx PortID 0x%06x bad handle 0x%x", + chan, (unsigned long long) ini, s_id, nphdl); return; } fcp = FCPARAM(isp, chan); - if (fcp->isp_tgt_map[nphdl] == 0) { - lp = NULL; - } else { - lp = &fcp->portdb[fcp->isp_tgt_map[nphdl] - 1]; - if (lp->target_mode == 0) { - lp = NULL; - } - } - if (lp == NULL) { - isp_prt(isp, ISP_LOGWARN, "Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x cannot be found to be deleted", - chan, (unsigned long long) ini, nphdl, s_id); + if (isp_find_pdb_by_handle(isp, chan, nphdl, &lp) == 0) { + isp_prt(isp, ISP_LOGWARN, "Chan %d WWPN 0x%016llx PortID 0x%06x handle 0x%x cannot be found to be deleted", + chan, (unsigned long long) ini, s_id, nphdl); isp_dump_portdb(isp, chan); return; } - isp_prt(isp, ISP_LOGTINFO, "Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x vtgt %d deleted", - chan, (unsigned long long) lp->port_wwn, nphdl, lp->portid, fcp->isp_tgt_map[nphdl] - 1); - fcp->isp_tgt_map[nphdl] = 0; - lp->state = FC_PORTDB_STATE_DEAD; + isp_prt(isp, ISP_LOGTINFO, "Chan %d WWPN 0x%016llx PortID 0x%06x handle 0x%x vtgt %d deleted", + chan, (unsigned long long) lp->port_wwn, lp->portid, nphdl, FC_PORTDB_TGT(isp, chan, lp)); + lp->state = FC_PORTDB_STATE_NIL; - ISP_MEMZERO(&nt, sizeof (nt)); - nt.nt_hba = isp; - nt.nt_wwn = lp->port_wwn; - nt.nt_tgt = FCPARAM(isp, chan)->isp_wwpn; - nt.nt_sid = lp->portid; - nt.nt_did = FCPARAM(isp, chan)->isp_portid; - nt.nt_nphdl = nphdl; - nt.nt_channel = chan; - nt.nt_ncode = NT_DEPARTED; - isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); + /* Notify above levels about gone port. */ + isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); } void @@ -2671,11 +2613,11 @@ isp_del_all_wwn_entries(ispsoftc_t *isp, int chan) if (fcp == NULL) { return; } - for (i = 0; i < MAX_NPORT_HANDLE; i++) { - if (fcp->isp_tgt_map[i]) { - fcportdb_t *lp = &fcp->portdb[fcp->isp_tgt_map[i] - 1]; + for (i = 0; i < MAX_FC_TARG; i++) { + fcportdb_t *lp = &fcp->portdb[i]; + + if (lp->state != FC_PORTDB_STATE_NIL) isp_del_wwn_entry(isp, chan, lp->port_wwn, lp->handle, lp->portid); - } } } @@ -2702,7 +2644,7 @@ isp_del_wwn_entries(ispsoftc_t *isp, isp_notify_t *mp) * We need to find the actual entry so we can delete it. */ if (mp->nt_nphdl != NIL_HANDLE) { - if (isp_find_pdb_by_loopid(isp, mp->nt_channel, mp->nt_nphdl, &lp)) { + if (isp_find_pdb_by_handle(isp, mp->nt_channel, mp->nt_nphdl, &lp)) { isp_del_wwn_entry(isp, mp->nt_channel, lp->port_wwn, lp->handle, lp->portid); return; } @@ -2719,8 +2661,8 @@ isp_del_wwn_entries(ispsoftc_t *isp, isp_notify_t *mp) return; } } - isp_prt(isp, ISP_LOGWARN, "Chan %d unable to find entry to delete N-port handle 0x%04x initiator WWN 0x%016llx Port ID 0x%06x", - mp->nt_channel, mp->nt_nphdl, (unsigned long long) mp->nt_wwn, mp->nt_sid); + isp_prt(isp, ISP_LOGWARN, "Chan %d unable to find entry to delete WWPN 0x%016jx PortID 0x%06x handle 0x%x", + mp->nt_channel, mp->nt_wwn, mp->nt_sid, mp->nt_nphdl); } void diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h index a326bfa..cc0cfaa 100644 --- a/sys/dev/isp/isp_library.h +++ b/sys/dev/isp/isp_library.h @@ -165,9 +165,10 @@ int isp_allocate_xs_tgt(ispsoftc_t *, void *, uint32_t *); void *isp_find_xs_tgt(ispsoftc_t *, uint32_t); uint32_t isp_find_tgt_handle(ispsoftc_t *, void *); void isp_destroy_tgt_handle(ispsoftc_t *, uint32_t); - +#endif int isp_find_pdb_by_wwn(ispsoftc_t *, int, uint64_t, fcportdb_t **); -int isp_find_pdb_by_loopid(ispsoftc_t *, int, uint32_t, fcportdb_t **); +#ifdef ISP_TARGET_MODE +int isp_find_pdb_by_handle(ispsoftc_t *, int, uint32_t, fcportdb_t **); int isp_find_pdb_by_sid(ispsoftc_t *, int, uint32_t, fcportdb_t **); void isp_find_chan_by_did(ispsoftc_t *, uint32_t, uint16_t *); void isp_add_wwn_entry(ispsoftc_t *, int, uint64_t, uint16_t, uint32_t, uint16_t); diff --git a/sys/dev/isp/isp_target.h b/sys/dev/isp/isp_target.h index 40a1732..8922a33 100644 --- a/sys/dev/isp/isp_target.h +++ b/sys/dev/isp/isp_target.h @@ -51,8 +51,6 @@ typedef enum { NT_LOGOUT, NT_GLOBAL_LOGOUT, NT_CHANGED, - NT_ARRIVED, - NT_DEPARTED, NT_HBA_RESET } isp_ncode_t; diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index 27167fa..2d5379a 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -376,9 +376,6 @@ typedef struct { * duples. * * + There can never be two non-NIL entries with the same handle. - * - * + There can never be two non-NIL entries which have the same dev_map_idx - * value. */ typedef struct { /* @@ -389,8 +386,6 @@ typedef struct { uint16_t handle; /* - * The dev_map_idx, if nonzero, is the system virtual target ID (+1) - * * A device is 'autologin' if the firmware automatically logs into * it (re-logins as needed). Basically, local private loop devices. * @@ -398,27 +393,24 @@ typedef struct { * * The state is the current state of this entry. * + * The is_target is the current state of target on this port. + * + * The is_initiator is the current state of initiator on this port. + * * Portid is obvious, as are node && port WWNs. The new_role and * new_portid is for when we are pending a change. - * - * The 'target_mode' tag means that this entry arrived via a - * target mode command and is immune from normal flushing rules. - * You should also never see anything with an initiator role - * with this set. */ uint16_t prli_word3; /* PRLI parameters */ uint16_t new_prli_word3; /* Incoming new PRLI parameters */ - uint16_t dev_map_idx : 12, + uint16_t : 12, autologin : 1, /* F/W does PLOGI/PLOGO */ state : 3; - uint32_t : 7, - target_mode : 1, + uint32_t : 6, + is_target : 1, + is_initiator : 1, portid : 24; uint32_t - : 5, - reported_gone : 1, - announced : 1, - dirty : 1, /* commands have been run */ + : 8, new_portid : 24; uint64_t node_wwn; uint64_t port_wwn; @@ -434,6 +426,8 @@ typedef struct { #define FC_PORTDB_STATE_ZOMBIE 6 #define FC_PORTDB_STATE_VALID 7 +#define FC_PORTDB_TGT(isp, bus, pdb) (int)(lp - FCPARAM(isp, bus)->portdb) + /* * FC card specific information * @@ -485,18 +479,6 @@ typedef struct { */ fcportdb_t portdb[MAX_FC_TARG]; -#ifdef ISP_TARGET_MODE - /* - * This maps N-Port Handle to portdb entry so we - * don't have to search for every incoming command. - * - * The mapping function is to take any non-zero entry and - * subtract one to get the portdb index. This means that - * entries which are zero are unmapped (i.e., don't exist). - */ - uint16_t isp_tgt_map[MAX_NPORT_HANDLE]; -#endif - /* * Scratch DMA mapped in area to fetch Port Database stuff, etc. */ @@ -840,7 +822,7 @@ void isp_init(ispsoftc_t *); /* * Reset the ISP and call completion for any orphaned commands. */ -void isp_reinit(ispsoftc_t *, int); +int isp_reinit(ispsoftc_t *, int); /* * Internal Interrupt Service Routine |