summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2017-03-29 16:13:24 +0000
committermav <mav@FreeBSD.org>2017-03-29 16:13:24 +0000
commit5201e87beff09b217ca4ea27b2f484d9d807c513 (patch)
tree8de7c7e3e5ea7852b2e8b8352bbcde39c86404e4
parentae40897038469ffe48ab392280d3d3d9200fb08f (diff)
downloadFreeBSD-src-5201e87beff09b217ca4ea27b2f484d9d807c513.zip
FreeBSD-src-5201e87beff09b217ca4ea27b2f484d9d807c513.tar.gz
MFC r315533: Move 24xx RQSTYPE_NOTIFY handling to generic code.
This code has nothing to do with specific platform.
-rw-r--r--sys/dev/isp/isp_freebsd.c157
-rw-r--r--sys/dev/isp/isp_target.c177
-rw-r--r--sys/dev/isp/isp_target.h3
3 files changed, 156 insertions, 181 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index a4d6bf5..4347e26 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -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 @@ mdp:
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)
{
@@ -4043,6 +3917,9 @@ changed:
*/
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);
@@ -4079,12 +3956,6 @@ changed:
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;
@@ -4097,6 +3968,10 @@ changed:
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;
}
diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c
index 0d5bab0..0d7ac31 100644
--- a/sys/dev/isp/isp_target.c
+++ b/sys/dev/isp/isp_target.c
@@ -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;
+ portid = PORT_ANY;
+ }
+
+ 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:
+ {
+ /*
+ * 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;
}
- lochan = chan;
- hichan = chan + 1;
+ 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;
}
- 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:
+ 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:
- case IN24XX_LINK_FAILED:
+ 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:
- 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);
- }
- inot_24xx->in_vpidx = ochan;
+#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;
}
}
diff --git a/sys/dev/isp/isp_target.h b/sys/dev/isp/isp_target.h
index 5c42732..d949a67 100644
--- a/sys/dev/isp/isp_target.h
+++ b/sys/dev/isp/isp_target.h
@@ -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 {
OpenPOWER on IntegriCloud