Make port logins asynchronous, following r292739 logic.

This is even more important since it involves more network operations and
more prone to delays and timeouts.
This commit is contained in:
Alexander Motin 2015-12-26 06:13:01 +00:00
parent e3148e46b2
commit 9d8b002160

View file

@ -108,7 +108,7 @@ 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);
@ -2550,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;
@ -2576,64 +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);
/* 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);
}
if (gs == 0) {
if (FC_SCRATCH_ACQUIRE(isp, chan)) {
isp_prt(isp, ISP_LOGERR, sacq);
return (-1);
}
/* 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);
}
fcp = FCPARAM(isp, chan);
scp = fcp->isp_scratch;
isp_put_plogx(isp, plp, (isp_plogx_t *) scp);
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);
MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL,
MBCMD_DEFAULT_TIMEOUT + ICB_LOGIN_TOV * 1000000);
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;
}
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 (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;
@ -2694,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);
}
@ -3196,7 +3184,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
@ -3883,7 +3871,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) {
@ -3892,12 +3880,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;
@ -4937,11 +4925,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;
@ -6170,6 +6158,7 @@ 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) {