Merge branches 'bkl-removal', 'cma', 'ehca', 'for-2.6.27', 'mlx4', 'mthca' and 'nes...
authorRoland Dreier <rolandd@cisco.com>
Thu, 24 Jul 2008 15:38:47 +0000 (08:38 -0700)
committerRoland Dreier <rolandd@cisco.com>
Thu, 24 Jul 2008 15:38:47 +0000 (08:38 -0700)
14 files changed:
MAINTAINERS
drivers/infiniband/core/cma.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/hw/ehca/ehca_classes.h
drivers/infiniband/hw/ehca/ehca_hca.c
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/infiniband/hw/ehca/ehca_qp.c
drivers/infiniband/hw/ehca/ipz_pt_fn.c
drivers/infiniband/hw/mthca/mthca_dev.h
drivers/infiniband/hw/mthca/mthca_mr.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/iser/iser_verbs.c
include/rdma/rdma_cm.h

index 11944b4..2a73da0 100644 (file)
@@ -2915,8 +2915,6 @@ P:        Faisal Latif
 M:     flatif@neteffect.com
 P:     Chien Tung
 M:     ctung@neteffect.com
-P:     Glenn Streiff
-M:     gstreiff@neteffect.com
 L:     general@lists.openfabrics.org
 W:     http://www.neteffect.com
 S:     Supported
index ae11d5c..e980ff3 100644 (file)
@@ -168,6 +168,12 @@ struct cma_work {
        struct rdma_cm_event    event;
 };
 
+struct cma_ndev_work {
+       struct work_struct      work;
+       struct rdma_id_private  *id;
+       struct rdma_cm_event    event;
+};
+
 union cma_ip_addr {
        struct in6_addr ip6;
        struct {
@@ -914,7 +920,10 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
        struct rdma_cm_event event;
        int ret = 0;
 
-       if (cma_disable_callback(id_priv, CMA_CONNECT))
+       if ((ib_event->event != IB_CM_TIMEWAIT_EXIT &&
+               cma_disable_callback(id_priv, CMA_CONNECT)) ||
+           (ib_event->event == IB_CM_TIMEWAIT_EXIT &&
+               cma_disable_callback(id_priv, CMA_DISCONNECT)))
                return 0;
 
        memset(&event, 0, sizeof event);
@@ -950,6 +959,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
                event.event = RDMA_CM_EVENT_DISCONNECTED;
                break;
        case IB_CM_TIMEWAIT_EXIT:
+               event.event = RDMA_CM_EVENT_TIMEWAIT_EXIT;
+               break;
        case IB_CM_MRA_RECEIVED:
                /* ignore event */
                goto out;
@@ -1598,6 +1609,30 @@ out:
        kfree(work);
 }
 
+static void cma_ndev_work_handler(struct work_struct *_work)
+{
+       struct cma_ndev_work *work = container_of(_work, struct cma_ndev_work, work);
+       struct rdma_id_private *id_priv = work->id;
+       int destroy = 0;
+
+       mutex_lock(&id_priv->handler_mutex);
+       if (id_priv->state == CMA_DESTROYING ||
+           id_priv->state == CMA_DEVICE_REMOVAL)
+               goto out;
+
+       if (id_priv->id.event_handler(&id_priv->id, &work->event)) {
+               cma_exch(id_priv, CMA_DESTROYING);
+               destroy = 1;
+       }
+
+out:
+       mutex_unlock(&id_priv->handler_mutex);
+       cma_deref_id(id_priv);
+       if (destroy)
+               rdma_destroy_id(&id_priv->id);
+       kfree(work);
+}
+
 static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
 {
        struct rdma_route *route = &id_priv->id.route;
@@ -2723,6 +2758,65 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
 }
 EXPORT_SYMBOL(rdma_leave_multicast);
 
+static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id_priv)
+{
+       struct rdma_dev_addr *dev_addr;
+       struct cma_ndev_work *work;
+
+       dev_addr = &id_priv->id.route.addr.dev_addr;
+
+       if ((dev_addr->src_dev == ndev) &&
+           memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) {
+               printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
+                      ndev->name, &id_priv->id);
+               work = kzalloc(sizeof *work, GFP_KERNEL);
+               if (!work)
+                       return -ENOMEM;
+
+               INIT_WORK(&work->work, cma_ndev_work_handler);
+               work->id = id_priv;
+               work->event.event = RDMA_CM_EVENT_ADDR_CHANGE;
+               atomic_inc(&id_priv->refcount);
+               queue_work(cma_wq, &work->work);
+       }
+
+       return 0;
+}
+
+static int cma_netdev_callback(struct notifier_block *self, unsigned long event,
+                              void *ctx)
+{
+       struct net_device *ndev = (struct net_device *)ctx;
+       struct cma_device *cma_dev;
+       struct rdma_id_private *id_priv;
+       int ret = NOTIFY_DONE;
+
+       if (dev_net(ndev) != &init_net)
+               return NOTIFY_DONE;
+
+       if (event != NETDEV_BONDING_FAILOVER)
+               return NOTIFY_DONE;
+
+       if (!(ndev->flags & IFF_MASTER) || !(ndev->priv_flags & IFF_BONDING))
+               return NOTIFY_DONE;
+
+       mutex_lock(&lock);
+       list_for_each_entry(cma_dev, &dev_list, list)
+               list_for_each_entry(id_priv, &cma_dev->id_list, list) {
+                       ret = cma_netdev_change(ndev, id_priv);
+                       if (ret)
+                               goto out;
+               }
+
+out:
+       mutex_unlock(&lock);
+       return ret;
+}
+
+static struct notifier_block cma_nb = {
+       .notifier_call = cma_netdev_callback
+};
+
 static void cma_add_one(struct ib_device *device)
 {
        struct cma_device *cma_dev;
@@ -2831,6 +2925,7 @@ static int cma_init(void)
 
        ib_sa_register_client(&sa_client);
        rdma_addr_register_client(&addr_client);
+       register_netdevice_notifier(&cma_nb);
 
        ret = ib_register_client(&cma_client);
        if (ret)
@@ -2838,6 +2933,7 @@ static int cma_init(void)
        return 0;
 
 err:
+       unregister_netdevice_notifier(&cma_nb);
        rdma_addr_unregister_client(&addr_client);
        ib_sa_unregister_client(&sa_client);
        destroy_workqueue(cma_wq);
@@ -2847,6 +2943,7 @@ err:
 static void cma_cleanup(void)
 {
        ib_unregister_client(&cma_client);
+       unregister_netdevice_notifier(&cma_nb);
        rdma_addr_unregister_client(&addr_client);
        ib_sa_unregister_client(&sa_client);
        destroy_workqueue(cma_wq);
index 81c9195..8f9509e 100644 (file)
@@ -942,8 +942,7 @@ static int iwcm_init_qp_init_attr(struct iwcm_id_private *cm_id_priv,
        case IW_CM_STATE_CONN_RECV:
        case IW_CM_STATE_ESTABLISHED:
                *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
-               qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
-                                          IB_ACCESS_REMOTE_WRITE|
+               qp_attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE|
                                           IB_ACCESS_REMOTE_READ;
                ret = 0;
                break;
index 1341de7..7863a50 100644 (file)
@@ -1064,7 +1064,8 @@ static void ib_sa_remove_one(struct ib_device *device)
 
        for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
                ib_unregister_mad_agent(sa_dev->port[i].agent);
-               kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
+               if (sa_dev->port[i].sm_ah)
+                       kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
        }
 
        kfree(sa_dev);
index 1e9e99a..0b0618e 100644 (file)
@@ -194,6 +194,7 @@ struct ehca_qp {
        u32 packet_count;
        atomic_t nr_events; /* events seen */
        wait_queue_head_t wait_completion;
+       int mig_armed;
 };
 
 #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
index bc3b37d..4628822 100644 (file)
@@ -114,7 +114,9 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
        }
 
        props->max_pkeys           = 16;
-       props->local_ca_ack_delay  = min_t(u8, rblock->local_ca_ack_delay, 255);
+       /* Some FW versions say 0 here; insert sensible value in that case */
+       props->local_ca_ack_delay  = rblock->local_ca_ack_delay ?
+               min_t(u8, rblock->local_ca_ack_delay, 255) : 12;
        props->max_raw_ipv6_qp     = limit_uint(rblock->max_raw_ipv6_qp);
        props->max_raw_ethy_qp     = limit_uint(rblock->max_raw_ethy_qp);
        props->max_mcast_grp       = limit_uint(rblock->max_mcast_grp);
index 0792d93..99642a6 100644 (file)
@@ -178,6 +178,10 @@ static void dispatch_qp_event(struct ehca_shca *shca, struct ehca_qp *qp,
 {
        struct ib_event event;
 
+       /* PATH_MIG without the QP ever having been armed is false alarm */
+       if (event_type == IB_EVENT_PATH_MIG && !qp->mig_armed)
+               return;
+
        event.device = &shca->ib_device;
        event.event = event_type;
 
index 3f59587..ea13efd 100644 (file)
@@ -1460,6 +1460,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
                        goto modify_qp_exit2;
                }
                mqpcb->path_migration_state = attr->path_mig_state + 1;
+               if (attr->path_mig_state == IB_MIG_REARM)
+                       my_qp->mig_armed = 1;
                update_mask |=
                        EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1);
        }
index 661f8db..c3a3284 100644 (file)
@@ -163,6 +163,7 @@ static int alloc_small_queue_page(struct ipz_queue *queue, struct ehca_pd *pd)
 
 out:
        ehca_err(pd->ib_pd.device, "failed to allocate small queue page");
+       mutex_unlock(&pd->lock);
        return 0;
 }
 
index ee4d073..2525901 100644 (file)
@@ -202,6 +202,7 @@ struct mthca_pd_table {
 
 struct mthca_buddy {
        unsigned long **bits;
+       int            *num_free;
        int             max_order;
        spinlock_t      lock;
 };
index 8489b1e..882e6b7 100644 (file)
@@ -89,23 +89,26 @@ static u32 mthca_buddy_alloc(struct mthca_buddy *buddy, int order)
 
        spin_lock(&buddy->lock);
 
-       for (o = order; o <= buddy->max_order; ++o) {
-               m = 1 << (buddy->max_order - o);
-               seg = find_first_bit(buddy->bits[o], m);
-               if (seg < m)
-                       goto found;
-       }
+       for (o = order; o <= buddy->max_order; ++o)
+               if (buddy->num_free[o]) {
+                       m = 1 << (buddy->max_order - o);
+                       seg = find_first_bit(buddy->bits[o], m);
+                       if (seg < m)
+                               goto found;
+               }
 
        spin_unlock(&buddy->lock);
        return -1;
 
  found:
        clear_bit(seg, buddy->bits[o]);
+       --buddy->num_free[o];
 
        while (o > order) {
                --o;
                seg <<= 1;
                set_bit(seg ^ 1, buddy->bits[o]);
+               ++buddy->num_free[o];
        }
 
        spin_unlock(&buddy->lock);
@@ -123,11 +126,13 @@ static void mthca_buddy_free(struct mthca_buddy *buddy, u32 seg, int order)
 
        while (test_bit(seg ^ 1, buddy->bits[order])) {
                clear_bit(seg ^ 1, buddy->bits[order]);
+               --buddy->num_free[order];
                seg >>= 1;
                ++order;
        }
 
        set_bit(seg, buddy->bits[order]);
+       ++buddy->num_free[order];
 
        spin_unlock(&buddy->lock);
 }
@@ -141,7 +146,9 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
 
        buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
                              GFP_KERNEL);
-       if (!buddy->bits)
+       buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+                                 GFP_KERNEL);
+       if (!buddy->bits || !buddy->num_free)
                goto err_out;
 
        for (i = 0; i <= buddy->max_order; ++i) {
@@ -154,6 +161,7 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
        }
 
        set_bit(0, buddy->bits[buddy->max_order]);
+       buddy->num_free[buddy->max_order] = 1;
 
        return 0;
 
@@ -161,9 +169,10 @@ err_out_free:
        for (i = 0; i <= buddy->max_order; ++i)
                kfree(buddy->bits[i]);
 
+err_out:
        kfree(buddy->bits);
+       kfree(buddy->num_free);
 
-err_out:
        return -ENOMEM;
 }
 
@@ -175,6 +184,7 @@ static void mthca_buddy_cleanup(struct mthca_buddy *buddy)
                kfree(buddy->bits[i]);
 
        kfree(buddy->bits);
+       kfree(buddy->num_free);
 }
 
 static u32 mthca_alloc_mtt_range(struct mthca_dev *dev, int order,
index 8be9ea0..f51201b 100644 (file)
@@ -548,7 +548,7 @@ static int path_rec_start(struct net_device *dev,
                                   path_rec_completion,
                                   path, &path->query);
        if (path->query_id < 0) {
-               ipoib_warn(priv, "ib_sa_path_rec_get failed\n");
+               ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id);
                path->query = NULL;
                return path->query_id;
        }
index 3a917c1..63462ec 100644 (file)
@@ -483,6 +483,7 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
                break;
        case RDMA_CM_EVENT_DISCONNECTED:
        case RDMA_CM_EVENT_DEVICE_REMOVAL:
+       case RDMA_CM_EVENT_ADDR_CHANGE:
                iser_disconnected_handler(cma_id);
                break;
        default:
index 22bb2e7..df7faf0 100644 (file)
@@ -57,7 +57,9 @@ enum rdma_cm_event_type {
        RDMA_CM_EVENT_DISCONNECTED,
        RDMA_CM_EVENT_DEVICE_REMOVAL,
        RDMA_CM_EVENT_MULTICAST_JOIN,
-       RDMA_CM_EVENT_MULTICAST_ERROR
+       RDMA_CM_EVENT_MULTICAST_ERROR,
+       RDMA_CM_EVENT_ADDR_CHANGE,
+       RDMA_CM_EVENT_TIMEWAIT_EXIT
 };
 
 enum rdma_port_space {