diff options
author | 2014-03-31 11:25:45 +0000 | |
---|---|---|
committer | 2014-03-31 11:25:45 +0000 | |
commit | d10165e5f7def8e8052cca42d08658e8dd4020dd (patch) | |
tree | e22467915df75fb5dc606aca85f093cfc73dd071 | |
parent | If HOST or the host argument starts with a /, treat it as a device name (diff) | |
download | wireguard-openbsd-d10165e5f7def8e8052cca42d08658e8dd4020dd.tar.xz wireguard-openbsd-d10165e5f7def8e8052cca42d08658e8dd4020dd.zip |
Rather than scanning local loop ids sequentially, just ask the chip which
local devices it has logged in to. This will also be useful for hotplug
later on.
-rw-r--r-- | sys/dev/ic/qla.c | 77 | ||||
-rw-r--r-- | sys/dev/ic/qlareg.h | 7 | ||||
-rw-r--r-- | sys/dev/ic/qlavar.h | 9 |
3 files changed, 75 insertions, 18 deletions
diff --git a/sys/dev/ic/qla.c b/sys/dev/ic/qla.c index 6f239a671e0..fcd27d4b20f 100644 --- a/sys/dev/ic/qla.c +++ b/sys/dev/ic/qla.c @@ -1,4 +1,4 @@ -/* $OpenBSD: qla.c,v 1.30 2014/02/23 10:40:19 jmatthew Exp $ */ +/* $OpenBSD: qla.c,v 1.31 2014/03/31 11:25:45 jmatthew Exp $ */ /* * Copyright (c) 2011 David Gwynne <dlg@openbsd.org> @@ -95,6 +95,7 @@ void qla_put_cmd(struct qla_softc *, void *, struct scsi_xfer *, struct qla_ccb *qla_handle_resp(struct qla_softc *, u_int16_t); void qla_put_data_seg(struct qla_iocb_seg *, bus_dmamap_t, int); +int qla_get_port_name_list(struct qla_softc *, u_int32_t); struct qla_fc_port *qla_next_fabric_port(struct qla_softc *, u_int32_t *, u_int32_t *); int qla_add_port(struct qla_softc *, u_int16_t, u_int32_t, @@ -311,6 +312,7 @@ qla_attach(struct qla_softc *sc) TAILQ_INIT(&sc->sc_ports); TAILQ_INIT(&sc->sc_ports_new); TAILQ_INIT(&sc->sc_ports_gone); + TAILQ_INIT(&sc->sc_ports_found); switch (sc->sc_isp_gen) { case QLA_GEN_ISP2100: @@ -523,37 +525,37 @@ qla_attach(struct qla_softc *sc) } if (sc->sc_loop_up) { - int i; + struct qla_fc_port *port; qla_update_topology(sc); - for (i = 0; i < sc->sc_loop_max_id; i++) { - if (i != sc->sc_loop_id) { - qla_add_port(sc, i, 0, - QLA_LOCATION_LOOP_ID(i)); - } + qla_get_port_name_list(sc, QLA_LOCATION_LOOP); + while (!TAILQ_EMPTY(&sc->sc_ports_found)) { + port = TAILQ_FIRST(&sc->sc_ports_found); + TAILQ_REMOVE(&sc->sc_ports_found, port, update); + qla_add_port(sc, port->loopid, port->portid, + QLA_LOCATION_LOOP_ID(port->loopid)); + free(port, M_DEVBUF); } if (qla_update_fabric(sc) == 0) { - TAILQ_HEAD(, qla_fc_port) found; u_int32_t firstport = 0xffffffff; u_int32_t lastport = 0; - struct qla_fc_port *port; - TAILQ_INIT(&found); do { port = qla_next_fabric_port(sc, &firstport, &lastport); if (port != NULL) - TAILQ_INSERT_TAIL(&found, port, update); + TAILQ_INSERT_TAIL(&sc->sc_ports_found, + port, update); } while (lastport != 0xffffffff); - while (!TAILQ_EMPTY(&found)) { - port = TAILQ_FIRST(&found); + while (!TAILQ_EMPTY(&sc->sc_ports_found)) { + port = TAILQ_FIRST(&sc->sc_ports_found); if (qla_fabric_plogi(sc, port) == 0) { qla_add_port(sc, port->loopid, port->portid, port->location); } - TAILQ_REMOVE(&found, port, update); + TAILQ_REMOVE(&sc->sc_ports_found, port, update); free(port, M_DEVBUF); } } @@ -1385,6 +1387,53 @@ qla_update_fabric(struct qla_softc *sc) return (0); } +int +qla_get_port_name_list(struct qla_softc *sc, u_int32_t match) +{ + int i; + struct qla_port_name_list *l; + struct qla_fc_port *port; + + sc->sc_mbox[0] = QLA_MBOX_GET_PORT_NAME_LIST; + sc->sc_mbox[1] = 0x08; /* include initiators */ + if (match & QLA_LOCATION_FABRIC) + sc->sc_mbox[1] |= 0x02; /* return all loop ids */ + qla_mbox_putaddr(sc->sc_mbox, sc->sc_scratch); + bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_scratch), 0, + QLA_DMA_LEN(sc->sc_scratch), BUS_DMASYNC_PREREAD); + if (qla_mbox(sc, 0x04f, 0x003)) { + DPRINTF(QLA_D_PORT, "%s: get port name list failed: %x\n", + DEVNAME(sc), sc->sc_mbox[0]); + return (1); + } + bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_scratch), 0, + QLA_DMA_LEN(sc->sc_scratch), BUS_DMASYNC_PREREAD); + + i = 0; + l = QLA_DMA_KVA(sc->sc_scratch); + while (i * sizeof(*l) < sc->sc_mbox[1]) { + u_int16_t loopid; + u_int32_t loc; + + loopid = letoh16(l[i].loop_id); + + loc = (loopid < QLA_MIN_HANDLE) ? QLA_LOCATION_LOOP : + QLA_LOCATION_FABRIC; + if (match & loc) { + port = malloc(sizeof(*port), M_DEVBUF, M_ZERO | + M_NOWAIT); + port->loopid = loopid; + port->port_name = letoh64(l[i].port_name); + DPRINTF(QLA_D_PORT, "%s: loop id %d, port name %llx\n", + DEVNAME(sc), port->loopid, port->port_name); + TAILQ_INSERT_TAIL(&sc->sc_ports_found, port, update); + } + i++; + } + + return (0); +} + struct qla_fc_port * qla_next_fabric_port(struct qla_softc *sc, u_int32_t *firstport, u_int32_t *lastport) diff --git a/sys/dev/ic/qlareg.h b/sys/dev/ic/qlareg.h index 6a3b15c56b7..3078bd61f28 100644 --- a/sys/dev/ic/qlareg.h +++ b/sys/dev/ic/qlareg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: qlareg.h,v 1.4 2014/02/06 21:05:54 jmatthew Exp $ */ +/* $OpenBSD: qlareg.h,v 1.5 2014/03/31 11:25:45 jmatthew Exp $ */ /* * Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org> @@ -423,6 +423,11 @@ struct qla_get_port_db { u_int16_t ext_lun_stop_ptr; } __packed; +struct qla_port_name_list { + u_int64_t port_name; + u_int16_t loop_id; +} __packed; + #define QLA_SVC3_TARGET_ROLE 0x0010 /* fabric name server commands */ diff --git a/sys/dev/ic/qlavar.h b/sys/dev/ic/qlavar.h index 556600df22f..82e793a8805 100644 --- a/sys/dev/ic/qlavar.h +++ b/sys/dev/ic/qlavar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: qlavar.h,v 1.5 2014/02/20 00:23:00 dlg Exp $ */ +/* $OpenBSD: qlavar.h,v 1.6 2014/03/31 11:25:45 jmatthew Exp $ */ /* * Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org> @@ -73,8 +73,10 @@ enum qla_port_disp { #define QLA_UPDATE_FABRIC_SCAN 4 #define QLA_UPDATE_FABRIC_RELOGIN 5 -#define QLA_LOCATION_LOOP_ID(l) (l | (1 << 24)) -#define QLA_LOCATION_PORT_ID(p) (p | (2 << 24)) +#define QLA_LOCATION_LOOP (1 << 24) +#define QLA_LOCATION_FABRIC (2 << 24) +#define QLA_LOCATION_LOOP_ID(l) (l | QLA_LOCATION_LOOP) +#define QLA_LOCATION_PORT_ID(p) (p | QLA_LOCATION_FABRIC) struct qla_fc_port { TAILQ_ENTRY(qla_fc_port) ports; @@ -158,6 +160,7 @@ struct qla_softc { TAILQ_HEAD(, qla_fc_port) sc_ports; TAILQ_HEAD(, qla_fc_port) sc_ports_new; TAILQ_HEAD(, qla_fc_port) sc_ports_gone; + TAILQ_HEAD(, qla_fc_port) sc_ports_found; struct qla_fc_port *sc_targets[QLA_MAX_TARGETS]; struct taskq *sc_scan_taskq; |