IB/cm: Store and restore ah_attr during CM message processing
authorParav Pandit <parav@mellanox.com>
Mon, 14 May 2018 08:11:09 +0000 (11:11 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Wed, 16 May 2018 20:11:46 +0000 (14:11 -0600)
During CM request processing flow, ah_attr is initialized twice.
First based on wc. Secondly based on primary path record.
ah_attr initialization from path record can fail, which leads to ah_attr
zeroed out.

Therefore, always initialize ah_attr on stack during reinitialization
phase. If ah_attr init is successful, use the new ah_attry by
overwriting the old one. If the ah_attr init fails, continue to use the
last ah_attr.

Signed-off-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/core/cm.c

index 8b640cb88f3a876c21985a29ecb069fbfbfc72dc..7df4c7173607ef1a09838a8f0807a3df9e0342d5 100644 (file)
@@ -535,6 +535,7 @@ static struct cm_port *get_cm_port_from_path(struct sa_path_rec *path)
 static int cm_init_av_by_path(struct sa_path_rec *path, struct cm_av *av,
                              struct cm_id_private *cm_id_priv)
 {
+       struct rdma_ah_attr new_ah_attr;
        struct cm_device *cm_dev;
        struct cm_port *port;
        int ret;
@@ -550,15 +551,26 @@ static int cm_init_av_by_path(struct sa_path_rec *path, struct cm_av *av,
                return ret;
 
        av->port = port;
+
+       /*
+        * av->ah_attr might be initialized based on wc or during
+        * request processing time. So initialize a new ah_attr on stack.
+        * If initialization fails, old ah_attr is used for sending any
+        * responses. If initialization is successful, than new ah_attr
+        * is used by overwriting the old one.
+        */
        ret = ib_init_ah_attr_from_path(cm_dev->ib_device, port->port_num, path,
-                                       &av->ah_attr);
+                                       &new_ah_attr);
        if (ret)
                return ret;
 
        av->timeout = path->packet_life_time + 1;
 
        ret = add_cm_id_to_port_list(cm_id_priv, av, port);
-       return ret;
+       if (ret)
+               return ret;
+       memcpy(&av->ah_attr, &new_ah_attr, sizeof(new_ah_attr));
+       return 0;
 }
 
 static int cm_alloc_id(struct cm_id_private *cm_id_priv)