summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/qle.c85
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",