From e5d3c72656a64ec23d22da4b2deb4a3e6e061355 Mon Sep 17 00:00:00 2001 From: jmatthew Date: Fri, 18 Apr 2014 05:08:15 +0000 Subject: [PATCH] Implement qle_fabric_plogo and let qle_fabric_plogi look at the response that comes back, so later on we can work out what to do when logins fail --- sys/dev/pci/qle.c | 92 +++++++++++++++++++++++++++++++++----------- sys/dev/pci/qlereg.h | 21 +++++++++- 2 files changed, 88 insertions(+), 25 deletions(-) diff --git a/sys/dev/pci/qle.c b/sys/dev/pci/qle.c index 1d0b885c1c9..d3a76f83901 100644 --- a/sys/dev/pci/qle.c +++ b/sys/dev/pci/qle.c @@ -1,4 +1,4 @@ -/* $OpenBSD: qle.c,v 1.24 2014/04/18 01:11:23 jmatthew Exp $ */ +/* $OpenBSD: qle.c,v 1.25 2014/04/18 05:08:15 jmatthew Exp $ */ /* * Copyright (c) 2013, 2014 Jonathan Matthew @@ -222,6 +222,7 @@ struct qle_softc { u_int32_t sc_last_resp_id; int sc_marker_required; int sc_fabric_pending; + u_int8_t sc_fabric_response[QLE_QUEUE_ENTRY_SIZE]; struct qle_nvram sc_nvram; int sc_nvram_valid; @@ -296,6 +297,8 @@ void qle_ports_gone(struct qle_softc *, u_int32_t); int qle_softreset(struct qle_softc *); void qle_update_topology(struct qle_softc *); int qle_update_fabric(struct qle_softc *); +int qle_fabric_plogx(struct qle_softc *, struct qle_fc_port *, int, + u_int32_t *); int qle_fabric_plogi(struct qle_softc *, struct qle_fc_port *); void qle_fabric_plogo(struct qle_softc *, struct qle_fc_port *); @@ -1025,6 +1028,8 @@ qle_handle_resp(struct qle_softc *sc, u_int32_t id) case QLE_IOCB_CT_PASSTHROUGH: if (sc->sc_fabric_pending) { qle_dump_iocb(sc, entry); + memcpy(sc->sc_fabric_response, entry, + QLE_QUEUE_ENTRY_SIZE); sc->sc_fabric_pending = 2; wakeup(sc->sc_scratch); } else { @@ -1805,24 +1810,15 @@ qle_next_fabric_port(struct qle_softc *sc, u_int32_t *firstport, return (fport); } - int -qle_fabric_plogi(struct qle_softc *sc, struct qle_fc_port *port) +qle_fabric_plogx(struct qle_softc *sc, struct qle_fc_port *port, int flags, + u_int32_t *info) { struct qle_iocb_plogx *iocb; u_int16_t req; u_int64_t offset; int rv; - int loopid; - mtx_enter(&sc->sc_port_mtx); - loopid = qle_get_loop_id(sc); - mtx_leave(&sc->sc_port_mtx); - if (loopid == -1) { - printf("%s: ran out of loop ids\n", DEVNAME(sc)); - return (1); - } - mtx_enter(&sc->sc_queue_mtx); req = sc->sc_next_req_id++; @@ -1839,12 +1835,14 @@ qle_fabric_plogi(struct qle_softc *sc, struct qle_fc_port *port) iocb->entry_count = 1; iocb->req_handle = 7; - htolem16(&iocb->req_nport_handle, loopid); + htolem16(&iocb->req_nport_handle, port->loopid); htolem16(&iocb->req_port_id_lo, port->portid); iocb->req_port_id_hi = port->portid >> 16; - iocb->req_flags = 0; + htolem16(&iocb->req_flags, flags); - /*qle_dump_iocb(sc, iocb);*/ + DPRINTF(QLE_D_PORT, "%s: plogx loop id %d port %06x, flags %x\n", + DEVNAME(sc), port->loopid, port->portid, flags); + qle_dump_iocb(sc, iocb); qle_write(sc, QLE_REQ_IN, sc->sc_next_req_id); sc->sc_fabric_pending = 1; @@ -1865,21 +1863,69 @@ qle_fabric_plogi(struct qle_softc *sc, struct qle_fc_port *port) } sc->sc_fabric_pending = 0; - port->loopid = loopid; + iocb = (struct qle_iocb_plogx *)&sc->sc_fabric_response; + rv = lemtoh16(&iocb->req_status); + if (rv == QLE_PLOGX_ERROR) { + rv = lemtoh32(&iocb->req_ioparms[0]); + *info = lemtoh32(&iocb->req_ioparms[1]); + } + return (rv); } +int +qle_fabric_plogi(struct qle_softc *sc, struct qle_fc_port *port) +{ + u_int32_t info; + int err; + + if (port->loopid == 0) { + int loopid; + + mtx_enter(&sc->sc_port_mtx); + loopid = qle_get_loop_id(sc); + mtx_leave(&sc->sc_port_mtx); + if (loopid == -1) { + printf("%s: ran out of loop ids\n", DEVNAME(sc)); + return (1); + } + + port->loopid = loopid; + } + + err = qle_fabric_plogx(sc, port, QLE_PLOGX_LOGIN, &info); + if (err == 0) { + DPRINTF(QLE_D_PORT, "%s: logged in to port %06x at %d\n", + DEVNAME(sc), port->portid, port->loopid); + port->flags &= ~QLE_PORT_FLAG_NEEDS_LOGIN; + return (0); + } else { + DPRINTF(QLE_D_PORT, "%s: error %x(%x) logging in to %06x\n", + DEVNAME(sc), err, info, port->portid); + port->loopid = 0; + return (1); + } +} + void qle_fabric_plogo(struct qle_softc *sc, struct qle_fc_port *port) { -#if 0 - sc->sc_mbox[0] = QLE_MBOX_FABRIC_PLOGO; - sc->sc_mbox[1] = port->loopid; - sc->sc_mbox[10] = 0; + int err; + u_int32_t info; - if (qle_mbox(sc, 0x0403)) - printf("%s: PLOGO %d failed\n", DEVNAME(sc), port->loopid); -#endif + /* + * we only log out if we can't see the port any more, so we always + * want to do an explicit logout and free the n-port handle. + */ + err = qle_fabric_plogx(sc, port, QLE_PLOGX_LOGOUT | + QLE_PLOGX_LOGOUT_EXPLICIT | QLE_PLOGX_LOGOUT_FREE_HANDLE, &info); + if (err == 0) { + DPRINTF(QLE_D_PORT, "%s: logged out of port %06x\n", + DEVNAME(sc), port->portid); + } else { + DPRINTF(QLE_D_PORT, "%s: failed to log out of port %06x: " + "%x %x\n", DEVNAME(sc), port->portid, err, info); + } } void diff --git a/sys/dev/pci/qlereg.h b/sys/dev/pci/qlereg.h index 65f17011a27..708105a9a60 100644 --- a/sys/dev/pci/qlereg.h +++ b/sys/dev/pci/qlereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: qlereg.h,v 1.7 2014/04/17 23:17:18 jmatthew Exp $ */ +/* $OpenBSD: qlereg.h,v 1.8 2014/04/18 05:08:15 jmatthew Exp $ */ /* * Copyright (c) 2013, 2014 Jonathan Matthew @@ -595,6 +595,23 @@ struct qle_iocb_ct_passthrough { struct qle_iocb_seg req_resp_seg; } __packed __aligned(64); +#define QLE_PLOGX_LOGIN 0x0000 +#define QLE_PLOGX_LOGIN_COND 0x0010 + +#define QLE_PLOGX_LOGOUT 0x0008 +#define QLE_PLOGX_LOGOUT_IMPLICIT 0x0010 +#define QLE_PLOGX_LOGOUT_ALL 0x0020 +#define QLE_PLOGX_LOGOUT_EXPLICIT 0x0040 +#define QLE_PLOGX_LOGOUT_FREE_HANDLE 0x0080 + +#define QLE_PLOGX_PORT_UNAVAILABLE 0x28 +#define QLE_PLOGX_PORT_LOGGED_OUT 0x29 +#define QLE_PLOGX_ERROR 0x31 + +#define QLE_PLOGX_ERROR_PORT_ID_USED 0x1A +#define QLE_PLOGX_ERROR_HANDLE_USED 0x1B +#define QLE_PLOGX_ERROR_NO_HANDLE 0x1C + struct qle_iocb_plogx { u_int8_t entry_type; /* QLE_IOCB_PLOGX */ u_int8_t entry_count; @@ -610,5 +627,5 @@ struct qle_iocb_plogx { u_int16_t req_port_id_lo; u_int8_t req_port_id_hi; u_int8_t req_rspsize; - u_int16_t req_ioparms[22]; + u_int32_t req_ioparms[11]; } __packed __aligned(64); -- 2.20.1