From: Kaike Wan Date: Mon, 9 Jun 2014 22:43:27 +0000 (-0700) Subject: ibacm: Handle pkey/lid/gid change X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=43da8a949bbf9f0162e5259f906b998e9b800ae1;p=~shefty%2Fibacm.git ibacm: Handle pkey/lid/gid change 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 Signed-off-by: Sean Hefty --- diff --git a/src/acm.c b/src/acm.c index 6b2d0e1..56e3982 100644 --- 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; }