summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJonathan Matthew <jmatthew@cvs.openbsd.org>2014-04-20 09:49:24 +0000
committerJonathan Matthew <jmatthew@cvs.openbsd.org>2014-04-20 09:49:24 +0000
commit0d1459d9b91fa20b4e28e9b0ba6f183ba65aab47 (patch)
treec8e9752f27653bb2daa0924a653949b9d1852d8d /sys
parent5058855ac007b9afc9818aa4250e331295100b1a (diff)
Update hotplug. Add qle_get_port_name_list, use it to discover local
loop ports and other fabric ports that have logged in to us, and check that we're still logged in to other fabric ports. Rearrange the update processing loop so we attach and detach targets last, since we need to get all the way through before we've identified what's gone missing. Handle fabric port login errors a bit more usefully too.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/qle.c399
-rw-r--r--sys/dev/pci/qlereg.h8
2 files changed, 274 insertions, 133 deletions
diff --git a/sys/dev/pci/qle.c b/sys/dev/pci/qle.c
index d3a76f83901..89553596984 100644
--- a/sys/dev/pci/qle.c
+++ b/sys/dev/pci/qle.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: qle.c,v 1.25 2014/04/18 05:08:15 jmatthew Exp $ */
+/* $OpenBSD: qle.c,v 1.26 2014/04/20 09:49:23 jmatthew Exp $ */
/*
* Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org>
@@ -196,15 +196,15 @@ struct qle_softc {
int sc_update_tasks;
#define QLE_UPDATE_TASK_CLEAR_ALL 0x00000001
#define QLE_UPDATE_TASK_SOFTRESET 0x00000002
-#define QLE_UPDATE_TASK_DETACH_TARGET 0x00000004
-#define QLE_UPDATE_TASK_ATTACH_TARGET 0x00000008
-#define QLE_UPDATE_TASK_UPDATE_TOPO 0x00000010
-#define QLE_UPDATE_TASK_SCAN_LOOP 0x00000020
-#define QLE_UPDATE_TASK_SCANNING_LOOP 0x00000040
-#define QLE_UPDATE_TASK_SCAN_FABRIC 0x00000080
-#define QLE_UPDATE_TASK_SCANNING_FABRIC 0x00000100
-#define QLE_UPDATE_TASK_FABRIC_LOGIN 0x00000200
-#define QLE_UPDATE_TASK_FABRIC_RELOGIN 0x00000400
+#define QLE_UPDATE_TASK_UPDATE_TOPO 0x00000004
+#define QLE_UPDATE_TASK_GET_PORT_LIST 0x00000008
+#define QLE_UPDATE_TASK_PORT_LIST 0x00000010
+#define QLE_UPDATE_TASK_SCAN_FABRIC 0x00000020
+#define QLE_UPDATE_TASK_SCANNING_FABRIC 0x00000040
+#define QLE_UPDATE_TASK_FABRIC_LOGIN 0x00000080
+#define QLE_UPDATE_TASK_FABRIC_RELOGIN 0x00000100
+#define QLE_UPDATE_TASK_DETACH_TARGET 0x00000200
+#define QLE_UPDATE_TASK_ATTACH_TARGET 0x00000400
int sc_maxcmds;
struct qle_dmamem *sc_requests;
@@ -287,13 +287,13 @@ struct qle_fc_port *qle_next_fabric_port(struct qle_softc *, u_int32_t *,
u_int32_t *);
int qle_get_port_db(struct qle_softc *, u_int16_t,
struct qle_dmamem *);
-int qle_add_loop_port(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_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);
void qle_clear_port_lists(struct qle_softc *);
-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 *);
@@ -735,7 +735,7 @@ qle_classify_port(struct qle_softc *sc, u_int32_t location,
return (QLE_PORT_DISP_NEW);
}
- TAILQ_FOREACH(port, &sc->sc_ports_gone, update) {
+ TAILQ_FOREACH(port, &sc->sc_ports, ports) {
if (port->location == location)
locmatch = port;
@@ -794,31 +794,95 @@ qle_get_port_db(struct qle_softc *sc, u_int16_t loopid, struct qle_dmamem *mem)
}
int
-qle_add_loop_port(struct qle_softc *sc, u_int16_t loopid)
+qle_get_port_name_list(struct qle_softc *sc, u_int32_t match)
{
- struct qle_get_port_db *pdb;
- struct qle_fc_port *port, *pport;
- int disp;
+ struct qle_port_name_list *l;
+ struct qle_fc_port *port;
+ int i;
- if (qle_get_port_db(sc, loopid, sc->sc_scratch) != 0) {
+ sc->sc_mbox[0] = QLE_MBOX_GET_PORT_NAME_LIST;
+ sc->sc_mbox[1] = 0;
+ sc->sc_mbox[8] = QLE_DMA_LEN(sc->sc_scratch);
+ sc->sc_mbox[9] = 0;
+ qle_mbox_putaddr(sc->sc_mbox, sc->sc_scratch);
+ bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_scratch), 0,
+ QLE_DMA_LEN(sc->sc_scratch), BUS_DMASYNC_PREREAD);
+ if (qle_mbox(sc, 0x03cf)) {
+ DPRINTF(QLE_D_PORT, "%s: get port name list failed: %x\n",
+ DEVNAME(sc), sc->sc_mbox[0]);
return (1);
}
- pdb = QLE_DMA_KVA(sc->sc_scratch);
+ bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_scratch), 0,
+ sc->sc_mbox[1], BUS_DMASYNC_POSTREAD);
- port = malloc(sizeof(*port), M_DEVBUF, M_ZERO | M_NOWAIT);
- if (port == NULL) {
- printf("%s: failed to allocate a port structure\n",
- DEVNAME(sc));
+ i = 0;
+ l = QLE_DMA_KVA(sc->sc_scratch);
+ mtx_enter(&sc->sc_port_mtx);
+ while (i * sizeof(*l) < sc->sc_mbox[1]) {
+ u_int16_t loopid;
+ u_int32_t loc;
+
+ loopid = lemtoh16(&l[i].loopid) & 0xfff;
+ /* skip special ports */
+ switch (loopid) {
+ case QLE_F_PORT_HANDLE:
+ case QLE_SNS_HANDLE:
+ case QLE_FABRIC_CTRL_HANDLE:
+ case QLE_IP_BCAST_HANDLE:
+ loc = 0;
+ break;
+ default:
+ if (loopid <= sc->sc_loop_max_id) {
+ loc = QLE_LOCATION_LOOP_ID(loopid);
+ } else {
+ /*
+ * we don't have the port id here, so just
+ * indicate it's a fabric port.
+ */
+ loc = QLE_LOCATION_FABRIC;
+ }
+ break;
+ }
+
+ if (match & loc) {
+ port = malloc(sizeof(*port), M_DEVBUF, M_ZERO |
+ M_NOWAIT);
+ if (port == NULL) {
+ printf("%s: failed to allocate port struct\n",
+ DEVNAME(sc));
+ break;
+ }
+ port->location = loc;
+ port->loopid = loopid;
+ port->port_name = letoh64(l[i].port_name);
+ DPRINTF(QLE_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++;
+ }
+ mtx_leave(&sc->sc_port_mtx);
+
+ return (0);
+}
+
+int
+qle_add_loop_port(struct qle_softc *sc, struct qle_fc_port *port)
+{
+ struct qle_get_port_db *pdb;
+ struct qle_fc_port *pport;
+ int disp;
+
+ if (qle_get_port_db(sc, port->loopid, sc->sc_scratch) != 0) {
return (1);
}
+ pdb = QLE_DMA_KVA(sc->sc_scratch);
if (lemtoh16(&pdb->prli_svc_word3) & QLE_SVC3_TARGET_ROLE)
port->flags |= QLE_PORT_FLAG_IS_TARGET;
port->port_name = betoh64(pdb->port_name);
port->node_name = betoh64(pdb->node_name);
- port->location = QLE_LOCATION_LOOP_ID(loopid);
- port->loopid = loopid;
port->portid = (pdb->port_id[0] << 16) | (pdb->port_id[1] << 8) |
pdb->port_id[2];
@@ -830,7 +894,7 @@ qle_add_loop_port(struct qle_softc *sc, u_int16_t loopid)
case QLE_PORT_DISP_MOVED:
case QLE_PORT_DISP_NEW:
TAILQ_INSERT_TAIL(&sc->sc_ports_new, port, update);
- sc->sc_targets[loopid] = port;
+ sc->sc_targets[port->loopid] = port;
break;
case QLE_PORT_DISP_DUP:
free(port, M_DEVBUF);
@@ -848,7 +912,8 @@ qle_add_loop_port(struct qle_softc *sc, u_int16_t loopid)
case QLE_PORT_DISP_NEW:
DPRINTF(QLE_D_PORT, "%s: %s %d; name %llx\n",
DEVNAME(sc), ISSET(port->flags, QLE_PORT_FLAG_IS_TARGET) ?
- "target" : "non-target", loopid, betoh64(pdb->port_name));
+ "target" : "non-target", port->loopid,
+ betoh64(pdb->port_name));
break;
default:
break;
@@ -870,7 +935,17 @@ qle_add_fabric_port(struct qle_softc *sc, struct qle_fc_port *port)
if (lemtoh16(&pdb->prli_svc_word3) & QLE_SVC3_TARGET_ROLE)
port->flags |= QLE_PORT_FLAG_IS_TARGET;
- /* compare port and node name with what's in the port db now */
+ /*
+ * if we only know about this port because qle_get_port_name_list
+ * returned it, we don't have its port id or node name, so fill
+ * those in and update its location.
+ */
+ if (port->location == QLE_LOCATION_FABRIC) {
+ port->node_name = betoh64(pdb->node_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);
+ }
mtx_enter(&sc->sc_port_mtx);
TAILQ_INSERT_TAIL(&sc->sc_ports_new, port, update);
@@ -1009,6 +1084,7 @@ qle_handle_resp(struct qle_softc *sc, u_int32_t id)
case QLE_IOCB_STATUS_PORT_CHANGED:
DPRINTF(QLE_D_IO, "%s: dev gone\n", DEVNAME(sc));
xs->error = XS_SELTIMEOUT;
+ /* mark port as needing relogin? */
break;
default:
@@ -1490,16 +1566,6 @@ qle_clear_port_lists(struct qle_softc *sc)
}
}
-void
-qle_ports_gone(struct qle_softc *sc, u_int32_t location)
-{
- struct qle_fc_port *port;
- TAILQ_FOREACH(port, &sc->sc_ports, ports) {
- if ((port->location & location) != 0)
- TAILQ_INSERT_TAIL(&sc->sc_ports_gone, port, update);
- }
-}
-
int
qle_softreset(struct qle_softc *sc)
{
@@ -1894,14 +1960,29 @@ qle_fabric_plogi(struct qle_softc *sc, struct qle_fc_port *port)
}
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",
+ switch (err) {
+ case 0:
+ DPRINTF(QLE_D_PORT, "%s: logged in to %06x as %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);
+
+ case QLE_PLOGX_ERROR_PORT_ID_USED:
+ DPRINTF(QLE_D_PORT, "%s: already logged in to %06x as %d\n",
+ DEVNAME(sc), port->portid, info);
+ port->loopid = info;
+ return (0);
+
+ case QLE_PLOGX_ERROR_HANDLE_USED:
+ DPRINTF(QLE_D_PORT, "%s: handle %d used for port %06x\n",
+ DEVNAME(sc), port->loopid, info);
+ /* now do something clever */
+ port->loopid = 0;
+ return (1);
+
+ default:
+ DPRINTF(QLE_D_PORT, "%s: error %x logging in to port %06x\n",
+ DEVNAME(sc), err);
port->loopid = 0;
return (1);
}
@@ -1932,8 +2013,8 @@ void
qle_do_update(void *xsc, void *x)
{
struct qle_softc *sc = xsc;
- int step, firstport, lastport;
- struct qle_fc_port *port;
+ int firstport, lastport;
+ struct qle_fc_port *port, *fport;
DPRINTF(QLE_D_PORT, "%s: updating\n", DEVNAME(sc));
while (sc->sc_update_tasks != 0) {
@@ -1949,9 +2030,6 @@ qle_do_update(void *xsc, void *x)
port = TAILQ_FIRST(&sc->sc_ports);
TAILQ_REMOVE(&sc->sc_ports, port, ports);
TAILQ_INSERT_TAIL(&detach, port, ports);
- if (port->flags & QLE_PORT_FLAG_IS_TARGET) {
- sc->sc_targets[port->loopid] = NULL;
- }
}
mtx_leave(&sc->sc_port_mtx);
@@ -1984,56 +2062,6 @@ qle_do_update(void *xsc, void *x)
continue;
}
- if (sc->sc_update_tasks & QLE_UPDATE_TASK_DETACH_TARGET) {
- mtx_enter(&sc->sc_port_mtx);
- port = TAILQ_FIRST(&sc->sc_ports_gone);
- if (port != NULL) {
- sc->sc_targets[port->loopid] = NULL;
- TAILQ_REMOVE(&sc->sc_ports_gone, port, update);
- TAILQ_REMOVE(&sc->sc_ports, port, ports);
- }
- mtx_leave(&sc->sc_port_mtx);
-
- if (port != NULL) {
- DPRINTF(QLE_D_PORT, "%s: detaching port %06x\n",
- DEVNAME(sc), port->portid);
- if (sc->sc_scsibus != NULL)
- scsi_detach_target(sc->sc_scsibus,
- port->loopid, -1);
-
- if (port->location & QLE_LOCATION_FABRIC)
- qle_fabric_plogo(sc, port);
-
- free(port, M_DEVBUF);
- } else {
- DPRINTF(QLE_D_PORT, "%s: nothing to detach\n",
- DEVNAME(sc));
- qle_update_done(sc,
- QLE_UPDATE_TASK_DETACH_TARGET);
- }
- continue;
- }
-
- if (sc->sc_update_tasks & QLE_UPDATE_TASK_ATTACH_TARGET) {
- mtx_enter(&sc->sc_port_mtx);
- port = TAILQ_FIRST(&sc->sc_ports_new);
- if (port != NULL) {
- TAILQ_REMOVE(&sc->sc_ports_new, port, update);
- TAILQ_INSERT_TAIL(&sc->sc_ports, port, ports);
- }
- mtx_leave(&sc->sc_port_mtx);
-
- if (port != NULL) {
- if (sc->sc_scsibus != NULL)
- scsi_probe_target(sc->sc_scsibus,
- port->loopid);
- } else {
- qle_update_done(sc,
- QLE_UPDATE_TASK_ATTACH_TARGET);
- }
- continue;
- }
-
if (sc->sc_update_tasks & QLE_UPDATE_TASK_UPDATE_TOPO) {
DPRINTF(QLE_D_PORT, "%s: updating topology\n",
DEVNAME(sc));
@@ -2042,28 +2070,79 @@ qle_do_update(void *xsc, void *x)
continue;
}
- if (sc->sc_update_tasks & QLE_UPDATE_TASK_SCAN_LOOP) {
- DPRINTF(QLE_D_PORT, "%s: starting loop scan\n",
+ if (sc->sc_update_tasks & QLE_UPDATE_TASK_GET_PORT_LIST) {
+ DPRINTF(QLE_D_PORT, "%s: getting port name list\n",
DEVNAME(sc));
+ mtx_enter(&sc->sc_port_mtx);
qle_clear_port_lists(sc);
- qle_update_start(sc, QLE_UPDATE_TASK_SCANNING_LOOP);
- qle_update_done(sc, QLE_UPDATE_TASK_SCAN_LOOP);
- step = 0;
+ mtx_leave(&sc->sc_port_mtx);
+
+ qle_get_port_name_list(sc, QLE_LOCATION_LOOP |
+ QLE_LOCATION_FABRIC);
+ mtx_enter(&sc->sc_port_mtx);
+ TAILQ_FOREACH(port, &sc->sc_ports, ports) {
+ TAILQ_INSERT_TAIL(&sc->sc_ports_gone, port,
+ update);
+ if (port->location & QLE_LOCATION_FABRIC) {
+ port->flags |=
+ QLE_PORT_FLAG_NEEDS_LOGIN;
+ }
+ }
+
+ /* take care of ports that haven't changed first */
+ TAILQ_FOREACH(fport, &sc->sc_ports_found, update) {
+ port = sc->sc_targets[fport->loopid];
+ if (port == NULL || fport->port_name !=
+ port->port_name) {
+ /* new or changed port, handled later */
+ continue;
+ }
+
+ /*
+ * the port hasn't been logged out, which
+ * means we don't need to log in again, and,
+ * for loop ports, that the port still exists
+ */
+ port->flags &= ~QLE_PORT_FLAG_NEEDS_LOGIN;
+ if (port->location & QLE_LOCATION_LOOP)
+ TAILQ_REMOVE(&sc->sc_ports_gone,
+ port, update);
+
+ fport->location = 0;
+ }
+ mtx_leave(&sc->sc_port_mtx);
+ qle_update_start(sc, QLE_UPDATE_TASK_PORT_LIST);
+ qle_update_done(sc, QLE_UPDATE_TASK_GET_PORT_LIST);
continue;
}
- if (sc->sc_update_tasks & QLE_UPDATE_TASK_SCANNING_LOOP) {
- DPRINTF(QLE_D_PORT, "%s: scanning loop id %d\n",
- DEVNAME(sc), step);
- qle_add_loop_port(sc, step);
- if (step == sc->sc_loop_max_id) {
+ if (sc->sc_update_tasks & QLE_UPDATE_TASK_PORT_LIST) {
+ mtx_enter(&sc->sc_port_mtx);
+ fport = TAILQ_FIRST(&sc->sc_ports_found);
+ if (fport != NULL) {
+ TAILQ_REMOVE(&sc->sc_ports_found, fport,
+ update);
+ }
+ mtx_leave(&sc->sc_port_mtx);
+
+ if (fport == NULL) {
+ DPRINTF(QLE_D_PORT, "%s: done with ports\n",
+ DEVNAME(sc));
qle_update_done(sc,
- QLE_UPDATE_TASK_SCANNING_LOOP);
+ QLE_UPDATE_TASK_PORT_LIST);
qle_update_start(sc,
QLE_UPDATE_TASK_ATTACH_TARGET |
QLE_UPDATE_TASK_DETACH_TARGET);
+ } else if (fport->location & QLE_LOCATION_LOOP) {
+ DPRINTF(QLE_D_PORT, "%s: loop port %04x\n",
+ DEVNAME(sc), fport->loopid);
+ if (qle_add_loop_port(sc, fport) != 0)
+ free(fport, M_DEVBUF);
+ } else if (fport->location & QLE_LOCATION_FABRIC) {
+ qle_add_fabric_port(sc, fport);
} else {
- step++;
+ /* already processed */
+ free(fport, M_DEVBUF);
}
continue;
}
@@ -2071,11 +2150,8 @@ qle_do_update(void *xsc, void *x)
if (sc->sc_update_tasks & QLE_UPDATE_TASK_SCAN_FABRIC) {
DPRINTF(QLE_D_PORT, "%s: starting fabric scan\n",
DEVNAME(sc));
- qle_clear_port_lists(sc);
- qle_ports_gone(sc, QLE_LOCATION_FABRIC);
lastport = sc->sc_port_id;
firstport = 0xffffffff;
- step = 0;
if (qle_update_fabric(sc))
qle_update_start(sc,
QLE_UPDATE_TASK_SCANNING_FABRIC);
@@ -2085,36 +2161,34 @@ qle_do_update(void *xsc, void *x)
}
if (sc->sc_update_tasks & QLE_UPDATE_TASK_SCANNING_FABRIC) {
- port = qle_next_fabric_port(sc, &firstport, &lastport);
- if (port != NULL) {
- struct qle_fc_port *pport = NULL;
+ fport = qle_next_fabric_port(sc, &firstport, &lastport);
+ if (fport != NULL) {
int disp;
mtx_enter(&sc->sc_port_mtx);
- disp = qle_classify_port(sc, port->location,
- port->port_name, port->node_name, &pport);
+ disp = qle_classify_port(sc, fport->location,
+ fport->port_name, fport->node_name, &port);
switch (disp) {
case QLE_PORT_DISP_CHANGED:
case QLE_PORT_DISP_MOVED:
- /* pport cleaned up later */
+ /* we'll log out the old port later */
case QLE_PORT_DISP_NEW:
DPRINTF(QLE_D_PORT, "%s: new port "
- "%06x\n", DEVNAME(sc), port->portid);
+ "%06x\n", DEVNAME(sc),
+ fport->portid);
TAILQ_INSERT_TAIL(&sc->sc_ports_found,
- port, update);
+ fport, update);
break;
case QLE_PORT_DISP_DUP:
- free(port, M_DEVBUF);
- port = NULL;
+ free(fport, M_DEVBUF);
break;
case QLE_PORT_DISP_SAME:
DPRINTF(QLE_D_PORT, "%s: existing port "
" %06x\n", DEVNAME(sc),
- port->portid);
- TAILQ_REMOVE(&sc->sc_ports_gone, pport,
+ fport->portid);
+ TAILQ_REMOVE(&sc->sc_ports_gone, port,
update);
- free(port, M_DEVBUF);
- port = NULL;
+ free(fport, M_DEVBUF);
break;
}
mtx_leave(&sc->sc_port_mtx);
@@ -2162,10 +2236,69 @@ qle_do_update(void *xsc, void *x)
}
if (sc->sc_update_tasks & QLE_UPDATE_TASK_FABRIC_RELOGIN) {
- /* loop across all fabric targets and redo login */
- qle_update_done(sc, QLE_UPDATE_TASK_FABRIC_RELOGIN);
+ TAILQ_FOREACH(port, &sc->sc_ports, ports) {
+ if (port->flags & QLE_PORT_FLAG_NEEDS_LOGIN) {
+ qle_fabric_plogi(sc, port);
+ break;
+ }
+ }
+
+ if (port == TAILQ_END(&sc->sc_ports))
+ qle_update_done(sc,
+ QLE_UPDATE_TASK_FABRIC_RELOGIN);
+ continue;
+ }
+
+ if (sc->sc_update_tasks & QLE_UPDATE_TASK_DETACH_TARGET) {
+ mtx_enter(&sc->sc_port_mtx);
+ port = TAILQ_FIRST(&sc->sc_ports_gone);
+ if (port != NULL) {
+ sc->sc_targets[port->loopid] = NULL;
+ TAILQ_REMOVE(&sc->sc_ports_gone, port, update);
+ TAILQ_REMOVE(&sc->sc_ports, port, ports);
+ }
+ mtx_leave(&sc->sc_port_mtx);
+
+ if (port != NULL) {
+ DPRINTF(QLE_D_PORT, "%s: detaching port %06x\n",
+ DEVNAME(sc), port->portid);
+ if (sc->sc_scsibus != NULL)
+ scsi_detach_target(sc->sc_scsibus,
+ port->loopid, -1);
+
+ if (port->location & QLE_LOCATION_FABRIC)
+ qle_fabric_plogo(sc, port);
+
+ free(port, M_DEVBUF);
+ } else {
+ DPRINTF(QLE_D_PORT, "%s: nothing to detach\n",
+ DEVNAME(sc));
+ qle_update_done(sc,
+ QLE_UPDATE_TASK_DETACH_TARGET);
+ }
+ continue;
+ }
+
+ if (sc->sc_update_tasks & QLE_UPDATE_TASK_ATTACH_TARGET) {
+ mtx_enter(&sc->sc_port_mtx);
+ port = TAILQ_FIRST(&sc->sc_ports_new);
+ if (port != NULL) {
+ TAILQ_REMOVE(&sc->sc_ports_new, port, update);
+ TAILQ_INSERT_TAIL(&sc->sc_ports, port, ports);
+ }
+ mtx_leave(&sc->sc_port_mtx);
+
+ if (port != NULL) {
+ if (sc->sc_scsibus != NULL)
+ scsi_probe_target(sc->sc_scsibus,
+ port->loopid);
+ } else {
+ qle_update_done(sc,
+ QLE_UPDATE_TASK_ATTACH_TARGET);
+ }
continue;
}
+
}
DPRINTF(QLE_D_PORT, "%s: done updating\n", DEVNAME(sc));
@@ -2196,7 +2329,7 @@ qle_async(struct qle_softc *sc, u_int16_t info)
sc->sc_loop_up = 1;
sc->sc_marker_required = 1;
qle_update_start(sc, QLE_UPDATE_TASK_UPDATE_TOPO |
- QLE_UPDATE_TASK_SCAN_LOOP |
+ QLE_UPDATE_TASK_GET_PORT_LIST |
QLE_UPDATE_TASK_SCAN_FABRIC);
break;
@@ -2215,13 +2348,15 @@ qle_async(struct qle_softc *sc, u_int16_t info)
case QLE_ASYNC_PORT_DB_CHANGE:
DPRINTF(QLE_D_PORT, "%s: port db changed %x\n", DEVNAME(sc),
qle_read_mbox(sc, 1));
- qle_update_start(sc, QLE_UPDATE_TASK_SCAN_LOOP);
+ qle_update_start(sc, QLE_UPDATE_TASK_GET_PORT_LIST |
+ QLE_UPDATE_TASK_SCAN_FABRIC);
break;
case QLE_ASYNC_CHANGE_NOTIFY:
DPRINTF(QLE_D_PORT, "%s: name server change (%02x:%02x)\n",
DEVNAME(sc), qle_read_mbox(sc, 1), qle_read_mbox(sc, 2));
- qle_update_start(sc, QLE_UPDATE_TASK_SCAN_FABRIC);
+ qle_update_start(sc, QLE_UPDATE_TASK_GET_PORT_LIST |
+ QLE_UPDATE_TASK_SCAN_FABRIC);
break;
case QLE_ASYNC_LIP_F8:
diff --git a/sys/dev/pci/qlereg.h b/sys/dev/pci/qlereg.h
index 708105a9a60..74471e91edd 100644
--- a/sys/dev/pci/qlereg.h
+++ b/sys/dev/pci/qlereg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: qlereg.h,v 1.8 2014/04/18 05:08:15 jmatthew Exp $ */
+/* $OpenBSD: qlereg.h,v 1.9 2014/04/20 09:49:23 jmatthew Exp $ */
/*
* Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org>
@@ -351,6 +351,12 @@ struct qle_get_port_db {
u_int8_t reserved3[24];
} __packed __aligned(4);
+struct qle_port_name_list {
+ u_int64_t port_name;
+ u_int16_t loopid;
+ u_int16_t reserved;
+} __packed;
+
#define QLE_SVC3_TARGET_ROLE 0x0010
/* fabric name server commands */