Move 24xx RQSTYPE_NOTIFY handling to generic code.

This code has nothing to do with specific platform.

MFC after:	2 weeks
This commit is contained in:
Alexander Motin 2017-03-19 09:30:03 +00:00
parent 15e58d4d26
commit 5a5632c2de
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=315533
3 changed files with 158 additions and 183 deletions

View File

@ -788,7 +788,6 @@ static void isp_target_start_ctio(ispsoftc_t *, union ccb *, enum Start_Ctio_How
static void isp_handle_platform_atio2(ispsoftc_t *, at2_entry_t *);
static void isp_handle_platform_atio7(ispsoftc_t *, at7_entry_t *);
static void isp_handle_platform_ctio(ispsoftc_t *, void *);
static void isp_handle_platform_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *);
static int isp_handle_platform_target_notify_ack(ispsoftc_t *, isp_notify_t *, uint32_t rsp);
static void isp_handle_platform_target_tmf(ispsoftc_t *, isp_notify_t *);
static void isp_target_mark_aborted_early(ispsoftc_t *, int chan, tstate_t *, uint32_t);
@ -2108,28 +2107,24 @@ isp_handle_srr_start(ispsoftc_t *isp, atio_private_data_t *atp)
static void
isp_handle_srr_notify(ispsoftc_t *isp, void *inot_raw)
isp_handle_platform_srr(ispsoftc_t *isp, isp_notify_t *notify)
{
in_fcentry_24xx_t *inot = inot_raw;
in_fcentry_24xx_t *inot = notify->nt_lreserved;
atio_private_data_t *atp;
uint32_t tag = inot->in_rxid;
uint32_t bus = inot->in_vpidx;
uint32_t tag = notify->nt_tagval & 0xffffffff;
if (!IS_24XX(isp)) {
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot_raw);
return;
}
atp = isp_find_atpd(isp, bus, tag);
atp = isp_find_atpd(isp, notify->nt_channel, tag);
if (atp == NULL) {
isp_prt(isp, ISP_LOGERR, "%s: cannot find adjunct for %x in SRR Notify", __func__, tag);
isp_prt(isp, ISP_LOGERR, "%s: cannot find adjunct for %x in SRR Notify",
__func__, tag);
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
return;
}
atp->srr_notify_rcvd = 1;
memcpy(atp->srr, inot, sizeof (atp->srr));
isp_prt(isp, ISP_LOGTINFO /* ISP_LOGTDEBUG0 */, "SRR[0x%x] inot->in_rxid flags 0x%x srr_iu=%x reloff 0x%x", inot->in_rxid, inot->in_flags, inot->in_srr_iu,
inot->in_srr_reloff_lo | (inot->in_srr_reloff_hi << 16));
isp_prt(isp, ISP_LOGTINFO, "SRR[0x%x] flags 0x%x srr_iu %x reloff 0x%x",
inot->in_rxid, inot->in_flags, inot->in_srr_iu,
((uint32_t)inot->in_srr_reloff_hi << 16) | inot->in_srr_reloff_lo);
if (atp->srr_ccb)
isp_handle_srr_start(isp, atp);
}
@ -2281,127 +2276,6 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
}
}
static void
isp_handle_platform_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *inot)
{
uint16_t nphdl;
uint16_t prli_options = 0;
uint32_t portid;
fcportdb_t *lp;
char *msg = NULL;
uint8_t *ptr = (uint8_t *)inot;
uint64_t wwpn = INI_NONE, wwnn = INI_NONE;
nphdl = inot->in_nphdl;
if (nphdl != NIL_HANDLE) {
portid = inot->in_portid_hi << 16 | inot->in_portid_lo;
} else {
portid = PORT_ANY;
}
switch (inot->in_status) {
case IN24XX_ELS_RCVD:
{
char buf[16];
int chan = ISP_GET_VPIDX(isp, inot->in_vpidx);
/*
* Note that we're just getting notification that an ELS was received
* (possibly with some associated information sent upstream). This is
* *not* the same as being given the ELS frame to accept or reject.
*/
switch (inot->in_status_subcode) {
case LOGO:
msg = "LOGO";
wwpn = be64dec(&ptr[IN24XX_PLOGI_WWPN_OFF]);
isp_del_wwn_entry(isp, chan, wwpn, nphdl, portid);
break;
case PRLO:
msg = "PRLO";
break;
case PLOGI:
msg = "PLOGI";
wwnn = be64dec(&ptr[IN24XX_PLOGI_WWNN_OFF]);
wwpn = be64dec(&ptr[IN24XX_PLOGI_WWPN_OFF]);
isp_add_wwn_entry(isp, chan, wwpn, wwnn,
nphdl, portid, prli_options);
break;
case PRLI:
msg = "PRLI";
prli_options = inot->in_prli_options;
if (inot->in_flags & IN24XX_FLAG_PN_NN_VALID)
wwnn = be64dec(&ptr[IN24XX_PRLI_WWNN_OFF]);
wwpn = be64dec(&ptr[IN24XX_PRLI_WWPN_OFF]);
isp_add_wwn_entry(isp, chan, wwpn, wwnn,
nphdl, portid, prli_options);
break;
case PDISC:
msg = "PDISC";
break;
case ADISC:
msg = "ADISC";
break;
default:
ISP_SNPRINTF(buf, sizeof (buf), "ELS 0x%x", inot->in_status_subcode);
msg = buf;
break;
}
if (inot->in_flags & IN24XX_FLAG_PUREX_IOCB) {
isp_prt(isp, ISP_LOGERR, "%s Chan %d ELS N-port handle %x PortID 0x%06x marked as needing a PUREX response", msg, chan, nphdl, portid);
break;
}
isp_prt(isp, ISP_LOGTDEBUG0, "%s Chan %d ELS N-port handle %x PortID 0x%06x RX_ID 0x%x OX_ID 0x%x", msg, chan, nphdl, portid,
inot->in_rxid, inot->in_oxid);
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
break;
}
case IN24XX_PORT_LOGOUT:
msg = "PORT LOGOUT";
if (isp_find_pdb_by_handle(isp, ISP_GET_VPIDX(isp, inot->in_vpidx), nphdl, &lp)) {
isp_del_wwn_entry(isp, ISP_GET_VPIDX(isp, inot->in_vpidx), lp->port_wwn, nphdl, lp->portid);
}
/* FALLTHROUGH */
case IN24XX_PORT_CHANGED:
if (msg == NULL)
msg = "PORT CHANGED";
/* FALLTHROUGH */
case IN24XX_LIP_RESET:
if (msg == NULL)
msg = "LIP RESET";
isp_prt(isp, ISP_LOGINFO, "Chan %d %s (sub-status 0x%x) for N-port handle 0x%x", ISP_GET_VPIDX(isp, inot->in_vpidx), msg, inot->in_status_subcode, nphdl);
/*
* All subcodes here are irrelevant. What is relevant
* is that we need to terminate all active commands from
* this initiator (known by N-port handle).
*/
/* XXX IMPLEMENT XXX */
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
break;
case IN24XX_SRR_RCVD:
#ifdef ISP_TARGET_MODE
isp_handle_srr_notify(isp, inot);
break;
#else
if (msg == NULL)
msg = "SRR RCVD";
/* FALLTHROUGH */
#endif
case IN24XX_LINK_RESET:
if (msg == NULL)
msg = "LINK RESET";
case IN24XX_LINK_FAILED:
if (msg == NULL)
msg = "LINK FAILED";
default:
isp_prt(isp, ISP_LOGWARN, "Chan %d %s", ISP_GET_VPIDX(isp, inot->in_vpidx), msg);
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
break;
}
}
static int
isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp, uint32_t rsp)
{
@ -4044,6 +3918,9 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
*/
isp_handle_platform_target_notify_ack(isp, notify, 0);
break;
case NT_SRR:
isp_handle_platform_srr(isp, notify);
break;
default:
isp_prt(isp, ISP_LOGALL, "target notify code 0x%x", notify->nt_ncode);
isp_handle_platform_target_notify_ack(isp, notify, 0);
@ -4080,12 +3957,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
hp = va_arg(ap, isphdr_t *);
va_end(ap);
switch (hp->rqs_entry_type) {
default:
isp_prt(isp, ISP_LOGWARN, "%s: unhandled target action 0x%x", __func__, hp->rqs_entry_type);
break;
case RQSTYPE_NOTIFY:
isp_handle_platform_notify_24xx(isp, (in_fcentry_24xx_t *) hp);
break;
case RQSTYPE_ATIO:
isp_handle_platform_atio7(isp, (at7_entry_t *) hp);
break;
@ -4098,6 +3969,10 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
case RQSTYPE_CTIO:
isp_handle_platform_ctio(isp, hp);
break;
default:
isp_prt(isp, ISP_LOGWARN, "%s: unhandled target action 0x%x",
__func__, hp->rqs_entry_type);
break;
}
break;
}

View File

@ -152,7 +152,7 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
#define hdrp unp.hp
} unp;
uint8_t local[QENTRY_LEN];
int bus, type, len, level, rval = 1;
int type, len, level, rval = 1;
type = isp_get_response_type(isp, (isphdr_t *)vptr);
unp.vp = vptr;
@ -214,11 +214,9 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
break;
case RQSTYPE_NOTIFY:
bus = 0;
if (IS_24XX(isp)) {
isp_get_notify_24xx(isp, inot_24xx, (in_fcentry_24xx_t *)local);
inot_24xx = (in_fcentry_24xx_t *) local;
isp_handle_notify_24xx(isp, inot_24xx);
isp_handle_notify_24xx(isp, (in_fcentry_24xx_t *)local);
break;
}
if (ISP_CAP_2KLOGIN(isp))
@ -1380,51 +1378,152 @@ isp_handle_notify(ispsoftc_t *isp, in_fcentry_t *inp)
}
static void
isp_handle_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *inot_24xx)
isp_handle_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *inot)
{
uint8_t ochan, chan, lochan, hichan;
uint8_t chan;
uint16_t nphdl, prli_options = 0;
uint32_t portid;
fcportdb_t *lp;
char *msg = NULL;
uint8_t *ptr = (uint8_t *)inot;
uint64_t wwpn = INI_NONE, wwnn = INI_NONE;
isp_notify_t notify;
char buf[16];
/*
* Check to see whether we got a wildcard channel.
* If so, we have to iterate over all channels.
*/
ochan = chan = ISP_GET_VPIDX(isp, inot_24xx->in_vpidx);
if (chan == 0xff) {
lochan = 0;
hichan = isp->isp_nchan;
nphdl = inot->in_nphdl;
if (nphdl != NIL_HANDLE) {
portid = inot->in_portid_hi << 16 | inot->in_portid_lo;
} else {
if (chan >= isp->isp_nchan) {
char buf[64];
ISP_SNPRINTF(buf, sizeof buf, "%s: bad channel %d for status 0x%x", __func__, chan, inot_24xx->in_status);
isp_print_bytes(isp, buf, QENTRY_LEN, inot_24xx);
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot_24xx);
return;
}
lochan = chan;
hichan = chan + 1;
portid = PORT_ANY;
}
isp_prt(isp, ISP_LOGTDEBUG1, "%s: Immediate Notify Channels %d..%d status=0x%x seqid=0x%x", __func__, lochan, hichan-1, inot_24xx->in_status, inot_24xx->in_rxid);
switch (inot_24xx->in_status) {
case IN24XX_LIP_RESET:
case IN24XX_LINK_RESET:
case IN24XX_PORT_LOGOUT:
case IN24XX_PORT_CHANGED:
case IN24XX_LINK_FAILED:
case IN24XX_SRR_RCVD:
chan = ISP_GET_VPIDX(isp, inot->in_vpidx);
if (chan >= isp->isp_nchan &&
inot->in_status != IN24XX_LIP_RESET &&
inot->in_status != IN24XX_LINK_RESET &&
inot->in_status != IN24XX_LINK_FAILED) {
isp_prt(isp, ISP_LOGWARN, "%s: Received INOT with status %x on VP %x",
__func__, inot->in_status, chan);
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
return;
}
switch (inot->in_status) {
case IN24XX_ELS_RCVD:
for (chan = lochan; chan < hichan; chan++) {
if (FCPARAM(isp, chan)->role == ISP_ROLE_NONE)
continue;
inot_24xx->in_reserved = 0; /* clear this for later usage */
inot_24xx->in_vpidx = chan;
isp_async(isp, ISPASYNC_TARGET_ACTION, inot_24xx);
{
/*
* Note that we're just getting notification that an ELS was
* received (possibly with some associated information sent
* upstream). This is *not* the same as being given the ELS
* frame to accept or reject.
*/
switch (inot->in_status_subcode) {
case LOGO:
msg = "LOGO";
wwpn = be64dec(&ptr[IN24XX_PLOGI_WWPN_OFF]);
isp_del_wwn_entry(isp, chan, wwpn, nphdl, portid);
break;
case PRLO:
msg = "PRLO";
break;
case PLOGI:
msg = "PLOGI";
wwnn = be64dec(&ptr[IN24XX_PLOGI_WWNN_OFF]);
wwpn = be64dec(&ptr[IN24XX_PLOGI_WWPN_OFF]);
isp_add_wwn_entry(isp, chan, wwpn, wwnn,
nphdl, portid, prli_options);
break;
case PRLI:
msg = "PRLI";
prli_options = inot->in_prli_options;
if (inot->in_flags & IN24XX_FLAG_PN_NN_VALID)
wwnn = be64dec(&ptr[IN24XX_PRLI_WWNN_OFF]);
wwpn = be64dec(&ptr[IN24XX_PRLI_WWPN_OFF]);
isp_add_wwn_entry(isp, chan, wwpn, wwnn,
nphdl, portid, prli_options);
break;
case PDISC:
msg = "PDISC";
break;
case ADISC:
msg = "ADISC";
break;
default:
ISP_SNPRINTF(buf, sizeof (buf), "ELS 0x%x",
inot->in_status_subcode);
msg = buf;
break;
}
inot_24xx->in_vpidx = ochan;
if (inot->in_flags & IN24XX_FLAG_PUREX_IOCB) {
isp_prt(isp, ISP_LOGERR, "%s Chan %d ELS N-port handle %x"
" PortID 0x%06x marked as needing a PUREX response",
msg, chan, nphdl, portid);
break;
}
isp_prt(isp, ISP_LOGTDEBUG0, "%s Chan %d ELS N-port handle %x"
" PortID 0x%06x RX_ID 0x%x OX_ID 0x%x", msg, chan, nphdl,
portid, inot->in_rxid, inot->in_oxid);
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
break;
}
case IN24XX_PORT_LOGOUT:
msg = "PORT LOGOUT";
if (isp_find_pdb_by_handle(isp, chan, nphdl, &lp))
isp_del_wwn_entry(isp, chan, lp->port_wwn, nphdl, lp->portid);
/* FALLTHROUGH */
case IN24XX_PORT_CHANGED:
if (msg == NULL)
msg = "PORT CHANGED";
/* FALLTHROUGH */
case IN24XX_LIP_RESET:
if (msg == NULL)
msg = "LIP RESET";
isp_prt(isp, ISP_LOGINFO, "Chan %d %s (sub-status 0x%x) for "
"N-port handle 0x%x",
chan, msg, inot->in_status_subcode, nphdl);
/*
* All subcodes here are irrelevant. What is relevant
* is that we need to terminate all active commands from
* this initiator (known by N-port handle).
*/
/* XXX IMPLEMENT XXX */
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
break;
case IN24XX_SRR_RCVD:
#ifdef ISP_TARGET_MODE
ISP_MEMZERO(&notify, sizeof (isp_notify_t));
notify.nt_hba = isp;
notify.nt_wwn = INI_ANY;
notify.nt_tgt = FCPARAM(isp, chan)->isp_wwpn;
notify.nt_nphdl = nphdl;
notify.nt_sid = portid;
notify.nt_did = PORT_ANY;
notify.nt_lun = LUN_ANY;
notify.nt_tagval = inot->in_rxid;
notify.nt_tagval |= ((uint64_t)inot->in_srr_rxid << 32);
notify.nt_need_ack = 1;
notify.nt_channel = chan;
notify.nt_lreserved = inot;
notify.nt_ncode = NT_SRR;
isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
break;
#else
if (msg == NULL)
msg = "SRR RCVD";
/* FALLTHROUGH */
#endif
case IN24XX_LINK_RESET:
if (msg == NULL)
msg = "LINK RESET";
case IN24XX_LINK_FAILED:
if (msg == NULL)
msg = "LINK FAILED";
default:
isp_prt(isp, ISP_LOGINFO, "%s: unhandled status (0x%x) for chan %d",
__func__, inot_24xx->in_status, chan);
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot_24xx);
isp_prt(isp, ISP_LOGWARN, "Chan %d %s", chan, msg);
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
break;
}
}

View File

@ -53,7 +53,8 @@ typedef enum {
NT_CHANGED,
NT_HBA_RESET,
NT_QUERY_TASK_SET,
NT_QUERY_ASYNC_EVENT
NT_QUERY_ASYNC_EVENT,
NT_SRR /* Sequence Retransmission Request */
} isp_ncode_t;
typedef struct isp_notify {