diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/qle.c | 85 |
1 files changed, 54 insertions, 31 deletions
diff --git a/sys/dev/pci/qle.c b/sys/dev/pci/qle.c index 8ee6f772656..3ab2e5f6578 100644 --- a/sys/dev/pci/qle.c +++ b/sys/dev/pci/qle.c @@ -1,4 +1,4 @@ -/* $OpenBSD: qle.c,v 1.28 2014/04/27 05:23:35 jmatthew Exp $ */ +/* $OpenBSD: qle.c,v 1.29 2014/05/21 22:59:26 jmatthew Exp $ */ /* * Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org> @@ -100,9 +100,6 @@ enum qle_port_disp { QLE_PORT_DISP_DUP }; -#define QLE_DOMAIN_CTRL_MASK 0xffff00 -#define QLE_DOMAIN_CTRL 0xfffc00 - #define QLE_LOCATION_LOOP (1 << 24) #define QLE_LOCATION_FABRIC (2 << 24) #define QLE_LOCATION_LOOP_ID(l) (l | QLE_LOCATION_LOOP) @@ -293,11 +290,11 @@ int qle_get_port_db(struct qle_softc *, u_int16_t, int qle_get_port_name_list(struct qle_softc *sc, u_int32_t); int qle_add_loop_port(struct qle_softc *, struct qle_fc_port *); int qle_add_fabric_port(struct qle_softc *, struct qle_fc_port *); -int qle_add_domain_ctrl_port(struct qle_softc *, u_int16_t, +int qle_add_logged_in_port(struct qle_softc *, u_int16_t, u_int32_t); int qle_classify_port(struct qle_softc *, u_int32_t, u_int64_t, u_int64_t, struct qle_fc_port **); -int qle_get_loop_id(struct qle_softc *sc); +int qle_get_loop_id(struct qle_softc *sc, int); void qle_clear_port_lists(struct qle_softc *); int qle_softreset(struct qle_softc *); void qle_update_topology(struct qle_softc *); @@ -765,12 +762,15 @@ qle_classify_port(struct qle_softc *sc, u_int32_t location, } int -qle_get_loop_id(struct qle_softc *sc) +qle_get_loop_id(struct qle_softc *sc, int start) { int i, last; i = QLE_MIN_HANDLE; last = QLE_MAX_HANDLE; + if (i < start) + i = start; + for (; i <= last; i++) { if (sc->sc_targets[i] == NULL) return (i); @@ -947,6 +947,7 @@ qle_add_fabric_port(struct qle_softc *sc, struct qle_fc_port *port) */ if (port->location == QLE_LOCATION_FABRIC) { port->node_name = betoh64(pdb->node_name); + port->port_name = betoh64(pdb->port_name); port->portid = (pdb->port_id[0] << 16) | (pdb->port_id[1] << 8) | pdb->port_id[2]; port->location = QLE_LOCATION_PORT_ID(port->portid); @@ -964,29 +965,63 @@ qle_add_fabric_port(struct qle_softc *sc, struct qle_fc_port *port) } int -qle_add_domain_ctrl_port(struct qle_softc *sc, u_int16_t loopid, +qle_add_logged_in_port(struct qle_softc *sc, u_int16_t loopid, u_int32_t portid) { struct qle_fc_port *port; + struct qle_get_port_db *pdb; + u_int64_t node_name, port_name; + int flags, ret; + + ret = qle_get_port_db(sc, loopid, sc->sc_scratch); + mtx_enter(&sc->sc_port_mtx); + if (ret != 0) { + /* put in a fake port to prevent use of this loop id */ + printf("%s: loop id %d used, but can't see what's using it\n", + DEVNAME(sc), loopid); + node_name = 0; + port_name = 0; + flags = 0; + } else { + pdb = QLE_DMA_KVA(sc->sc_scratch); + node_name = betoh64(pdb->node_name); + port_name = betoh64(pdb->port_name); + flags = 0; + if (lemtoh16(&pdb->prli_svc_word3) & QLE_SVC3_TARGET_ROLE) + flags |= QLE_PORT_FLAG_IS_TARGET; + + /* see if we've already found this port */ + TAILQ_FOREACH(port, &sc->sc_ports_found, update) { + if ((port->node_name == node_name) && + (port->port_name == port_name) && + (port->portid == portid)) { + mtx_leave(&sc->sc_port_mtx); + DPRINTF(QLE_D_PORT, "%s: already found port " + "%06x\n", DEVNAME(sc), portid); + return (0); + } + } + } port = malloc(sizeof(*port), M_DEVBUF, M_ZERO | M_NOWAIT); if (port == NULL) { + mtx_leave(&sc->sc_port_mtx); printf("%s: failed to allocate a port structure\n", DEVNAME(sc)); return (1); } port->location = QLE_LOCATION_PORT_ID(portid); - port->port_name = 0; - port->node_name = 0; + port->port_name = port_name; + port->node_name = node_name; port->loopid = loopid; port->portid = portid; + port->flags = flags; - mtx_enter(&sc->sc_port_mtx); TAILQ_INSERT_TAIL(&sc->sc_ports, port, ports); sc->sc_targets[port->loopid] = port; mtx_leave(&sc->sc_port_mtx); - DPRINTF(QLE_D_PORT, "%s: added domain controller port %06x at %d\n", + DPRINTF(QLE_D_PORT, "%s: added logged in port %06x at %d\n", DEVNAME(sc), portid, loopid); return (0); } @@ -1976,14 +2011,14 @@ int qle_fabric_plogi(struct qle_softc *sc, struct qle_fc_port *port) { u_int32_t info; - int err; + int err, loopid; + loopid = 0; retry: if (port->loopid == 0) { - int loopid; mtx_enter(&sc->sc_port_mtx); - loopid = qle_get_loop_id(sc); + loopid = qle_get_loop_id(sc, loopid); mtx_leave(&sc->sc_port_mtx); if (loopid == -1) { printf("%s: ran out of loop ids\n", DEVNAME(sc)); @@ -2009,24 +2044,12 @@ retry: return (0); case QLE_PLOGX_ERROR_HANDLE_USED: - /* - * domain controller ids (fffcDD, where DD is the domain id) - * get special treatment here because we can't find out about - * them any other way. otherwise, we restart the update - * process to add the port at this handle normally. - */ - if ((info & QLE_DOMAIN_CTRL_MASK) == QLE_DOMAIN_CTRL) { - if (qle_add_domain_ctrl_port(sc, port->loopid, info)) { - return (1); - } - port->loopid = 0; - goto retry; + if (qle_add_logged_in_port(sc, loopid, info)) { + return (1); } - DPRINTF(QLE_D_PORT, "%s: handle %d used for port %06x\n", - DEVNAME(sc), loopid, info); - qle_update_start(sc, QLE_UPDATE_TASK_GET_PORT_LIST); port->loopid = 0; - return (1); + loopid++; + goto retry; default: DPRINTF(QLE_D_PORT, "%s: error %x logging in to port %06x\n", |