]> git.openfabrics.org - ~shefty/ibacm.git/commitdiff
ibacm: Handle pkey/lid/gid change
authorKaike Wan <kaike.wan@intel.com>
Mon, 9 Jun 2014 22:43:27 +0000 (15:43 -0700)
committerSean Hefty <sean.hefty@intel.com>
Mon, 9 Jun 2014 22:43:27 +0000 (15:43 -0700)
When pkey/lid/gid changes, the endpoint and their addresses will be affected.
As a result, all endpoints will be removed and then added again.
Theoretically, it could selectively modify only those affected endpoints when
key changes. However, since pkey index, which is associated with a QP, may be
changed, the implementation could be very complicated.

Signed-off-by: Kaike Wan <kaike.wan@intel.com>
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
src/acm.c

index 6b2d0e11ae7b57940ffc43701d768b04b7432925..56e398274460b7d7fe451868fb70a3607ab39f0c 100644 (file)
--- a/src/acm.c
+++ b/src/acm.c
@@ -1748,27 +1748,15 @@ err1:
        acm_release_prov_context(dev_ctx);
 }
 
-static void acm_port_down(struct acmc_port *port)
+static void acm_shutdown_port(struct acmc_port *port)
 {
-       struct ibv_port_attr attr;
-       int ret;
        DLIST_ENTRY *entry;
        struct acmc_ep *ep;
        struct acmc_prov_context *dev_ctx;
 
-       acm_log(1, "%s %d\n", port->dev->device.verbs->device->name, 
-               port->port.port_num);
-       ret = ibv_query_port(port->dev->device.verbs, port->port.port_num, &attr);
-       if (!ret && attr.state == IBV_PORT_ACTIVE) {
-               acm_log(1, "port active\n");
-               return;
-       }
-
-       port->state = attr.state;
-
        lock_acquire(&port->lock);
-       for (entry = port->ep_list.Next; entry != &port->ep_list; 
-            entry = port->ep_list.Next) {
+       while (!DListEmpty(&port->ep_list)) {
+               entry = port->ep_list.Next;
                DListRemove(entry);
                lock_release(&port->lock);
                ep = container_of(entry, struct acmc_ep, entry);
@@ -1783,15 +1771,50 @@ static void acm_port_down(struct acmc_port *port)
                dev_ctx = acm_get_prov_context(&port->dev->prov_dev_context_list, 
                                               port->prov);
                if (dev_ctx) {
-                       port->prov->close_device(dev_ctx->context);
+                       if (atomic_get(&dev_ctx->refcnt) == 1)
+                               port->prov->close_device(dev_ctx->context);
                        acm_release_prov_context(dev_ctx);
                }
        }
+       port->prov = NULL;
+}
+
+static void acm_port_down(struct acmc_port *port)
+{
+       struct ibv_port_attr attr;
+       int ret;
+
+       acm_log(1, "%s %d\n", port->port.dev->verbs->device->name, port->port.port_num);
+       ret = ibv_query_port(port->port.dev->verbs, port->port.port_num, &attr);
+       if (!ret && attr.state == IBV_PORT_ACTIVE) {
+               acm_log(1, "port active\n");
+               return;
+       }
+
+       port->state = attr.state;
+       acm_shutdown_port(port);
 
        acm_log(1, "%s %d is down\n", port->dev->device.verbs->device->name, 
                port->port.port_num);
 }
 
+static void acm_port_change(struct acmc_port *port)
+{
+       struct ibv_port_attr attr;
+       int ret;
+
+       acm_log(1, "%s %d\n", port->port.dev->verbs->device->name, port->port.port_num);
+       ret = ibv_query_port(port->port.dev->verbs, port->port.port_num, &attr);
+       if (ret || attr.state != IBV_PORT_ACTIVE) {
+               acm_log(1, "port not active: don't care\n");
+               return;
+       }
+
+       port->state = attr.state;
+       acm_shutdown_port(port);
+       acm_port_up(port);
+}
+
 static void acm_event_handler(struct acmc_device *dev)
 {
        struct ibv_async_event event;
@@ -1824,6 +1847,11 @@ static void acm_event_handler(struct acmc_device *dev)
                                dev->device.verbs->device->name, i + 1);
                }
                break;
+       case IBV_EVENT_LID_CHANGE:
+       case IBV_EVENT_GID_CHANGE:
+       case IBV_EVENT_PKEY_CHANGE:
+               acm_port_change(&dev->port[i]);
+               break;
        default:
                break;
        }