summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-12-30 11:51:35 +0000
committermav <mav@FreeBSD.org>2015-12-30 11:51:35 +0000
commit5f12b30bfc3ad667d7db2668014bbda968c1001c (patch)
treeb7a4be17b11071b47e983cfacabe37d782ca17b9 /sys/dev
parent27a8f09a1b080c3913553e9a747a1e1b1ddde85b (diff)
downloadFreeBSD-src-5f12b30bfc3ad667d7db2668014bbda968c1001c.zip
FreeBSD-src-5f12b30bfc3ad667d7db2668014bbda968c1001c.tar.gz
MFC r292741: 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.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/isp/isp.c121
1 files changed, 55 insertions, 66 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index b5385bc..95f0302 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -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);
- }
-
- 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,
- 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;
+ /* 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;
@@ -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) {
OpenPOWER on IntegriCloud