diff options
Diffstat (limited to 'sys/dev/isp')
-rw-r--r-- | sys/dev/isp/isp.c | 565 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 20 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.h | 56 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.c | 327 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.h | 15 | ||||
-rw-r--r-- | sys/dev/isp/isp_pci.c | 297 | ||||
-rw-r--r-- | sys/dev/isp/isp_sbus.c | 120 | ||||
-rw-r--r-- | sys/dev/isp/isp_target.c | 4 | ||||
-rw-r--r-- | sys/dev/isp/ispmbox.h | 2 | ||||
-rw-r--r-- | sys/dev/isp/ispvar.h | 29 |
10 files changed, 678 insertions, 757 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index d394011..d5c393b 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -108,12 +108,12 @@ static void isp_fibre_init(ispsoftc_t *); static void isp_fibre_init_2400(ispsoftc_t *); static void isp_clear_portdb(ispsoftc_t *, int); static void isp_mark_portdb(ispsoftc_t *, int); -static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int, int); +static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int); static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t); static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t); -static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *, int); -static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int, int); -static void isp_dump_chip_portdb(ispsoftc_t *, int, int); +static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *); +static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int); +static void isp_dump_chip_portdb(ispsoftc_t *, int); static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int); static int isp_fclink_test(ispsoftc_t *, int, int); static int isp_pdb_sync(ispsoftc_t *, int); @@ -2142,19 +2142,41 @@ isp_fibre_init_2400(ispsoftc_t *isp) if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) { icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24; } - icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_AUTO; if (isp->isp_confopts & ISP_CFG_1GB) { + icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_1GB; } else if (isp->isp_confopts & ISP_CFG_2GB) { + icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_2GB; } else if (isp->isp_confopts & ISP_CFG_4GB) { + icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_4GB; } else if (isp->isp_confopts & ISP_CFG_8GB) { + icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_8GB; } else if (isp->isp_confopts & ISP_CFG_16GB) { + icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_16GB; } else { - icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO; + switch (icbp->icb_fwoptions3 & ICB2400_OPT3_RATE_MASK) { + case ICB2400_OPT3_RATE_4GB: + case ICB2400_OPT3_RATE_8GB: + case ICB2400_OPT3_RATE_16GB: + case ICB2400_OPT3_RATE_AUTO: + break; + case ICB2400_OPT3_RATE_2GB: + if (isp->isp_type <= ISP_HA_FC_2500) + break; + /*FALLTHROUGH*/ + case ICB2400_OPT3_RATE_1GB: + if (isp->isp_type <= ISP_HA_FC_2400) + break; + /*FALLTHROUGH*/ + default: + icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK; + icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO; + break; + } } icbp->icb_logintime = ICB_LOGIN_TOV; @@ -2322,6 +2344,161 @@ isp_fibre_init_2400(ispsoftc_t *isp) isp->isp_state = ISP_RUNSTATE; } +static int +isp_fc_enable_vp(ispsoftc_t *isp, int chan) +{ + fcparam *fcp = FCPARAM(isp, chan); + vp_modify_t vp; + void *reqp; + uint8_t resp[QENTRY_LEN]; + + /* Build a VP MODIFY command in memory */ + ISP_MEMZERO(&vp, sizeof(vp)); + vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY; + vp.vp_mod_hdr.rqs_entry_count = 1; + vp.vp_mod_cnt = 1; + vp.vp_mod_idx0 = chan; + vp.vp_mod_cmd = VP_MODIFY_ENA; + vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED | + ICB2400_VPOPT_ENA_SNSLOGIN; + if (fcp->role & ISP_ROLE_INITIATOR) + vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE; + if ((fcp->role & ISP_ROLE_TARGET) == 0) + vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE; + if (fcp->isp_loopid < LOCAL_LOOP_LIM) { + vp.vp_mod_ports[0].loopid = fcp->isp_loopid; + if (isp->isp_confopts & ISP_CFG_OWNLOOPID) + vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS; + else + vp.vp_mod_ports[0].options |= ICB2400_VPOPT_PREV_ADDRESS; + } + MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn); + MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn); + + /* Prepare space for response in memory */ + memset(resp, 0xff, sizeof(resp)); + vp.vp_mod_hdl = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); + if (vp.vp_mod_hdl == 0) { + isp_prt(isp, ISP_LOGERR, + "%s: VP_MODIFY of Chan %d out of handles", __func__, chan); + return (EIO); + } + + /* Send request and wait for response. */ + reqp = isp_getrqentry(isp); + if (reqp == NULL) { + isp_prt(isp, ISP_LOGERR, + "%s: VP_MODIFY of Chan %d out of rqent", __func__, chan); + isp_destroy_handle(isp, vp.vp_mod_hdl); + return (EIO); + } + isp_put_vp_modify(isp, &vp, (vp_modify_t *)reqp); + ISP_SYNC_REQUEST(isp); + if (msleep(resp, &isp->isp_lock, 0, "VP_MODIFY", 5*hz) == EWOULDBLOCK) { + isp_prt(isp, ISP_LOGERR, + "%s: VP_MODIFY of Chan %d timed out", __func__, chan); + isp_destroy_handle(isp, vp.vp_mod_hdl); + return (EIO); + } + isp_get_vp_modify(isp, (vp_modify_t *)resp, &vp); + + if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) { + isp_prt(isp, ISP_LOGERR, + "%s: VP_MODIFY of Chan %d failed with flags %x status %d", + __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status); + return (EIO); + } + return (0); +} + +static int +isp_fc_disable_vp(ispsoftc_t *isp, int chan) +{ + vp_ctrl_info_t vp; + void *reqp; + uint8_t resp[QENTRY_LEN]; + + /* Build a VP CTRL command in memory */ + ISP_MEMZERO(&vp, sizeof(vp)); + vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL; + vp.vp_ctrl_hdr.rqs_entry_count = 1; + if (ISP_CAP_VP0(isp)) { + vp.vp_ctrl_status = 1; + } else { + vp.vp_ctrl_status = 0; + chan--; /* VP0 can not be controlled in this case. */ + } + vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL; + vp.vp_ctrl_vp_count = 1; + vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16); + + /* Prepare space for response in memory */ + memset(resp, 0xff, sizeof(resp)); + vp.vp_ctrl_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); + if (vp.vp_ctrl_handle == 0) { + isp_prt(isp, ISP_LOGERR, + "%s: VP_CTRL of Chan %d out of handles", __func__, chan); + return (EIO); + } + + /* Send request and wait for response. */ + reqp = isp_getrqentry(isp); + if (reqp == NULL) { + isp_prt(isp, ISP_LOGERR, + "%s: VP_CTRL of Chan %d out of rqent", __func__, chan); + isp_destroy_handle(isp, vp.vp_ctrl_handle); + return (EIO); + } + isp_put_vp_ctrl_info(isp, &vp, (vp_ctrl_info_t *)reqp); + ISP_SYNC_REQUEST(isp); + if (msleep(resp, &isp->isp_lock, 0, "VP_CTRL", 5*hz) == EWOULDBLOCK) { + isp_prt(isp, ISP_LOGERR, + "%s: VP_CTRL of Chan %d timed out", __func__, chan); + isp_destroy_handle(isp, vp.vp_ctrl_handle); + return (EIO); + } + isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)resp, &vp); + + if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) { + isp_prt(isp, ISP_LOGERR, + "%s: VP_CTRL of Chan %d failed with flags %x status %d %d", + __func__, chan, vp.vp_ctrl_hdr.rqs_flags, + vp.vp_ctrl_status, vp.vp_ctrl_index_fail); + return (EIO); + } + return (0); +} + +static int +isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role) +{ + fcparam *fcp = FCPARAM(isp, chan); + int i, was, res = 0; + + if (chan >= isp->isp_nchan) { + isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan); + return (ENXIO); + } + if (fcp->role == new_role) + return (0); + for (was = 0, i = 0; i < isp->isp_nchan; i++) { + if (FCPARAM(isp, i)->role != ISP_ROLE_NONE) + was++; + } + if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) { + fcp->role = new_role; + return (isp_reinit(isp, 0)); + } + if (fcp->role != ISP_ROLE_NONE) { + res = isp_fc_disable_vp(isp, chan); + isp_clear_portdb(isp, chan); + } + fcp->role = new_role; + if (fcp->role != ISP_ROLE_NONE) + res = isp_fc_enable_vp(isp, chan); + return (res); +} + static void isp_clear_portdb(ispsoftc_t *isp, int chan) { @@ -2373,13 +2550,11 @@ isp_mark_portdb(ispsoftc_t *isp, int chan) * or via FABRIC LOGIN/FABRIC LOGOUT for other cards. */ static int -isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags, int gs) +isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags) { - mbreg_t mbs; - uint8_t q[QENTRY_LEN]; - isp_plogx_t *plp; - fcparam *fcp; - uint8_t *scp; + isp_plogx_t pl; + void *reqp; + uint8_t resp[QENTRY_LEN]; uint32_t sst, parm1; int rval, lev; const char *msg; @@ -2399,63 +2574,58 @@ isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags } } - ISP_MEMZERO(q, QENTRY_LEN); - plp = (isp_plogx_t *) q; - plp->plogx_header.rqs_entry_count = 1; - plp->plogx_header.rqs_entry_type = RQSTYPE_LOGIN; - plp->plogx_handle = 0xffffffff; - plp->plogx_nphdl = handle; - plp->plogx_vphdl = chan; - plp->plogx_portlo = portid; - plp->plogx_rspsz_porthi = (portid >> 16) & 0xff; - plp->plogx_flags = flags; + ISP_MEMZERO(&pl, sizeof(pl)); + pl.plogx_header.rqs_entry_count = 1; + pl.plogx_header.rqs_entry_type = RQSTYPE_LOGIN; + pl.plogx_nphdl = handle; + pl.plogx_vphdl = chan; + pl.plogx_portlo = portid; + pl.plogx_rspsz_porthi = (portid >> 16) & 0xff; + pl.plogx_flags = flags; - if (isp->isp_dblev & ISP_LOGDEBUG1) { - isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, plp); - } - - if (gs == 0) { - if (FC_SCRATCH_ACQUIRE(isp, chan)) { - isp_prt(isp, ISP_LOGERR, sacq); - return (-1); - } + /* Prepare space for response in memory */ + memset(resp, 0xff, sizeof(resp)); + pl.plogx_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL); + if (pl.plogx_handle == 0) { + isp_prt(isp, ISP_LOGERR, + "%s: PLOGX of Chan %d out of handles", __func__, chan); + return (-1); } - fcp = FCPARAM(isp, chan); - scp = fcp->isp_scratch; - isp_put_plogx(isp, plp, (isp_plogx_t *) scp); - MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 500000); - mbs.param[1] = QENTRY_LEN; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN, chan); - isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - rval = mbs.param[0]; - goto out; + /* Send request and wait for response. */ + reqp = isp_getrqentry(isp); + if (reqp == NULL) { + isp_prt(isp, ISP_LOGERR, + "%s: PLOGX of Chan %d out of rqent", __func__, chan); + isp_destroy_handle(isp, pl.plogx_handle); + return (-1); } - MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN, chan); - scp += QENTRY_LEN; - isp_get_plogx(isp, (isp_plogx_t *) scp, plp); - if (isp->isp_dblev & ISP_LOGDEBUG1) { - isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, plp); + if (isp->isp_dblev & ISP_LOGDEBUG1) + isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, &pl); + isp_put_plogx(isp, &pl, (isp_plogx_t *)reqp); + ISP_SYNC_REQUEST(isp); + if (msleep(resp, &isp->isp_lock, 0, "PLOGX", 3 * ICB_LOGIN_TOV * hz) + == EWOULDBLOCK) { + isp_prt(isp, ISP_LOGERR, + "%s: PLOGX of Chan %d timed out", __func__, chan); + isp_destroy_handle(isp, pl.plogx_handle); + return (-1); } + isp_get_plogx(isp, (isp_plogx_t *)resp, &pl); + if (isp->isp_dblev & ISP_LOGDEBUG1) + isp_print_bytes(isp, "IOCB LOGX response", QENTRY_LEN, &pl); - if (plp->plogx_status == PLOGX_STATUS_OK) { - rval = 0; - goto out; - } else if (plp->plogx_status != PLOGX_STATUS_IOCBERR) { + if (pl.plogx_status == PLOGX_STATUS_OK) { + return (0); + } else if (pl.plogx_status != PLOGX_STATUS_IOCBERR) { isp_prt(isp, ISP_LOGWARN, "status 0x%x on port login IOCB channel %d", - plp->plogx_status, chan); - rval = -1; - goto out; + pl.plogx_status, chan); + return (-1); } - sst = plp->plogx_ioparm[0].lo16 | (plp->plogx_ioparm[0].hi16 << 16); - parm1 = plp->plogx_ioparm[1].lo16 | (plp->plogx_ioparm[1].hi16 << 16); + sst = pl.plogx_ioparm[0].lo16 | (pl.plogx_ioparm[0].hi16 << 16); + parm1 = pl.plogx_ioparm[1].lo16 | (pl.plogx_ioparm[1].hi16 << 16); rval = -1; lev = ISP_LOGERR; @@ -2516,17 +2686,13 @@ isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags msg = "no FLOGI_ACC"; break; default: - ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", plp->plogx_status, flags); + ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", pl.plogx_status, flags); msg = buf; break; } if (msg) { isp_prt(isp, ISP_LOGERR, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s", chan, portid, handle, msg); } -out: - if (gs == 0) { - FC_SCRATCH_RELEASE(isp, chan); - } return (rval); } @@ -2596,7 +2762,7 @@ isp_port_logout(ispsoftc_t *isp, uint16_t handle, uint32_t portid) } static int -isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb, int dolock) +isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb) { fcparam *fcp = FCPARAM(isp, chan); mbreg_t mbs; @@ -2620,18 +2786,14 @@ isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb, int dolock) mbs.param[3] = DMA_WD0(fcp->isp_scdma); mbs.param[6] = DMA_WD3(fcp->isp_scdma); mbs.param[7] = DMA_WD2(fcp->isp_scdma); - if (dolock) { - if (FC_SCRATCH_ACQUIRE(isp, chan)) { - isp_prt(isp, ISP_LOGERR, sacq); - return (-1); - } + if (FC_SCRATCH_ACQUIRE(isp, chan)) { + isp_prt(isp, ISP_LOGERR, sacq); + return (-1); } MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (un), chan); isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - if (dolock) { - FC_SCRATCH_RELEASE(isp, chan); - } + FC_SCRATCH_RELEASE(isp, chan); return (mbs.param[0] | (mbs.param[1] << 16)); } if (IS_24XX(isp)) { @@ -2647,9 +2809,7 @@ isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb, int dolock) 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) { - FC_SCRATCH_RELEASE(isp, chan); - } + FC_SCRATCH_RELEASE(isp, chan); return (mbs.param[0]); } } else { @@ -2662,15 +2822,12 @@ isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb, int dolock) isp_prt(isp, ISP_LOGDEBUG1, "Chan %d handle 0x%x Port 0x%06x", chan, id, pdb->portid); } - if (dolock) { - FC_SCRATCH_RELEASE(isp, chan); - } + FC_SCRATCH_RELEASE(isp, chan); return (0); } static int -isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, - int dolock, int loop) +isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, int loop) { fcparam *fcp = FCPARAM(isp, chan); mbreg_t mbs; @@ -2696,18 +2853,14 @@ isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, mbs.param[3] = DMA_WD3(fcp->isp_scdma); mbs.param[6] = DMA_WD2(fcp->isp_scdma); } - if (dolock) { - if (FC_SCRATCH_ACQUIRE(isp, chan)) { - isp_prt(isp, ISP_LOGERR, sacq); - return (-1); - } + if (FC_SCRATCH_ACQUIRE(isp, chan)) { + isp_prt(isp, ISP_LOGERR, sacq); + return (-1); } MEMORYBARRIER(isp, SYNC_SFORDEV, 0, ISP_FC_SCRLEN, chan); isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - if (dolock) { - FC_SCRATCH_RELEASE(isp, chan); - } + FC_SCRATCH_RELEASE(isp, chan); return (mbs.param[0] | (mbs.param[1] << 16)); } elp1 = fcp->isp_scratch; @@ -2735,13 +2888,12 @@ isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, handles[j++] = h; } *num = j; - if (dolock) - FC_SCRATCH_RELEASE(isp, chan); + FC_SCRATCH_RELEASE(isp, chan); return (0); } static void -isp_dump_chip_portdb(ispsoftc_t *isp, int chan, int dolock) +isp_dump_chip_portdb(ispsoftc_t *isp, int chan) { isp_pdb_t pdb; uint16_t lim, nphdl; @@ -2753,7 +2905,7 @@ isp_dump_chip_portdb(ispsoftc_t *isp, int chan, int dolock) lim = NPH_MAX; } for (nphdl = 0; nphdl != lim; nphdl++) { - if (isp_getpdb(isp, chan, nphdl, &pdb, dolock)) { + if (isp_getpdb(isp, chan, nphdl, &pdb)) { continue; } isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Handle 0x%04x " @@ -2903,7 +3055,7 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay) if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) { nphdl = IS_24XX(isp) ? NPH_FL_ID : FL_ID; - r = isp_getpdb(isp, chan, nphdl, &pdb, 1); + r = isp_getpdb(isp, chan, nphdl, &pdb); if (r != 0 || pdb.portid == 0) { if (IS_2100(isp)) { fcp->isp_topo = TOPO_NL_PORT; @@ -3018,7 +3170,7 @@ isp_pdb_sync(ispsoftc_t *isp, int chan) lp->portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | - PLOGX_FLG_FREE_NPHDL, 0); + PLOGX_FLG_FREE_NPHDL); } /* * Note that we might come out of this with our state @@ -3145,7 +3297,7 @@ isp_fix_portids(ispsoftc_t *isp, int chan) if (VALID_PORT(lp->portid)) continue; - r = isp_getpdb(isp, chan, lp->handle, &pdb, 1); + r = isp_getpdb(isp, chan, lp->handle, &pdb); if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) return; if (r != 0) { @@ -3174,7 +3326,7 @@ isp_scan_loop(ispsoftc_t *isp, int chan) fcparam *fcp = FCPARAM(isp, chan); int idx, lim, r; isp_pdb_t pdb; - uint16_t handles[LOCAL_LOOP_LIM]; + uint16_t *handles; uint16_t handle; if (fcp->isp_loopstate < LOOP_LTEST_DONE) @@ -3196,8 +3348,9 @@ isp_scan_loop(ispsoftc_t *isp, int chan) return (0); } - lim = LOCAL_LOOP_LIM; - r = isp_gethandles(isp, chan, handles, &lim, 1, 1); + handles = (uint16_t *)fcp->isp_scanscratch; + lim = ISP_FC_SCRLEN / 2; + r = isp_gethandles(isp, chan, handles, &lim, 1); if (r != 0) { isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Getting list of handles failed with %x", chan, r); @@ -3247,7 +3400,7 @@ abort: /* * Get the port database entity for this index. */ - r = isp_getpdb(isp, chan, handle, &pdb, 1); + r = isp_getpdb(isp, chan, handle, &pdb); if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) goto abort; if (r != 0) { @@ -3276,20 +3429,10 @@ abort: * * For the 24XX card, we have to use CT-Pass through run via the Execute IOCB * mailbox command. - * - * The net result is to leave the list of Port IDs setting untranslated in - * offset IGPOFF of the FC scratch area, whereupon we'll canonicalize it to - * host order at OGPOFF. */ - -/* - * Take half of our scratch area to store Port IDs - */ -#define GIDLEN (ISP_FC_SCRLEN >> 1) +#define GIDLEN (ISP_FC_SCRLEN - (3 * QENTRY_LEN)) #define NGENT ((GIDLEN - 16) >> 2) -#define IGPOFF (0) -#define OGPOFF (ISP_FC_SCRLEN >> 1) #define XTXOFF (ISP_FC_SCRLEN - (3 * QENTRY_LEN)) /* CT request */ #define CTXOFF (ISP_FC_SCRLEN - (2 * QENTRY_LEN)) /* Request IOCB */ #define ZTXOFF (ISP_FC_SCRLEN - (1 * QENTRY_LEN)) /* Response IOCB */ @@ -3306,21 +3449,25 @@ isp_gid_ft_sns(ispsoftc_t *isp, int chan) uint8_t *scp = fcp->isp_scratch; mbreg_t mbs; - isp_prt(isp, ISP_LOGDEBUG0, "Chan %d scanning fabric (GID_FT) via SNS", chan); + isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_FT via SNS", chan); + if (FC_SCRATCH_ACQUIRE(isp, chan)) { + isp_prt(isp, ISP_LOGERR, sacq); + return (-1); + } ISP_MEMZERO(rq, SNS_GID_FT_REQ_SIZE); rq->snscb_rblen = GIDLEN >> 1; - rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + IGPOFF); - rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + IGPOFF); - rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + IGPOFF); - rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + IGPOFF); + rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma); + rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma); + rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma); + rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma); rq->snscb_sblen = 6; rq->snscb_cmd = SNS_GID_FT; rq->snscb_mword_div_2 = NGENT; rq->snscb_fc4_type = FC4_SCSI; isp_put_gid_ft_request(isp, rq, (sns_gid_ft_req_t *)&scp[CTXOFF]); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE, chan); + MEMORYBARRIER(isp, SYNC_SFORDEV, CTXOFF, SNS_GID_FT_REQ_SIZE, chan); MBSINIT(&mbs, MBOX_SEND_SNS, MBLOGALL, 10000000); mbs.param[0] = MBOX_SEND_SNS; @@ -3337,6 +3484,12 @@ isp_gid_ft_sns(ispsoftc_t *isp, int chan) return (-1); } } + MEMORYBARRIER(isp, SYNC_SFORCPU, 0, GIDLEN, chan); + if (isp->isp_dblev & ISP_LOGDEBUG1) + isp_print_bytes(isp, "CT response", GIDLEN, scp); + isp_get_gid_ft_response(isp, (sns_gid_ft_rsp_t *)scp, + (sns_gid_ft_rsp_t *)fcp->isp_scanscratch, NGENT); + FC_SCRATCH_RELEASE(isp, chan); return (0); } @@ -3355,7 +3508,11 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp, int chan) uint32_t *rp; uint8_t *scp = fcp->isp_scratch; - isp_prt(isp, ISP_LOGDEBUG0, "Chan %d scanning fabric (GID_FT) via CT", chan); + isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_FT via CT", chan); + if (FC_SCRATCH_ACQUIRE(isp, chan)) { + isp_prt(isp, ISP_LOGERR, sacq); + return (-1); + } /* * Build a Passthrough IOCB in memory. @@ -3368,15 +3525,15 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp, int chan) pt->ctp_nphdl = fcp->isp_sns_hdl; pt->ctp_cmd_cnt = 1; pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan); - pt->ctp_time = 30; + pt->ctp_time = 10; pt->ctp_rsp_cnt = 1; pt->ctp_rsp_bcnt = GIDLEN; pt->ctp_cmd_bcnt = sizeof (*ct) + sizeof (uint32_t); pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF); pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF); pt->ctp_dataseg[0].ds_count = sizeof (*ct) + sizeof (uint32_t); - pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF); - pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma); + pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma); pt->ctp_dataseg[1].ds_count = GIDLEN; if (isp->isp_dblev & ISP_LOGDEBUG1) { isp_print_bytes(isp, "ct IOCB", QENTRY_LEN, pt); @@ -3404,7 +3561,8 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp, int chan) sizeof (*ct) + sizeof (uint32_t), &scp[XTXOFF]); } ISP_MEMZERO(&scp[ZTXOFF], QENTRY_LEN); - MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 500000); + MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, + MBCMD_DEFAULT_TIMEOUT + pt->ctp_time * 1000000); mbs.param[1] = QENTRY_LEN; mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF); mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF); @@ -3415,7 +3573,7 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp, int chan) if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return (-1); } - MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN, chan); + MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan); pt = &un.plocal; isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt); if (isp->isp_dblev & ISP_LOGDEBUG1) { @@ -3424,14 +3582,15 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp, int chan) if (pt->ctp_status && pt->ctp_status != RQCS_DATA_UNDERRUN) { isp_prt(isp, ISP_LOGWARN, - "Chan %d ISP GID FT CT Passthrough returned 0x%x", + "Chan %d GID_FT CT Passthrough returned 0x%x", chan, pt->ctp_status); return (-1); } - MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN, chan); - if (isp->isp_dblev & ISP_LOGDEBUG1) { - isp_print_bytes(isp, "CT response", GIDLEN, &scp[IGPOFF]); - } + if (isp->isp_dblev & ISP_LOGDEBUG1) + isp_print_bytes(isp, "CT response", GIDLEN, scp); + isp_get_gid_ft_response(isp, (sns_gid_ft_rsp_t *)scp, + (sns_gid_ft_rsp_t *)fcp->isp_scanscratch, NGENT); + FC_SCRATCH_RELEASE(isp, chan); return (0); } @@ -3444,7 +3603,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan) uint16_t nphdl; isp_pdb_t pdb; int portidx, portlim, r; - sns_gid_ft_rsp_t *rs0, *rs1; + sns_gid_ft_rsp_t *rs; if (fcp->isp_loopstate < LOOP_LSCAN_DONE) return (-1); @@ -3460,13 +3619,6 @@ isp_scan_fabric(ispsoftc_t *isp, int chan) return (0); } - if (FC_SCRATCH_ACQUIRE(isp, chan)) { - isp_prt(isp, ISP_LOGERR, sacq); -fail: - isp_prt(isp, ISP_LOG_SANCFG, - "Chan %d FC fabric scan done (bad)", chan); - return (-1); - } if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { abort: FC_SCRATCH_RELEASE(isp, chan); @@ -3479,14 +3631,16 @@ abort: * Make sure we still are logged into the fabric controller. */ nphdl = IS_24XX(isp) ? NPH_FL_ID : FL_ID; - r = isp_getpdb(isp, chan, nphdl, &pdb, 0); + r = isp_getpdb(isp, chan, nphdl, &pdb); if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) { - isp_dump_chip_portdb(isp, chan, 0); + isp_dump_chip_portdb(isp, chan); } if (r) { fcp->isp_loopstate = LOOP_LTEST_DONE; - FC_SCRATCH_RELEASE(isp, chan); - goto fail; +fail: + isp_prt(isp, ISP_LOG_SANCFG, + "Chan %d FC fabric scan done (bad)", chan); + return (-1); } /* Get list of port IDs from SNS. */ @@ -3498,42 +3652,36 @@ abort: goto abort; if (r > 0) { fcp->isp_loopstate = LOOP_FSCAN_DONE; - FC_SCRATCH_RELEASE(isp, chan); return (-1); } else if (r < 0) { fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */ - FC_SCRATCH_RELEASE(isp, chan); return (-1); } - MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN, chan); - rs0 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+IGPOFF); - rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF); - isp_get_gid_ft_response(isp, rs0, rs1, NGENT); + rs = (sns_gid_ft_rsp_t *) fcp->isp_scanscratch; if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) goto abort; - if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) { + if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) { int level; - if (rs1->snscb_cthdr.ct_reason == 9 && rs1->snscb_cthdr.ct_explanation == 7) { + if (rs->snscb_cthdr.ct_reason == 9 && rs->snscb_cthdr.ct_explanation == 7) { level = ISP_LOG_SANCFG; } else { level = ISP_LOGWARN; } isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_FT" " (Reason=0x%x Expl=0x%x)", chan, - rs1->snscb_cthdr.ct_reason, - rs1->snscb_cthdr.ct_explanation); - FC_SCRATCH_RELEASE(isp, chan); + rs->snscb_cthdr.ct_reason, + rs->snscb_cthdr.ct_explanation); fcp->isp_loopstate = LOOP_FSCAN_DONE; return (-1); } /* Check our buffer was big enough to get the full list. */ for (portidx = 0; portidx < NGENT-1; portidx++) { - if (rs1->snscb_ports[portidx].control & 0x80) + if (rs->snscb_ports[portidx].control & 0x80) break; } - if ((rs1->snscb_ports[portidx].control & 0x80) == 0) { + if ((rs->snscb_ports[portidx].control & 0x80) == 0) { isp_prt(isp, ISP_LOGWARN, "fabric too big for scratch area: increase ISP_FC_SCRLEN"); } @@ -3546,24 +3694,24 @@ abort: int npidx; portid = - ((rs1->snscb_ports[portidx].portid[0]) << 16) | - ((rs1->snscb_ports[portidx].portid[1]) << 8) | - ((rs1->snscb_ports[portidx].portid[2])); + ((rs->snscb_ports[portidx].portid[0]) << 16) | + ((rs->snscb_ports[portidx].portid[1]) << 8) | + ((rs->snscb_ports[portidx].portid[2])); for (npidx = portidx + 1; npidx < portlim; npidx++) { uint32_t new_portid = - ((rs1->snscb_ports[npidx].portid[0]) << 16) | - ((rs1->snscb_ports[npidx].portid[1]) << 8) | - ((rs1->snscb_ports[npidx].portid[2])); + ((rs->snscb_ports[npidx].portid[0]) << 16) | + ((rs->snscb_ports[npidx].portid[1]) << 8) | + ((rs->snscb_ports[npidx].portid[2])); if (new_portid == portid) { break; } } if (npidx < portlim) { - rs1->snscb_ports[npidx].portid[0] = 0; - rs1->snscb_ports[npidx].portid[1] = 0; - rs1->snscb_ports[npidx].portid[2] = 0; + rs->snscb_ports[npidx].portid[0] = 0; + rs->snscb_ports[npidx].portid[1] = 0; + rs->snscb_ports[npidx].portid[2] = 0; isp_prt(isp, ISP_LOG_SANCFG, "Chan %d removing duplicate PortID 0x%06x entry from list", chan, portid); } } @@ -3584,9 +3732,9 @@ abort: */ isp_mark_portdb(isp, chan); for (portidx = 0; portidx < portlim; portidx++) { - portid = ((rs1->snscb_ports[portidx].portid[0]) << 16) | - ((rs1->snscb_ports[portidx].portid[1]) << 8) | - ((rs1->snscb_ports[portidx].portid[2])); + portid = ((rs->snscb_ports[portidx].portid[0]) << 16) | + ((rs->snscb_ports[portidx].portid[1]) << 8) | + ((rs->snscb_ports[portidx].portid[2])); isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Checking fabric port 0x%06x", chan, portid); if (portid == 0) { @@ -3608,7 +3756,6 @@ abort: "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)", chan, lp->portid, lp->handle, FC_PORTDB_TGT(isp, chan, lp), lp->state); - FC_SCRATCH_RELEASE(isp, chan); isp_dump_portdb(isp, chan); goto fail; } @@ -3628,7 +3775,7 @@ abort: * database entry for somebody further along to * decide what to do (policy choice). */ - r = isp_getpdb(isp, chan, lp->handle, &pdb, 0); + r = isp_getpdb(isp, chan, lp->handle, &pdb); if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) goto abort; if (r != 0) { @@ -3662,7 +3809,6 @@ relogin: if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) goto abort; - FC_SCRATCH_RELEASE(isp, chan); fcp->isp_loopstate = LOOP_FSCAN_DONE; isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan); return (0); @@ -3689,7 +3835,7 @@ isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint1 return (-1); /* Check if this handle is free. */ - r = isp_getpdb(isp, chan, handle, p, 0); + r = isp_getpdb(isp, chan, handle, p); if (r == 0) { if (p->portid != portid) { /* This handle is busy, try next one. */ @@ -3704,7 +3850,7 @@ isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint1 /* * Now try and log into the device */ - r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1); + r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI); if (r == 0) { break; } else if ((r & 0xffff) == MBOX_PORT_ID_USED) { @@ -3713,12 +3859,12 @@ isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint1 * handle. We need to break that association. We used to try and just substitute the handle, but then * failed to get any data via isp_getpdb (below). */ - if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1)) { + if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL)) { isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16); } if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) return (-1); - r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1); + r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI); if (r != 0) i = lim; break; @@ -3742,7 +3888,7 @@ isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint1 * so we can crosscheck that it is still what we think it * is and that we also have the role it plays */ - r = isp_getpdb(isp, chan, handle, p, 0); + r = isp_getpdb(isp, chan, handle, p); if (r != 0) { isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle); return (-1); @@ -3839,15 +3985,15 @@ isp_register_fc4_type_24xx(ispsoftc_t *isp, int chan) pt->ctp_nphdl = fcp->isp_sns_hdl; pt->ctp_cmd_cnt = 1; pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan); - pt->ctp_time = 1; + pt->ctp_time = 4; pt->ctp_rsp_cnt = 1; pt->ctp_rsp_bcnt = sizeof (ct_hdr_t); pt->ctp_cmd_bcnt = sizeof (rft_id_t); pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF); pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF); pt->ctp_dataseg[0].ds_count = sizeof (rft_id_t); - pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF); - pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma); + pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma); pt->ctp_dataseg[1].ds_count = sizeof (ct_hdr_t); isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]); if (isp->isp_dblev & ISP_LOGDEBUG1) { @@ -3878,7 +4024,8 @@ isp_register_fc4_type_24xx(ispsoftc_t *isp, int chan) ISP_MEMZERO(&scp[ZTXOFF], sizeof (ct_hdr_t)); - MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 1000000); + MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, + MBCMD_DEFAULT_TIMEOUT + pt->ctp_time * 1000000); mbs.param[1] = QENTRY_LEN; mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF); mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF); @@ -3904,7 +4051,7 @@ isp_register_fc4_type_24xx(ispsoftc_t *isp, int chan) return (1); } - isp_get_ct_hdr(isp, (ct_hdr_t *) &scp[IGPOFF], ct); + isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct); FC_SCRATCH_RELEASE(isp, chan); if (ct->ct_cmd_resp == LS_RJT) { @@ -3950,15 +4097,15 @@ isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan) pt->ctp_nphdl = fcp->isp_sns_hdl; pt->ctp_cmd_cnt = 1; pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan); - pt->ctp_time = 1; + pt->ctp_time = 4; pt->ctp_rsp_cnt = 1; pt->ctp_rsp_bcnt = sizeof (ct_hdr_t); pt->ctp_cmd_bcnt = sizeof (rff_id_t); pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF); pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF); pt->ctp_dataseg[0].ds_count = sizeof (rff_id_t); - pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF); - pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF); + pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma); + pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma); pt->ctp_dataseg[1].ds_count = sizeof (ct_hdr_t); isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]); if (isp->isp_dblev & ISP_LOGDEBUG1) { @@ -3994,7 +4141,8 @@ isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan) ISP_MEMZERO(&scp[ZTXOFF], sizeof (ct_hdr_t)); - MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 1000000); + MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, + MBCMD_DEFAULT_TIMEOUT + pt->ctp_time * 1000000); mbs.param[1] = QENTRY_LEN; mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF); mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF); @@ -4020,7 +4168,7 @@ isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan) return (1); } - isp_get_ct_hdr(isp, (ct_hdr_t *) &scp[IGPOFF], ct); + isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct); FC_SCRATCH_RELEASE(isp, chan); if (ct->ct_cmd_resp == LS_RJT) { @@ -4090,7 +4238,7 @@ int isp_start(XS_T *xs) { ispsoftc_t *isp; - uint32_t handle, cdblen; + uint32_t cdblen; uint8_t local[QENTRY_LEN]; ispreq_t *reqp; void *cdbp, *qep; @@ -4381,21 +4529,18 @@ isp_start(XS_T *xs) } ISP_MEMCPY(cdbp, XS_CDBP(xs), cdblen); - *tptr = XS_TIME(xs) / 1000; - if (*tptr == 0 && XS_TIME(xs)) { - *tptr = 1; - } + *tptr = (XS_TIME(xs) + 999) / 1000; if (IS_24XX(isp) && *tptr > 0x1999) { *tptr = 0x1999; } - if (isp_allocate_xs(isp, xs, &handle)) { + /* Whew. Thankfully the same for type 7 requests */ + reqp->req_handle = isp_allocate_handle(isp, xs, ISP_HANDLE_INITIATOR); + if (reqp->req_handle == 0) { isp_prt(isp, ISP_LOG_WARN1, "out of xflist pointers"); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } - /* Whew. Thankfully the same for type 7 requests */ - reqp->req_handle = handle; /* * Set up DMA and/or do any platform dependent swizzling of the request entry @@ -4405,7 +4550,7 @@ isp_start(XS_T *xs) */ dmaresult = ISP_DMASETUP(isp, xs, reqp); if (dmaresult != CMD_QUEUED) { - isp_destroy_handle(isp, handle); + isp_destroy_handle(isp, reqp->req_handle); /* * dmasetup sets actual error in packet, and * return what we were given to return. @@ -4490,13 +4635,14 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, ...) tmf->tmf_header.rqs_entry_count = 1; tmf->tmf_nphdl = lp->handle; tmf->tmf_delay = 2; - tmf->tmf_timeout = 2; + tmf->tmf_timeout = 4; tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET; tmf->tmf_tidlo = lp->portid; tmf->tmf_tidhi = lp->portid >> 16; tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan); isp_prt(isp, ISP_LOGALL, "Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid); - MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000); + MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, + MBCMD_DEFAULT_TIMEOUT + tmf->tmf_timeout * 1000000); mbs.param[1] = QENTRY_LEN; mbs.param[2] = DMA_WD1(fcp->isp_scdma); mbs.param[3] = DMA_WD0(fcp->isp_scdma); @@ -4710,7 +4856,7 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, ...) tgt = va_arg(ap, int); pdb = va_arg(ap, isp_pdb_t *); va_end(ap); - return (isp_getpdb(isp, chan, tgt, pdb, 1)); + return (isp_getpdb(isp, chan, tgt, pdb)); } break; @@ -4758,11 +4904,11 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, ...) va_end(ap); if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) { - return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags, 0)); + return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags)); } do { isp_next_handle(isp, &p->handle); - r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags, 0); + r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags); if ((r & 0xffff) == MBOX_PORT_ID_USED) { p->handle = r >> 16; r = 0; @@ -5133,12 +5279,6 @@ again: } } - if (!ISP_VALID_HANDLE(isp, sp->req_handle)) { - isp_prt(isp, ISP_LOGERR, "bad request handle 0x%x (iocb type 0x%x)", sp->req_handle, etype); - ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */ - last_etype = etype; - continue; - } xs = isp_find_xs(isp, sp->req_handle); if (xs == NULL) { uint8_t ts = completion_status & 0xff; @@ -5952,6 +6092,8 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt { isp_ridacq_t rid; int chan, c; + uint32_t hdl; + void *ptr; switch (type) { case RQSTYPE_STATUS_CONT: @@ -5993,6 +6135,17 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt } } return (1); + case RQSTYPE_VP_MODIFY: + case RQSTYPE_VP_CTRL: + case RQSTYPE_LOGIN: + ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl); + ptr = isp_find_xs(isp, hdl); + if (ptr != NULL) { + isp_destroy_handle(isp, hdl); + memcpy(ptr, hp, QENTRY_LEN); + wakeup(ptr); + } + return (1); case RQSTYPE_ATIO: case RQSTYPE_CTIO: case RQSTYPE_ENABLE_LUN: @@ -6879,7 +7032,7 @@ static const uint32_t mbpfc[] = { ISP_FC_OPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf), /* 0x20: MBOX_GET_LOOP_ID */ ISP_FC_OPMAP(0x00, 0x00), /* 0x21: */ - ISP_FC_OPMAP(0x01, 0x07), /* 0x22: MBOX_GET_RETRY_COUNT */ + ISP_FC_OPMAP(0x03, 0x4b), /* 0x22: MBOX_GET_TIMEOUT_PARAMS */ ISP_FC_OPMAP(0x00, 0x00), /* 0x23: */ ISP_FC_OPMAP(0x00, 0x00), /* 0x24: */ ISP_FC_OPMAP(0x00, 0x00), /* 0x25: */ @@ -6895,7 +7048,7 @@ static const uint32_t mbpfc[] = { ISP_FC_OPMAP(0x00, 0x00), /* 0x2f: */ ISP_FC_OPMAP(0x00, 0x00), /* 0x30: */ ISP_FC_OPMAP(0x00, 0x00), /* 0x31: */ - ISP_FC_OPMAP(0x07, 0x07), /* 0x32: MBOX_SET_RETRY_COUNT */ + ISP_FC_OPMAP(0x4b, 0x4b), /* 0x32: MBOX_SET_TIMEOUT_PARAMS */ ISP_FC_OPMAP(0x00, 0x00), /* 0x33: */ ISP_FC_OPMAP(0x00, 0x00), /* 0x34: */ ISP_FC_OPMAP(0x00, 0x00), /* 0x35: */ @@ -7632,6 +7785,7 @@ isp_setdfltfcparm(ispsoftc_t *isp, int chan) fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX; } fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS; + fcp->isp_zfwoptions |= ICB2400_OPT3_RATE_AUTO; } else { fcp->isp_fwoptions |= ICBOPT_FAIRNESS; fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; @@ -7644,6 +7798,7 @@ isp_setdfltfcparm(ispsoftc_t *isp, int chan) * extended options from NVRAM */ fcp->isp_fwoptions &= ~ICBOPT_EXTENDED; + fcp->isp_zfwoptions |= ICBZOPT_RATE_AUTO; } diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 35ca7fe..e38ae45 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -632,7 +632,7 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td) tmf->tmf_header.rqs_entry_count = 1; tmf->tmf_nphdl = lp->handle; tmf->tmf_delay = 2; - tmf->tmf_timeout = 2; + tmf->tmf_timeout = 4; tmf->tmf_tidlo = lp->portid; tmf->tmf_tidhi = lp->portid >> 16; tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan); @@ -668,7 +668,8 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td) ISP_UNLOCK(isp); break; } - MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000); + MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, + MBCMD_DEFAULT_TIMEOUT + tmf->tmf_timeout * 1000000); mbs.param[1] = QENTRY_LEN; mbs.param[2] = DMA_WD1(fcp->isp_scdma); mbs.param[3] = DMA_WD0(fcp->isp_scdma); @@ -1403,7 +1404,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) cto->ct_iid_hi = atp->portid >> 16; cto->ct_oxid = atp->oxid; cto->ct_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(ccb)); - cto->ct_timeout = 120; + cto->ct_timeout = (XS_TIME(ccb) + 999) / 1000; cto->ct_flags = atp->tattr << CT7_TASK_ATTR_SHIFT; /* @@ -1555,7 +1556,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) cto->ct_lun = ccb->ccb_h.target_lun; } } - cto->ct_timeout = 10; + cto->ct_timeout = (XS_TIME(ccb) + 999) / 1000; cto->ct_rxid = cso->tag_id; /* @@ -1693,7 +1694,8 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe); break; } - if (isp_allocate_xs_tgt(isp, ccb, &handle)) { + handle = isp_allocate_handle(isp, ccb, ISP_HANDLE_TARGET); + if (handle == 0) { ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "No XFLIST pointers for %s\n", __func__); TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe); isp_free_pcmd(isp, ccb); @@ -1722,7 +1724,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) dmaresult = ISP_DMASETUP(isp, cso, (ispreq_t *) local); if (dmaresult != CMD_QUEUED) { - isp_destroy_tgt_handle(isp, handle); + isp_destroy_handle(isp, handle); isp_free_pcmd(isp, ccb); if (dmaresult == CMD_EAGAIN) { TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe); @@ -2379,12 +2381,12 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg) uint32_t handle, moved_data = 0, data_requested; handle = ((ct2_entry_t *)arg)->ct_syshandle; - ccb = isp_find_xs_tgt(isp, handle); + ccb = isp_find_xs(isp, handle); if (ccb == NULL) { isp_print_bytes(isp, "null ccb in isp_handle_platform_ctio", QENTRY_LEN, arg); return; } - isp_destroy_tgt_handle(isp, handle); + isp_destroy_handle(isp, handle); data_requested = PISP_PCMD(ccb)->datalen; isp_free_pcmd(isp, ccb); if (isp->isp_nactive) { @@ -3320,7 +3322,7 @@ isp_loop_dead(ispsoftc_t *isp, int chan) for (i = 0; i < isp->isp_maxcmds; i++) { struct ccb_scsiio *xs; - if (!ISP_VALID_HANDLE(isp, isp->isp_xflist[i].handle)) { + if (ISP_H2HT(isp->isp_xflist[i].handle) != ISP_HANDLE_INITIATOR) { continue; } if ((xs = isp->isp_xflist[i].cmd) == NULL) { diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h index 9a9093a..7702ee6 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -225,8 +225,7 @@ struct isp_fc { struct cam_path *path; struct ispsoftc *isp; struct proc *kproc; - bus_dma_tag_t tdmat; - bus_dmamap_t tdmap; + bus_dmamap_t scmap; uint64_t def_wwpn; uint64_t def_wwnn; time_t loop_down_time; @@ -285,13 +284,18 @@ struct isposinfo { const struct firmware * fw; /* - * DMA related sdtuff + * DMA related stuff */ struct resource * regs; struct resource * regs2; bus_dma_tag_t dmat; - bus_dma_tag_t cdmat; - bus_dmamap_t cdmap; + bus_dma_tag_t reqdmat; + bus_dma_tag_t respdmat; + bus_dma_tag_t atiodmat; + bus_dma_tag_t scdmat; + bus_dmamap_t reqmap; + bus_dmamap_t respmap; + bus_dmamap_t atiomap; /* * Command and transaction related related stuff @@ -406,62 +410,60 @@ struct isposinfo { #define MEMORYBARRIER(isp, type, offset, size, chan) \ switch (type) { \ +case SYNC_REQUEST: \ + bus_dmamap_sync(isp->isp_osinfo.reqdmat, \ + isp->isp_osinfo.reqmap, BUS_DMASYNC_PREWRITE); \ + break; \ +case SYNC_RESULT: \ + bus_dmamap_sync(isp->isp_osinfo.respdmat, \ + isp->isp_osinfo.respmap, BUS_DMASYNC_POSTREAD); \ + break; \ case SYNC_SFORDEV: \ { \ struct isp_fc *fc = ISP_FC_PC(isp, chan); \ - bus_dmamap_sync(fc->tdmat, fc->tdmap, \ + bus_dmamap_sync(isp->isp_osinfo.scdmat, fc->scmap, \ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); \ break; \ } \ -case SYNC_REQUEST: \ - bus_dmamap_sync(isp->isp_osinfo.cdmat, \ - isp->isp_osinfo.cdmap, \ - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); \ - break; \ case SYNC_SFORCPU: \ { \ struct isp_fc *fc = ISP_FC_PC(isp, chan); \ - bus_dmamap_sync(fc->tdmat, fc->tdmap, \ + bus_dmamap_sync(isp->isp_osinfo.scdmat, fc->scmap, \ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); \ break; \ } \ -case SYNC_RESULT: \ - bus_dmamap_sync(isp->isp_osinfo.cdmat, \ - isp->isp_osinfo.cdmap, \ - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); \ - break; \ case SYNC_REG: \ bus_barrier(isp->isp_osinfo.regs, offset, size, \ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); \ break; \ +case SYNC_ATIOQ: \ + bus_dmamap_sync(isp->isp_osinfo.atiodmat, \ + isp->isp_osinfo.atiomap, BUS_DMASYNC_POSTREAD); \ + break; \ default: \ break; \ } #define MEMORYBARRIERW(isp, type, offset, size, chan) \ switch (type) { \ +case SYNC_REQUEST: \ + bus_dmamap_sync(isp->isp_osinfo.reqdmat, \ + isp->isp_osinfo.reqmap, BUS_DMASYNC_PREWRITE); \ + break; \ case SYNC_SFORDEV: \ { \ struct isp_fc *fc = ISP_FC_PC(isp, chan); \ - bus_dmamap_sync(fc->tdmat, fc->tdmap, \ + bus_dmamap_sync(isp->isp_osinfo.scdmat, fc->scmap, \ BUS_DMASYNC_PREWRITE); \ break; \ } \ -case SYNC_REQUEST: \ - bus_dmamap_sync(isp->isp_osinfo.cdmat, \ - isp->isp_osinfo.cdmap, BUS_DMASYNC_PREWRITE); \ - break; \ case SYNC_SFORCPU: \ { \ struct isp_fc *fc = ISP_FC_PC(isp, chan); \ - bus_dmamap_sync(fc->tdmat, fc->tdmap, \ + bus_dmamap_sync(isp->isp_osinfo.scdmat, fc->scmap, \ BUS_DMASYNC_POSTWRITE); \ break; \ } \ -case SYNC_RESULT: \ - bus_dmamap_sync(isp->isp_osinfo.cdmat, \ - isp->isp_osinfo.cdmap, BUS_DMASYNC_POSTWRITE); \ - break; \ case SYNC_REG: \ bus_barrier(isp->isp_osinfo.regs, offset, size, \ BUS_SPACE_BARRIER_WRITE); \ diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index ec99244..78c7f6f 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -247,28 +247,26 @@ copy_and_sync: return (CMD_QUEUED); } -int -isp_allocate_xs(ispsoftc_t *isp, XS_T *xs, uint32_t *handlep) +uint32_t +isp_allocate_handle(ispsoftc_t *isp, void *xs, int type) { isp_hdl_t *hdp; hdp = isp->isp_xffree; - if (hdp == NULL) { - return (-1); - } + if (hdp == NULL) + return (ISP_HANDLE_FREE); isp->isp_xffree = hdp->cmd; hdp->cmd = xs; hdp->handle = (hdp - isp->isp_xflist); - hdp->handle |= (ISP_HANDLE_INITIATOR << ISP_HANDLE_USAGE_SHIFT); + hdp->handle |= (type << ISP_HANDLE_USAGE_SHIFT); hdp->handle |= (isp->isp_seqno++ << ISP_HANDLE_SEQ_SHIFT); - *handlep = hdp->handle; - return (0); + return (hdp->handle); } -XS_T * +void * isp_find_xs(ispsoftc_t *isp, uint32_t handle) { - if (!ISP_VALID_INI_HANDLE(isp, handle)) { + if (!ISP_VALID_HANDLE(isp, handle)) { isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle); return (NULL); } @@ -276,7 +274,7 @@ isp_find_xs(ispsoftc_t *isp, uint32_t handle) } uint32_t -isp_find_handle(ispsoftc_t *isp, XS_T *xs) +isp_find_handle(ispsoftc_t *isp, void *xs) { uint32_t i, foundhdl = ISP_HANDLE_FREE; @@ -292,21 +290,10 @@ isp_find_handle(ispsoftc_t *isp, XS_T *xs) return (foundhdl); } -uint32_t -isp_handle_index(ispsoftc_t *isp, uint32_t handle) -{ - if (!ISP_VALID_HANDLE(isp, handle)) { - isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle); - return (ISP_BAD_HANDLE_INDEX); - } else { - return (handle & ISP_HANDLE_CMD_MASK); - } -} - void isp_destroy_handle(ispsoftc_t *isp, uint32_t handle) { - if (!ISP_VALID_INI_HANDLE(isp, handle)) { + if (!ISP_VALID_HANDLE(isp, handle)) { isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle); } else { isp->isp_xflist[(handle & ISP_HANDLE_CMD_MASK)].handle = ISP_HANDLE_FREE; @@ -573,168 +560,6 @@ isp_fc_toponame(fcparam *fcp) } } -static int -isp_fc_enable_vp(ispsoftc_t *isp, int chan) -{ - fcparam *fcp = FCPARAM(isp, chan); - mbreg_t mbs; - vp_modify_t *vp; - uint8_t qe[QENTRY_LEN], *scp; - - ISP_MEMZERO(qe, QENTRY_LEN); - if (FC_SCRATCH_ACQUIRE(isp, chan)) { - return (EBUSY); - } - scp = fcp->isp_scratch; - - /* - * Build a VP MODIFY command in memory - */ - vp = (vp_modify_t *) qe; - vp->vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY; - vp->vp_mod_hdr.rqs_entry_count = 1; - vp->vp_mod_cnt = 1; - vp->vp_mod_idx0 = chan; - vp->vp_mod_cmd = VP_MODIFY_ENA; - vp->vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED | - ICB2400_VPOPT_ENA_SNSLOGIN; - if (fcp->role & ISP_ROLE_INITIATOR) { - vp->vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE; - } - if ((fcp->role & ISP_ROLE_TARGET) == 0) { - vp->vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE; - } - if (fcp->isp_loopid < LOCAL_LOOP_LIM) { - vp->vp_mod_ports[0].loopid = fcp->isp_loopid; - if (isp->isp_confopts & ISP_CFG_OWNLOOPID) - vp->vp_mod_ports[0].options |= - ICB2400_VPOPT_HARD_ADDRESS; - else - vp->vp_mod_ports[0].options |= - ICB2400_VPOPT_PREV_ADDRESS; - } - MAKE_NODE_NAME_FROM_WWN(vp->vp_mod_ports[0].wwpn, fcp->isp_wwpn); - MAKE_NODE_NAME_FROM_WWN(vp->vp_mod_ports[0].wwnn, fcp->isp_wwnn); - isp_put_vp_modify(isp, vp, (vp_modify_t *) scp); - - /* - * Build a EXEC IOCB A64 command that points to the VP MODIFY command - */ - MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 0); - mbs.param[1] = QENTRY_LEN; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, 2 * QENTRY_LEN, chan); - isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - FC_SCRATCH_RELEASE(isp, chan); - return (EIO); - } - MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN, chan); - isp_get_vp_modify(isp, (vp_modify_t *)&scp[QENTRY_LEN], vp); - - FC_SCRATCH_RELEASE(isp, chan); - - if (vp->vp_mod_status != VP_STS_OK) { - isp_prt(isp, ISP_LOGERR, "%s: VP_MODIFY of Chan %d failed with status %d", __func__, chan, vp->vp_mod_status); - return (EIO); - } - return (0); -} - -static int -isp_fc_disable_vp(ispsoftc_t *isp, int chan) -{ - fcparam *fcp = FCPARAM(isp, chan); - mbreg_t mbs; - vp_ctrl_info_t *vp; - uint8_t qe[QENTRY_LEN], *scp; - - ISP_MEMZERO(qe, QENTRY_LEN); - if (FC_SCRATCH_ACQUIRE(isp, chan)) { - return (EBUSY); - } - scp = fcp->isp_scratch; - - /* - * Build a VP CTRL command in memory - */ - vp = (vp_ctrl_info_t *) qe; - vp->vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL; - vp->vp_ctrl_hdr.rqs_entry_count = 1; - if (ISP_CAP_VP0(isp)) { - vp->vp_ctrl_status = 1; - } else { - vp->vp_ctrl_status = 0; - chan--; /* VP0 can not be controlled in this case. */ - } - vp->vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL; - vp->vp_ctrl_vp_count = 1; - vp->vp_ctrl_idmap[chan / 16] |= (1 << chan % 16); - isp_put_vp_ctrl_info(isp, vp, (vp_ctrl_info_t *) scp); - - /* - * Build a EXEC IOCB A64 command that points to the VP CTRL command - */ - MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 0); - mbs.param[1] = QENTRY_LEN; - mbs.param[2] = DMA_WD1(fcp->isp_scdma); - mbs.param[3] = DMA_WD0(fcp->isp_scdma); - mbs.param[6] = DMA_WD3(fcp->isp_scdma); - mbs.param[7] = DMA_WD2(fcp->isp_scdma); - MEMORYBARRIER(isp, SYNC_SFORDEV, 0, 2 * QENTRY_LEN, chan); - isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - FC_SCRATCH_RELEASE(isp, chan); - return (EIO); - } - MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN, chan); - isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)&scp[QENTRY_LEN], vp); - - FC_SCRATCH_RELEASE(isp, chan); - - if (vp->vp_ctrl_status != 0) { - isp_prt(isp, ISP_LOGERR, - "%s: VP_CTRL of Chan %d failed with status %d %d", - __func__, chan, vp->vp_ctrl_status, vp->vp_ctrl_index_fail); - return (EIO); - } - return (0); -} - -/* - * Change Roles - */ -int -isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role) -{ - fcparam *fcp = FCPARAM(isp, chan); - int i, was, res = 0; - - if (chan >= isp->isp_nchan) { - isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan); - return (ENXIO); - } - if (fcp->role == new_role) - return (0); - for (was = 0, i = 0; i < isp->isp_nchan; i++) { - if (FCPARAM(isp, i)->role != ISP_ROLE_NONE) - was++; - } - if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) { - fcp->role = new_role; - return (isp_reinit(isp, 0)); - } - if (fcp->role != ISP_ROLE_NONE) - res = isp_fc_disable_vp(isp, chan); - fcp->role = new_role; - if (fcp->role != ISP_ROLE_NONE) - res = isp_fc_enable_vp(isp, chan); - return (res); -} - void isp_clear_commands(ispsoftc_t *isp) { @@ -745,46 +570,49 @@ isp_clear_commands(ispsoftc_t *isp) #endif for (tmp = 0; isp->isp_xflist && tmp < isp->isp_maxcmds; tmp++) { - XS_T *xs; hdp = &isp->isp_xflist[tmp]; - if (hdp->handle == ISP_HANDLE_FREE) { - continue; - } - xs = hdp->cmd; - if (XS_XFRLEN(xs)) { - ISP_DMAFREE(isp, xs, hdp->handle); - XS_SET_RESID(xs, XS_XFRLEN(xs)); - } else { - XS_SET_RESID(xs, 0); + switch (ISP_H2HT(hdp->handle)) { + case ISP_HANDLE_INITIATOR: { + XS_T *xs = hdp->cmd; + if (XS_XFRLEN(xs)) { + ISP_DMAFREE(isp, xs, hdp->handle); + XS_SET_RESID(xs, XS_XFRLEN(xs)); + } else { + XS_SET_RESID(xs, 0); + } + isp_destroy_handle(isp, hdp->handle); + XS_SETERR(xs, HBA_BUSRESET); + isp_done(xs); + break; } - hdp->handle = 0; - hdp->cmd = NULL; - XS_SETERR(xs, HBA_BUSRESET); - isp_done(xs); - } #ifdef ISP_TARGET_MODE - for (tmp = 0; isp->isp_tgtlist && tmp < isp->isp_maxcmds; tmp++) { - uint8_t local[QENTRY_LEN]; - hdp = &isp->isp_tgtlist[tmp]; - if (hdp->handle == ISP_HANDLE_FREE) { - continue; + case ISP_HANDLE_TARGET: { + uint8_t local[QENTRY_LEN]; + ISP_DMAFREE(isp, hdp->cmd, hdp->handle); + ISP_MEMZERO(local, QENTRY_LEN); + if (IS_24XX(isp)) { + ct7_entry_t *ctio = (ct7_entry_t *) local; + ctio->ct_syshandle = hdp->handle; + ctio->ct_nphdl = CT_HBA_RESET; + ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO7; + } else { + ct2_entry_t *ctio = (ct2_entry_t *) local; + ctio->ct_syshandle = hdp->handle; + ctio->ct_status = CT_HBA_RESET; + ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO2; + } + isp_async(isp, ISPASYNC_TARGET_ACTION, local); + break; } - ISP_DMAFREE(isp, hdp->cmd, hdp->handle); - ISP_MEMZERO(local, QENTRY_LEN); - if (IS_24XX(isp)) { - ct7_entry_t *ctio = (ct7_entry_t *) local; - ctio->ct_syshandle = hdp->handle; - ctio->ct_nphdl = CT_HBA_RESET; - ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO7; - } else { - ct2_entry_t *ctio = (ct2_entry_t *) local; - ctio->ct_syshandle = hdp->handle; - ctio->ct_status = CT_HBA_RESET; - ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO2; +#endif + case ISP_HANDLE_CTRL: + wakeup(hdp->cmd); + isp_destroy_handle(isp, hdp->handle); + break; } - isp_async(isp, ISPASYNC_TARGET_ACTION, local); } +#ifdef ISP_TARGET_MODE for (tmp = 0; tmp < isp->isp_nchan; tmp++) { ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); notify.nt_ncode = NT_HBA_RESET; @@ -2385,69 +2213,6 @@ isp_send_tgt_cmd(ispsoftc_t *isp, void *fqe, void *segp, uint32_t nsegs, uint32_ return (CMD_QUEUED); } -int -isp_allocate_xs_tgt(ispsoftc_t *isp, void *xs, uint32_t *handlep) -{ - isp_hdl_t *hdp; - - hdp = isp->isp_tgtfree; - if (hdp == NULL) { - return (-1); - } - isp->isp_tgtfree = hdp->cmd; - hdp->cmd = xs; - hdp->handle = (hdp - isp->isp_tgtlist); - hdp->handle |= (ISP_HANDLE_TARGET << ISP_HANDLE_USAGE_SHIFT); - /* - * Target handles for SCSI cards are only 16 bits, so - * sequence number protection will be ommitted. - */ - if (IS_FC(isp)) { - hdp->handle |= (isp->isp_seqno++ << ISP_HANDLE_SEQ_SHIFT); - } - *handlep = hdp->handle; - return (0); -} - -void * -isp_find_xs_tgt(ispsoftc_t *isp, uint32_t handle) -{ - if (!ISP_VALID_TGT_HANDLE(isp, handle)) { - isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle); - return (NULL); - } - return (isp->isp_tgtlist[(handle & ISP_HANDLE_CMD_MASK)].cmd); -} - -uint32_t -isp_find_tgt_handle(ispsoftc_t *isp, void *xs) -{ - uint32_t i, foundhdl = ISP_HANDLE_FREE; - - if (xs != NULL) { - for (i = 0; i < isp->isp_maxcmds; i++) { - if (isp->isp_tgtlist[i].cmd != xs) { - continue; - } - foundhdl = isp->isp_tgtlist[i].handle; - break; - } - } - return (foundhdl); -} - -void -isp_destroy_tgt_handle(ispsoftc_t *isp, uint32_t handle) -{ - if (!ISP_VALID_TGT_HANDLE(isp, handle)) { - isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle); - } else { - isp->isp_tgtlist[(handle & ISP_HANDLE_CMD_MASK)].handle = ISP_HANDLE_FREE; - isp->isp_tgtlist[(handle & ISP_HANDLE_CMD_MASK)].cmd = isp->isp_tgtfree; - isp->isp_tgtfree = &isp->isp_tgtlist[(handle & ISP_HANDLE_CMD_MASK)]; - } -} - #endif /* diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h index efe4e0e..922a98b 100644 --- a/sys/dev/isp/isp_library.h +++ b/sys/dev/isp/isp_library.h @@ -43,10 +43,9 @@ int isp_send_cmd(ispsoftc_t *, void *, void *, uint32_t, uint32_t, isp_ddir_t, i * * These handles are associate with a command. */ -int isp_allocate_xs(ispsoftc_t *, XS_T *, uint32_t *); -XS_T * isp_find_xs(ispsoftc_t *, uint32_t); -uint32_t isp_find_handle(ispsoftc_t *, XS_T *); -uint32_t isp_handle_index(ispsoftc_t *, uint32_t); +uint32_t isp_allocate_handle(ispsoftc_t *, void *, int); +void *isp_find_xs(ispsoftc_t *, uint32_t); +uint32_t isp_find_handle(ispsoftc_t *, void *); void isp_destroy_handle(ispsoftc_t *, uint32_t); /* @@ -72,9 +71,6 @@ const char *isp_fc_fw_statename(int); const char *isp_fc_loop_statename(int); const char *isp_fc_toponame(fcparam *); -int isp_fc_change_role(ispsoftc_t *, int, int); - - /* * Cleanup */ @@ -165,11 +161,6 @@ void isp_put_fcp_rsp_iu(ispsoftc_t *isp, fcp_rsp_iu_t *, fcp_rsp_iu_t *); #endif int isp_send_tgt_cmd(ispsoftc_t *, void *, void *, uint32_t, uint32_t, isp_ddir_t, void *, uint32_t); - -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_empty(ispsoftc_t *, int, fcportdb_t **); int isp_find_pdb_by_wwpn(ispsoftc_t *, int, uint64_t, fcportdb_t **); diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index d30f6cb..11386ee 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -1539,78 +1539,17 @@ isp_pci_wr_reg_2600(ispsoftc_t *isp, int regoff, uint32_t val) struct imush { - ispsoftc_t *isp; - caddr_t vbase; - int chan; + bus_addr_t maddr; int error; }; -static void imc(void *, bus_dma_segment_t *, int, int); -static void imc1(void *, bus_dma_segment_t *, int, int); - static void imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) { struct imush *imushp = (struct imush *) arg; - isp_ecmd_t *ecmd; - - if (error) { - imushp->error = error; - return; - } - if (nseg != 1) { - imushp->error = EINVAL; - return; - } - isp_prt(imushp->isp, ISP_LOGDEBUG0, "request/result area @ 0x%jx/0x%jx", (uintmax_t) segs->ds_addr, (uintmax_t) segs->ds_len); - - imushp->isp->isp_rquest = imushp->vbase; - imushp->isp->isp_rquest_dma = segs->ds_addr; - segs->ds_addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp)); - imushp->vbase += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp)); - - imushp->isp->isp_result_dma = segs->ds_addr; - imushp->isp->isp_result = imushp->vbase; - segs->ds_addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp)); - imushp->vbase += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp)); - - if (imushp->isp->isp_type >= ISP_HA_FC_2200) { - imushp->isp->isp_osinfo.ecmd_dma = segs->ds_addr; - imushp->isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)imushp->vbase; - imushp->isp->isp_osinfo.ecmd_base = imushp->isp->isp_osinfo.ecmd_free; - for (ecmd = imushp->isp->isp_osinfo.ecmd_free; ecmd < &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) { - if (ecmd == &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS - 1]) { - ecmd->next = NULL; - } else { - ecmd->next = ecmd + 1; - } - } - } -#ifdef ISP_TARGET_MODE - segs->ds_addr += (N_XCMDS * XCMD_SIZE); - imushp->vbase += (N_XCMDS * XCMD_SIZE); - if (IS_24XX(imushp->isp)) { - imushp->isp->isp_atioq_dma = segs->ds_addr; - imushp->isp->isp_atioq = imushp->vbase; - } -#endif -} -static void -imc1(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct imush *imushp = (struct imush *) arg; - if (error) { - imushp->error = error; - return; - } - if (nseg != 1) { - imushp->error = EINVAL; - return; - } - isp_prt(imushp->isp, ISP_LOGDEBUG0, "scdma @ 0x%jx/0x%jx", (uintmax_t) segs->ds_addr, (uintmax_t) segs->ds_len); - FCPARAM(imushp->isp, imushp->chan)->isp_scdma = segs->ds_addr; - FCPARAM(imushp->isp, imushp->chan)->isp_scratch = imushp->vbase; + if (!(imushp->error = error)) + imushp->maddr = segs[0].ds_addr; } static int @@ -1623,6 +1562,7 @@ isp_pci_mbxdma(ispsoftc_t *isp) bus_addr_t llim; /* low limit of unavailable dma */ bus_addr_t hlim; /* high limit of unavailable dma */ struct imush im; + isp_ecmd_t *ecmd; /* * Already been here? If so, leave... @@ -1684,97 +1624,129 @@ isp_pci_mbxdma(ispsoftc_t *isp) isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; } isp->isp_xffree = isp->isp_xflist; -#ifdef ISP_TARGET_MODE - len = sizeof (isp_hdl_t) * isp->isp_maxcmds; - isp->isp_tgtlist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); - if (isp->isp_tgtlist == NULL) { - free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); - free(isp->isp_xflist, M_DEVBUF); - ISP_LOCK(isp); - isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array"); - return (1); - } - for (len = 0; len < isp->isp_maxcmds - 1; len++) { - isp->isp_tgtlist[len].cmd = &isp->isp_tgtlist[len+1]; - } - isp->isp_tgtfree = isp->isp_tgtlist; -#endif /* - * Allocate and map the request and result queues (and ATIO queue - * if we're a 2400 supporting target mode), and a region for - * external dma addressable command/status structures (23XX and - * later). + * Allocate and map the request queue and a region for external + * DMA addressable command/status structures (22XX and later). */ len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); - len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); -#ifdef ISP_TARGET_MODE - if (IS_24XX(isp)) { - len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); - } -#endif - if (isp->isp_type >= ISP_HA_FC_2200) { + if (isp->isp_type >= ISP_HA_FC_2200) len += (N_XCMDS * XCMD_SIZE); + if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + len, 1, len, 0, &isp->isp_osinfo.reqdmat)) { + isp_prt(isp, ISP_LOGERR, "cannot create request DMA tag"); + goto bad1; + } + if (bus_dmamem_alloc(isp->isp_osinfo.reqdmat, (void **)&base, + BUS_DMA_COHERENT, &isp->isp_osinfo.reqmap) != 0) { + isp_prt(isp, ISP_LOGERR, "cannot allocate request DMA memory"); + bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); + goto bad1; + } + isp->isp_rquest = base; + im.error = 0; + if (bus_dmamap_load(isp->isp_osinfo.reqdmat, isp->isp_osinfo.reqmap, + base, len, imc, &im, 0) || im.error) { + isp_prt(isp, ISP_LOGERR, "error loading request DMA map %d", im.error); + goto bad1; + } + isp_prt(isp, ISP_LOGDEBUG0, "request area @ 0x%jx/0x%jx", + (uintmax_t)im.maddr, (uintmax_t)len); + isp->isp_rquest_dma = im.maddr; + base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); + im.maddr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); + if (isp->isp_type >= ISP_HA_FC_2200) { + isp->isp_osinfo.ecmd_dma = im.maddr; + isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)base; + isp->isp_osinfo.ecmd_base = isp->isp_osinfo.ecmd_free; + for (ecmd = isp->isp_osinfo.ecmd_free; + ecmd < &isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) { + if (ecmd == &isp->isp_osinfo.ecmd_free[N_XCMDS - 1]) + ecmd->next = NULL; + else + ecmd->next = ecmd + 1; + } } /* - * Create a tag for the control spaces. We don't always need this - * to be 32 bits, but we do this for simplicity and speed's sake. + * Allocate and map the result queue. */ - if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, slim, 0, &isp->isp_osinfo.cdmat)) { - isp_prt(isp, ISP_LOGERR, "cannot create a dma tag for control spaces"); - free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); - free(isp->isp_xflist, M_DEVBUF); -#ifdef ISP_TARGET_MODE - free(isp->isp_tgtlist, M_DEVBUF); -#endif - ISP_LOCK(isp); - return (1); + len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); + if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + len, 1, len, 0, &isp->isp_osinfo.respdmat)) { + isp_prt(isp, ISP_LOGERR, "cannot create response DMA tag"); + goto bad1; + } + if (bus_dmamem_alloc(isp->isp_osinfo.respdmat, (void **)&base, + BUS_DMA_COHERENT, &isp->isp_osinfo.respmap) != 0) { + isp_prt(isp, ISP_LOGERR, "cannot allocate response DMA memory"); + bus_dma_tag_destroy(isp->isp_osinfo.respdmat); + goto bad1; + } + isp->isp_result = base; + im.error = 0; + if (bus_dmamap_load(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap, + base, len, imc, &im, 0) || im.error) { + isp_prt(isp, ISP_LOGERR, "error loading response DMA map %d", im.error); + goto bad1; } + isp_prt(isp, ISP_LOGDEBUG0, "response area @ 0x%jx/0x%jx", + (uintmax_t)im.maddr, (uintmax_t)len); + isp->isp_result_dma = im.maddr; - if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &isp->isp_osinfo.cdmap) != 0) { - isp_prt(isp, ISP_LOGERR, "cannot allocate %d bytes of CCB memory", len); - bus_dma_tag_destroy(isp->isp_osinfo.cdmat); - free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); - free(isp->isp_xflist, M_DEVBUF); #ifdef ISP_TARGET_MODE - free(isp->isp_tgtlist, M_DEVBUF); -#endif - ISP_LOCK(isp); - return (1); - } - - im.isp = isp; - im.chan = 0; - im.vbase = base; - im.error = 0; - - bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0); - if (im.error) { - isp_prt(isp, ISP_LOGERR, "error %d loading dma map for control areas", im.error); - goto bad; + /* + * Allocate and map ATIO queue on 24xx with target mode. + */ + if (IS_24XX(isp)) { + len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); + if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + len, 1, len, 0, &isp->isp_osinfo.atiodmat)) { + isp_prt(isp, ISP_LOGERR, "cannot create ATIO DMA tag"); + goto bad1; + } + if (bus_dmamem_alloc(isp->isp_osinfo.atiodmat, (void **)&base, + BUS_DMA_COHERENT, &isp->isp_osinfo.atiomap) != 0) { + isp_prt(isp, ISP_LOGERR, "cannot allocate ATIO DMA memory"); + bus_dma_tag_destroy(isp->isp_osinfo.atiodmat); + goto bad1; + } + isp->isp_atioq = base; + im.error = 0; + if (bus_dmamap_load(isp->isp_osinfo.atiodmat, isp->isp_osinfo.atiomap, + base, len, imc, &im, 0) || im.error) { + isp_prt(isp, ISP_LOGERR, "error loading ATIO DMA map %d", im.error); + goto bad; + } + isp_prt(isp, ISP_LOGDEBUG0, "ATIO area @ 0x%jx/0x%jx", + (uintmax_t)im.maddr, (uintmax_t)len); + isp->isp_atioq_dma = im.maddr; } +#endif if (IS_FC(isp)) { + if (isp_dma_tag_create(isp->isp_osinfo.dmat, 64, slim, + BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, + ISP_FC_SCRLEN, 1, ISP_FC_SCRLEN, 0, &isp->isp_osinfo.scdmat)) { + goto bad; + } for (cmap = 0; cmap < isp->isp_nchan; cmap++) { struct isp_fc *fc = ISP_FC_PC(isp, cmap); - if (isp_dma_tag_create(isp->isp_osinfo.dmat, 64, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, ISP_FC_SCRLEN, 1, slim, 0, &fc->tdmat)) { - goto bad; - } - if (bus_dmamem_alloc(fc->tdmat, (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &fc->tdmap) != 0) { - bus_dma_tag_destroy(fc->tdmat); + if (bus_dmamem_alloc(isp->isp_osinfo.scdmat, + (void **)&base, BUS_DMA_COHERENT, &fc->scmap) != 0) goto bad; - } - im.isp = isp; - im.chan = cmap; - im.vbase = base; + FCPARAM(isp, cmap)->isp_scratch = base; im.error = 0; - bus_dmamap_load(fc->tdmat, fc->tdmap, base, ISP_FC_SCRLEN, imc1, &im, 0); - if (im.error) { - bus_dmamem_free(fc->tdmat, base, fc->tdmap); - bus_dma_tag_destroy(fc->tdmat); + if (bus_dmamap_load(isp->isp_osinfo.scdmat, fc->scmap, + base, ISP_FC_SCRLEN, imc, &im, 0) || im.error) { + bus_dmamem_free(isp->isp_osinfo.scdmat, + base, fc->scmap); goto bad; } + FCPARAM(isp, cmap)->isp_scdma = im.maddr; if (!IS_2100(isp)) { for (i = 0; i < INITIAL_NEXUS_COUNT; i++) { struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO); @@ -1815,25 +1787,52 @@ isp_pci_mbxdma(ispsoftc_t *isp) return (0); bad: - while (--cmap >= 0) { - struct isp_fc *fc = ISP_FC_PC(isp, cmap); - bus_dmamap_unload(fc->tdmat, fc->tdmap); - bus_dmamem_free(fc->tdmat, base, fc->tdmap); - bus_dma_tag_destroy(fc->tdmat); - while (fc->nexus_free_list) { - struct isp_nexus *n = fc->nexus_free_list; - fc->nexus_free_list = n->next; - free(n, M_DEVBUF); + if (IS_FC(isp)) { + while (--cmap >= 0) { + struct isp_fc *fc = ISP_FC_PC(isp, cmap); + bus_dmamap_unload(isp->isp_osinfo.scdmat, fc->scmap); + bus_dmamem_free(isp->isp_osinfo.scdmat, base, fc->scmap); + while (fc->nexus_free_list) { + struct isp_nexus *n = fc->nexus_free_list; + fc->nexus_free_list = n->next; + free(n, M_DEVBUF); + } } + bus_dma_tag_destroy(isp->isp_osinfo.scdmat); + } +bad1: + if (isp->isp_rquest_dma != 0) { + bus_dmamap_unload(isp->isp_osinfo.reqdmat, + isp->isp_osinfo.reqmap); + } + if (isp->isp_rquest != NULL) { + bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest, + isp->isp_osinfo.reqmap); + bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); + } + if (isp->isp_result_dma != 0) { + bus_dmamap_unload(isp->isp_osinfo.respdmat, + isp->isp_osinfo.respmap); + } + if (isp->isp_result != NULL) { + bus_dmamem_free(isp->isp_osinfo.respdmat, isp->isp_result, + isp->isp_osinfo.respmap); + bus_dma_tag_destroy(isp->isp_osinfo.respdmat); } - if (isp->isp_rquest_dma != 0) - bus_dmamap_unload(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap); - bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap); - bus_dma_tag_destroy(isp->isp_osinfo.cdmat); - free(isp->isp_xflist, M_DEVBUF); #ifdef ISP_TARGET_MODE - free(isp->isp_tgtlist, M_DEVBUF); + if (IS_24XX(isp)) { + if (isp->isp_atioq_dma != 0) { + bus_dmamap_unload(isp->isp_osinfo.atiodmat, + isp->isp_osinfo.atiomap); + } + if (isp->isp_atioq != NULL) { + bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_atioq, + isp->isp_osinfo.atiomap); + bus_dma_tag_destroy(isp->isp_osinfo.atiodmat); + } + } #endif + free(isp->isp_xflist, M_DEVBUF); free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); isp->isp_rquest = NULL; ISP_LOCK(isp); diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c index 2abfc64..f1ca83c 100644 --- a/sys/dev/isp/isp_sbus.c +++ b/sys/dev/isp/isp_sbus.c @@ -413,7 +413,7 @@ isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val) } struct imush { - ispsoftc_t *isp; + bus_addr_t maddr; int error; }; @@ -423,16 +423,9 @@ static void imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) { struct imush *imushp = (struct imush *) arg; - if (error) { - imushp->error = error; - } else { - ispsoftc_t *isp =imushp->isp; - bus_addr_t addr = segs->ds_addr; - isp->isp_rquest_dma = addr; - addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); - isp->isp_result_dma = addr; - } + if (!(imushp->error = error)) + imushp->maddr = segs[0].ds_addr; } static int @@ -479,40 +472,62 @@ isp_sbus_mbxdma(ispsoftc_t *isp) BUS_SPACE_MAXADDR_32BIT, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT, ISP_NSEG_MAX, BUS_SPACE_MAXADDR_24BIT, 0, &isp->isp_osinfo.dmat)) { isp_prt(isp, ISP_LOGERR, "could not create master dma tag"); - free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); - free(isp->isp_xflist, M_DEVBUF); - ISP_LOCK(isp); - return(1); + goto bad; } /* - * Allocate and map the request, result queues, plus FC scratch area. + * Allocate and map the request queue. */ len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); - len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); - - if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, - BUS_SPACE_MAXADDR_24BIT+1, BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR_32BIT, NULL, NULL, len, 1, - BUS_SPACE_MAXADDR_24BIT, 0, &isp->isp_osinfo.cdmat)) { - isp_prt(isp, ISP_LOGERR, - "cannot create a dma tag for control spaces"); - free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); - free(isp->isp_xflist, M_DEVBUF); - ISP_LOCK(isp); - return (1); + if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, BUS_SPACE_MAXADDR_24BIT+1, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + len, 1, len, 0, &isp->isp_osinfo.reqdmat)) { + isp_prt(isp, ISP_LOGERR, "cannot create request DMA tag"); + goto bad; + } + if (bus_dmamem_alloc(isp->isp_osinfo.reqdmat, (void **)&base, + BUS_DMA_COHERENT, &isp->isp_osinfo.reqmap) != 0) { + isp_prt(isp, ISP_LOGERR, "cannot allocate request DMA memory"); + bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); + goto bad; + } + im.error = 0; + if (bus_dmamap_load(isp->isp_osinfo.reqdmat, isp->isp_osinfo.reqmap, + base, len, imc, &im, 0) || im.error) { + isp_prt(isp, ISP_LOGERR, "error loading request DMA map %d", im.error); + goto bad; } + isp_prt(isp, ISP_LOGDEBUG0, "request area @ 0x%jx/0x%jx", + (uintmax_t)im.maddr, (uintmax_t)len); + isp->isp_rquest = base; + isp->isp_rquest_dma = im.maddr; - if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, - &isp->isp_osinfo.cdmap) != 0) { - isp_prt(isp, ISP_LOGERR, - "cannot allocate %d bytes of CCB memory", len); - bus_dma_tag_destroy(isp->isp_osinfo.cdmat); - free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); - free(isp->isp_xflist, M_DEVBUF); - ISP_LOCK(isp); - return (1); + /* + * Allocate and map the result queue. + */ + len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); + if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, BUS_SPACE_MAXADDR_24BIT+1, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + len, 1, len, 0, &isp->isp_osinfo.respdmat)) { + isp_prt(isp, ISP_LOGERR, "cannot create response DMA tag"); + goto bad; } + if (bus_dmamem_alloc(isp->isp_osinfo.respdmat, (void **)&base, + BUS_DMA_COHERENT, &isp->isp_osinfo.respmap) != 0) { + isp_prt(isp, ISP_LOGERR, "cannot allocate response DMA memory"); + bus_dma_tag_destroy(isp->isp_osinfo.respdmat); + goto bad; + } + im.error = 0; + if (bus_dmamap_load(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap, + base, len, imc, &im, 0) || im.error) { + isp_prt(isp, ISP_LOGERR, "error loading response DMA map %d", im.error); + goto bad; + } + isp_prt(isp, ISP_LOGDEBUG0, "response area @ 0x%jx/0x%jx", + (uintmax_t)im.maddr, (uintmax_t)len); + isp->isp_result = base; + isp->isp_result_dma = im.maddr; for (i = 0; i < isp->isp_maxcmds; i++) { struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i]; @@ -534,25 +549,28 @@ isp_sbus_mbxdma(ispsoftc_t *isp) } } isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; - - im.isp = isp; - im.error = 0; - bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0); - if (im.error) { - isp_prt(isp, ISP_LOGERR, - "error %d loading dma map for control areas", im.error); - goto bad; - } - - isp->isp_rquest = base; - base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); - isp->isp_result = base; ISP_LOCK(isp); return (0); bad: - bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap); - bus_dma_tag_destroy(isp->isp_osinfo.cdmat); + if (isp->isp_rquest_dma != 0) { + bus_dmamap_unload(isp->isp_osinfo.reqdmat, + isp->isp_osinfo.reqmap); + } + if (isp->isp_rquest != NULL) { + bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest, + isp->isp_osinfo.reqmap); + bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); + } + if (isp->isp_result_dma != 0) { + bus_dmamap_unload(isp->isp_osinfo.respdmat, + isp->isp_osinfo.respmap); + } + if (isp->isp_result != NULL) { + bus_dmamem_free(isp->isp_osinfo.respdmat, isp->isp_result, + isp->isp_osinfo.respmap); + bus_dma_tag_destroy(isp->isp_osinfo.respdmat); + } free(isp->isp_xflist, M_DEVBUF); free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); isp->isp_rquest = NULL; diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c index c6e48fe..c6af888 100644 --- a/sys/dev/isp/isp_target.c +++ b/sys/dev/isp/isp_target.c @@ -1094,7 +1094,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) char *fmsg = NULL; if (ct->ct_syshandle) { - xs = isp_find_xs_tgt(isp, ct->ct_syshandle); + xs = isp_find_xs(isp, ct->ct_syshandle); if (xs == NULL) { pl = ISP_LOGALL; } @@ -1249,7 +1249,7 @@ isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct) char *fmsg = NULL; if (ct->ct_syshandle) { - xs = isp_find_xs_tgt(isp, ct->ct_syshandle); + xs = isp_find_xs(isp, ct->ct_syshandle); if (xs == NULL) { pl = ISP_LOGALL; } diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h index a89228b..5a1306f 100644 --- a/sys/dev/isp/ispmbox.h +++ b/sys/dev/isp/ispmbox.h @@ -1086,7 +1086,7 @@ typedef struct { #define ICB_DFLT_RDELAY 5 #define ICB_DFLT_RCOUNT 3 -#define ICB_LOGIN_TOV 30 +#define ICB_LOGIN_TOV 10 #define ICB_LUN_ENABLE_TOV 15 diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index 0c42642..a7184e2 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -77,7 +77,7 @@ struct ispmdvec { */ #define MAX_TARGETS 16 #ifndef MAX_FC_TARG -#define MAX_FC_TARG 256 +#define MAX_FC_TARG 1024 #endif #define ISP_MAX_TARGETS(isp) (IS_FC(isp)? MAX_FC_TARG : MAX_TARGETS) #define ISP_MAX_LUNS(isp) (isp)->isp_maxluns @@ -315,21 +315,16 @@ typedef struct { # define ISP_HANDLE_NONE 0 # define ISP_HANDLE_INITIATOR 1 # define ISP_HANDLE_TARGET 2 +# define ISP_HANDLE_CTRL 3 #define ISP_HANDLE_SEQ_MASK 0xffff0000 #define ISP_HANDLE_SEQ_SHIFT 16 #define ISP_H2SEQ(hdl) ((hdl & ISP_HANDLE_SEQ_MASK) >> ISP_HANDLE_SEQ_SHIFT) -#define ISP_VALID_INI_HANDLE(c, hdl) \ - (ISP_H2HT(hdl) == ISP_HANDLE_INITIATOR && (hdl & ISP_HANDLE_CMD_MASK) < (c)->isp_maxcmds && \ - ISP_H2SEQ(hdl) == ISP_H2SEQ((c)->isp_xflist[hdl & ISP_HANDLE_CMD_MASK].handle)) -#ifdef ISP_TARGET_MODE -#define ISP_VALID_TGT_HANDLE(c, hdl) \ - (ISP_H2HT(hdl) == ISP_HANDLE_TARGET && (hdl & ISP_HANDLE_CMD_MASK) < (c)->isp_maxcmds && \ - ISP_H2SEQ(hdl) == ISP_H2SEQ((c)->isp_tgtlist[hdl & ISP_HANDLE_CMD_MASK].handle)) #define ISP_VALID_HANDLE(c, hdl) \ - (ISP_VALID_INI_HANDLE((c), hdl) || ISP_VALID_TGT_HANDLE((c), hdl)) -#else -#define ISP_VALID_HANDLE ISP_VALID_INI_HANDLE -#endif + ((ISP_H2HT(hdl) == ISP_HANDLE_INITIATOR || \ + ISP_H2HT(hdl) == ISP_HANDLE_TARGET || \ + ISP_H2HT(hdl) == ISP_HANDLE_CTRL) && \ + ((hdl) & ISP_HANDLE_CMD_MASK) < (c)->isp_maxcmds && \ + (hdl) == ((c)->isp_xflist[(hdl) & ISP_HANDLE_CMD_MASK].handle)) #define ISP_BAD_HANDLE_INDEX 0xffffffff @@ -477,6 +472,8 @@ typedef struct { */ void * isp_scratch; XS_DMA_ADDR_T isp_scdma; + + uint8_t isp_scanscratch[ISP_FC_SCRLEN]; } fcparam; #define FW_CONFIG_WAIT 0 @@ -598,14 +595,6 @@ struct ispsoftc { isp_hdl_t *isp_xflist; isp_hdl_t *isp_xffree; -#ifdef ISP_TARGET_MODE - /* - * Active target commands are stored here, indexed by handle functions. - */ - isp_hdl_t *isp_tgtlist; - isp_hdl_t *isp_tgtfree; -#endif - /* * request/result queue pointers and DMA handles for them. */ |