Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/dtor/input
[pandora-kernel.git] / drivers / infiniband / core / cm.c
index f35fcc4..842cd0b 100644 (file)
@@ -75,6 +75,7 @@ static struct ib_cm {
        struct rb_root remote_sidr_table;
        struct idr local_id_table;
        __be32 random_id_operand;
+       struct list_head timewait_list;
        struct workqueue_struct *wq;
 } cm;
 
@@ -87,7 +88,6 @@ struct cm_port {
 struct cm_device {
        struct list_head list;
        struct ib_device *device;
-       __be64 ca_guid;
        struct cm_port port[0];
 };
 
@@ -100,7 +100,7 @@ struct cm_av {
 };
 
 struct cm_work {
-       struct work_struct work;
+       struct delayed_work work;
        struct list_head list;
        struct cm_port *port;
        struct ib_mad_recv_wc *mad_recv_wc;     /* Received MADs */
@@ -112,6 +112,7 @@ struct cm_work {
 
 struct cm_timewait_info {
        struct cm_work work;                    /* Must be first. */
+       struct list_head list;
        struct rb_node remote_qp_node;
        struct rb_node remote_id_node;
        __be64 remote_ca_guid;
@@ -145,12 +146,12 @@ struct cm_id_private {
        __be32 rq_psn;
        int timeout_ms;
        enum ib_mtu path_mtu;
+       __be16 pkey;
        u8 private_data_len;
        u8 max_cm_retries;
        u8 peer_to_peer;
        u8 responder_resources;
        u8 initiator_depth;
-       u8 local_ack_timeout;
        u8 retry_count;
        u8 rnr_retry_count;
        u8 service_timeout;
@@ -159,7 +160,7 @@ struct cm_id_private {
        atomic_t work_count;
 };
 
-static void cm_work_handler(void *data);
+static void cm_work_handler(struct work_struct *work);
 
 static inline void cm_deref_id(struct cm_id_private *cm_id_priv)
 {
@@ -238,11 +239,10 @@ static void * cm_copy_private_data(const void *private_data,
        if (!private_data || !private_data_len)
                return NULL;
 
-       data = kmalloc(private_data_len, GFP_KERNEL);
+       data = kmemdup(private_data, private_data_len, GFP_KERNEL);
        if (!data)
                return ERR_PTR(-ENOMEM);
 
-       memcpy(data, private_data, private_data_len);
        return data;
 }
 
@@ -647,13 +647,6 @@ static inline int cm_convert_to_ms(int iba_time)
 
 static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
 {
-       unsigned long flags;
-
-       if (!timewait_info->inserted_remote_id &&
-           !timewait_info->inserted_remote_qp)
-           return;
-
-       spin_lock_irqsave(&cm.lock, flags);
        if (timewait_info->inserted_remote_id) {
                rb_erase(&timewait_info->remote_id_node, &cm.remote_id_table);
                timewait_info->inserted_remote_id = 0;
@@ -663,7 +656,6 @@ static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
                rb_erase(&timewait_info->remote_qp_node, &cm.remote_qp_table);
                timewait_info->inserted_remote_qp = 0;
        }
-       spin_unlock_irqrestore(&cm.lock, flags);
 }
 
 static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id)
@@ -675,8 +667,7 @@ static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id)
                return ERR_PTR(-ENOMEM);
 
        timewait_info->work.local_id = local_id;
-       INIT_WORK(&timewait_info->work.work, cm_work_handler,
-                 &timewait_info->work);
+       INIT_DELAYED_WORK(&timewait_info->work.work, cm_work_handler);
        timewait_info->work.cm_event.event = IB_CM_TIMEWAIT_EXIT;
        return timewait_info;
 }
@@ -684,8 +675,12 @@ static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id)
 static void cm_enter_timewait(struct cm_id_private *cm_id_priv)
 {
        int wait_time;
+       unsigned long flags;
 
+       spin_lock_irqsave(&cm.lock, flags);
        cm_cleanup_timewait(cm_id_priv->timewait_info);
+       list_add_tail(&cm_id_priv->timewait_info->list, &cm.timewait_list);
+       spin_unlock_irqrestore(&cm.lock, flags);
 
        /*
         * The cm_id could be destroyed by the user before we exit timewait.
@@ -693,7 +688,7 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv)
         * timewait before notifying the user that we've exited timewait.
         */
        cm_id_priv->id.state = IB_CM_TIMEWAIT;
-       wait_time = cm_convert_to_ms(cm_id_priv->local_ack_timeout);
+       wait_time = cm_convert_to_ms(cm_id_priv->av.packet_life_time + 1);
        queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
                           msecs_to_jiffies(wait_time));
        cm_id_priv->timewait_info = NULL;
@@ -701,9 +696,13 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv)
 
 static void cm_reset_to_idle(struct cm_id_private *cm_id_priv)
 {
+       unsigned long flags;
+
        cm_id_priv->id.state = IB_CM_IDLE;
        if (cm_id_priv->timewait_info) {
+               spin_lock_irqsave(&cm.lock, flags);
                cm_cleanup_timewait(cm_id_priv->timewait_info);
+               spin_unlock_irqrestore(&cm.lock, flags);
                kfree(cm_id_priv->timewait_info);
                cm_id_priv->timewait_info = NULL;
        }
@@ -739,8 +738,8 @@ retest:
                ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
-                              &cm_id_priv->av.port->cm_dev->ca_guid,
-                              sizeof cm_id_priv->av.port->cm_dev->ca_guid,
+                              &cm_id_priv->id.device->node_guid,
+                              sizeof cm_id_priv->id.device->node_guid,
                               NULL, 0);
                break;
        case IB_CM_REQ_RCVD:
@@ -883,7 +882,7 @@ static void cm_format_req(struct cm_req_msg *req_msg,
 
        req_msg->local_comm_id = cm_id_priv->id.local_id;
        req_msg->service_id = param->service_id;
-       req_msg->local_ca_guid = cm_id_priv->av.port->cm_dev->ca_guid;
+       req_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
        cm_req_set_local_qpn(req_msg, cpu_to_be32(param->qp_num));
        cm_req_set_resp_res(req_msg, param->responder_resources);
        cm_req_set_init_depth(req_msg, param->initiator_depth);
@@ -1008,6 +1007,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
        cm_id_priv->responder_resources = param->responder_resources;
        cm_id_priv->retry_count = param->retry_count;
        cm_id_priv->path_mtu = param->primary_path->mtu;
+       cm_id_priv->pkey = param->primary_path->pkey;
        cm_id_priv->qp_type = param->qp_type;
 
        ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg);
@@ -1022,8 +1022,6 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
 
        cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg);
        cm_id_priv->rq_psn = cm_req_get_starting_psn(req_msg);
-       cm_id_priv->local_ack_timeout =
-                               cm_req_get_primary_local_ack_timeout(req_msg);
 
        spin_lock_irqsave(&cm_id_priv->lock, flags);
        ret = ib_post_send_mad(cm_id_priv->msg, NULL);
@@ -1307,6 +1305,7 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
        if (timewait_info) {
                cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
                                           timewait_info->work.remote_id);
+               cm_cleanup_timewait(cm_id_priv->timewait_info);
                spin_unlock_irqrestore(&cm.lock, flags);
                if (cur_cm_id_priv) {
                        cm_dup_req_handler(work, cur_cm_id_priv);
@@ -1315,7 +1314,8 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
                        cm_issue_rej(work->port, work->mad_recv_wc,
                                     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
                                     NULL, 0);
-               goto error;
+               listen_cm_id_priv = NULL;
+               goto out;
        }
 
        /* Find matching listen request. */
@@ -1323,21 +1323,20 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
                                           req_msg->service_id,
                                           req_msg->private_data);
        if (!listen_cm_id_priv) {
+               cm_cleanup_timewait(cm_id_priv->timewait_info);
                spin_unlock_irqrestore(&cm.lock, flags);
                cm_issue_rej(work->port, work->mad_recv_wc,
                             IB_CM_REJ_INVALID_SERVICE_ID, CM_MSG_RESPONSE_REQ,
                             NULL, 0);
-               goto error;
+               goto out;
        }
        atomic_inc(&listen_cm_id_priv->refcount);
        atomic_inc(&cm_id_priv->refcount);
        cm_id_priv->id.state = IB_CM_REQ_RCVD;
        atomic_inc(&cm_id_priv->work_count);
        spin_unlock_irqrestore(&cm.lock, flags);
+out:
        return listen_cm_id_priv;
-
-error: cm_cleanup_timewait(cm_id_priv->timewait_info);
-       return NULL;
 }
 
 static int cm_req_handler(struct cm_work *work)
@@ -1407,9 +1406,8 @@ static int cm_req_handler(struct cm_work *work)
        cm_id_priv->initiator_depth = cm_req_get_resp_res(req_msg);
        cm_id_priv->responder_resources = cm_req_get_init_depth(req_msg);
        cm_id_priv->path_mtu = cm_req_get_path_mtu(req_msg);
+       cm_id_priv->pkey = req_msg->pkey;
        cm_id_priv->sq_psn = cm_req_get_starting_psn(req_msg);
-       cm_id_priv->local_ack_timeout =
-                               cm_req_get_primary_local_ack_timeout(req_msg);
        cm_id_priv->retry_count = cm_req_get_retry_count(req_msg);
        cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);
        cm_id_priv->qp_type = cm_req_get_qp_type(req_msg);
@@ -1443,7 +1441,7 @@ static void cm_format_rep(struct cm_rep_msg *rep_msg,
        cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
        cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
        cm_rep_set_srq(rep_msg, param->srq);
-       rep_msg->local_ca_guid = cm_id_priv->av.port->cm_dev->ca_guid;
+       rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
 
        if (param->private_data && param->private_data_len)
                memcpy(rep_msg->private_data, param->private_data,
@@ -1713,7 +1711,7 @@ static int cm_establish_handler(struct cm_work *work)
        unsigned long flags;
        int ret;
 
-       /* See comment in ib_cm_establish about lookup. */
+       /* See comment in cm_establish about lookup. */
        cm_id_priv = cm_acquire_id(work->local_id, work->remote_id);
        if (!cm_id_priv)
                return -EINVAL;
@@ -1899,6 +1897,32 @@ out:     spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 }
 EXPORT_SYMBOL(ib_send_cm_drep);
 
+static int cm_issue_drep(struct cm_port *port,
+                        struct ib_mad_recv_wc *mad_recv_wc)
+{
+       struct ib_mad_send_buf *msg = NULL;
+       struct cm_dreq_msg *dreq_msg;
+       struct cm_drep_msg *drep_msg;
+       int ret;
+
+       ret = cm_alloc_response_msg(port, mad_recv_wc, &msg);
+       if (ret)
+               return ret;
+
+       dreq_msg = (struct cm_dreq_msg *) mad_recv_wc->recv_buf.mad;
+       drep_msg = (struct cm_drep_msg *) msg->mad;
+
+       cm_format_mad_hdr(&drep_msg->hdr, CM_DREP_ATTR_ID, dreq_msg->hdr.tid);
+       drep_msg->remote_comm_id = dreq_msg->local_comm_id;
+       drep_msg->local_comm_id = dreq_msg->remote_comm_id;
+
+       ret = ib_post_send_mad(msg, NULL);
+       if (ret)
+               cm_free_msg(msg);
+
+       return ret;
+}
+
 static int cm_dreq_handler(struct cm_work *work)
 {
        struct cm_id_private *cm_id_priv;
@@ -1910,8 +1934,10 @@ static int cm_dreq_handler(struct cm_work *work)
        dreq_msg = (struct cm_dreq_msg *)work->mad_recv_wc->recv_buf.mad;
        cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id,
                                   dreq_msg->local_comm_id);
-       if (!cm_id_priv)
+       if (!cm_id_priv) {
+               cm_issue_drep(work->port, work->mad_recv_wc);
                return -EINVAL;
+       }
 
        work->cm_event.private_data = &dreq_msg->private_data;
 
@@ -2371,11 +2397,16 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
        cm_id_priv = container_of(cm_id, struct cm_id_private, id);
        spin_lock_irqsave(&cm_id_priv->lock, flags);
        if (cm_id->state != IB_CM_ESTABLISHED ||
-           cm_id->lap_state != IB_CM_LAP_IDLE) {
+           (cm_id->lap_state != IB_CM_LAP_UNINIT &&
+            cm_id->lap_state != IB_CM_LAP_IDLE)) {
                ret = -EINVAL;
                goto out;
        }
 
+       ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av);
+       if (ret)
+               goto out;
+
        ret = cm_alloc_msg(cm_id_priv, &msg);
        if (ret)
                goto out;
@@ -2400,7 +2431,8 @@ out:      spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 }
 EXPORT_SYMBOL(ib_send_cm_lap);
 
-static void cm_format_path_from_lap(struct ib_sa_path_rec *path,
+static void cm_format_path_from_lap(struct cm_id_private *cm_id_priv,
+                                   struct ib_sa_path_rec *path,
                                    struct cm_lap_msg *lap_msg)
 {
        memset(path, 0, sizeof *path);
@@ -2412,10 +2444,10 @@ static void cm_format_path_from_lap(struct ib_sa_path_rec *path,
        path->hop_limit = lap_msg->alt_hop_limit;
        path->traffic_class = cm_lap_get_traffic_class(lap_msg);
        path->reversible = 1;
-       /* pkey is same as in REQ */
+       path->pkey = cm_id_priv->pkey;
        path->sl = cm_lap_get_sl(lap_msg);
        path->mtu_selector = IB_SA_EQ;
-       /* mtu is same as in REQ */
+       path->mtu = cm_id_priv->path_mtu;
        path->rate_selector = IB_SA_EQ;
        path->rate = cm_lap_get_packet_rate(lap_msg);
        path->packet_life_time_selector = IB_SA_EQ;
@@ -2441,7 +2473,7 @@ static int cm_lap_handler(struct cm_work *work)
 
        param = &work->cm_event.param.lap_rcvd;
        param->alternate_path = &work->path[0];
-       cm_format_path_from_lap(param->alternate_path, lap_msg);
+       cm_format_path_from_lap(cm_id_priv, param->alternate_path, lap_msg);
        work->cm_event.private_data = &lap_msg->private_data;
 
        spin_lock_irqsave(&cm_id_priv->lock, flags);
@@ -2449,6 +2481,7 @@ static int cm_lap_handler(struct cm_work *work)
                goto unlock;
 
        switch (cm_id_priv->id.lap_state) {
+       case IB_CM_LAP_UNINIT:
        case IB_CM_LAP_IDLE:
                break;
        case IB_CM_MRA_LAP_SENT:
@@ -2471,6 +2504,10 @@ static int cm_lap_handler(struct cm_work *work)
 
        cm_id_priv->id.lap_state = IB_CM_LAP_RCVD;
        cm_id_priv->tid = lap_msg->hdr.tid;
+       cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
+                               work->mad_recv_wc->recv_buf.grh,
+                               &cm_id_priv->av);
+       cm_init_av_by_path(param->alternate_path, &cm_id_priv->alt_av);
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -2601,28 +2638,29 @@ static int cm_timewait_handler(struct cm_work *work)
 {
        struct cm_timewait_info *timewait_info;
        struct cm_id_private *cm_id_priv;
-       unsigned long flags;
        int ret;
 
        timewait_info = (struct cm_timewait_info *)work;
-       cm_cleanup_timewait(timewait_info);
+       spin_lock_irq(&cm.lock);
+       list_del(&timewait_info->list);
+       spin_unlock_irq(&cm.lock);
 
        cm_id_priv = cm_acquire_id(timewait_info->work.local_id,
                                   timewait_info->work.remote_id);
        if (!cm_id_priv)
                return -EINVAL;
 
-       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       spin_lock_irq(&cm_id_priv->lock);
        if (cm_id_priv->id.state != IB_CM_TIMEWAIT ||
            cm_id_priv->remote_qpn != timewait_info->remote_qpn) {
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               spin_unlock_irq(&cm_id_priv->lock);
                goto out;
        }
        cm_id_priv->id.state = IB_CM_IDLE;
        ret = atomic_inc_and_test(&cm_id_priv->work_count);
        if (!ret)
                list_add_tail(&work->list, &cm_id_priv->work_list);
-       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       spin_unlock_irq(&cm_id_priv->lock);
 
        if (ret)
                cm_process_work(cm_id_priv, work);
@@ -2955,9 +2993,9 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent,
        }
 }
 
-static void cm_work_handler(void *data)
+static void cm_work_handler(struct work_struct *_work)
 {
-       struct cm_work *work = data;
+       struct cm_work *work = container_of(_work, struct cm_work, work.work);
        int ret;
 
        switch (work->cm_event.event) {
@@ -3008,7 +3046,7 @@ static void cm_work_handler(void *data)
                cm_free_work(work);
 }
 
-int ib_cm_establish(struct ib_cm_id *cm_id)
+static int cm_establish(struct ib_cm_id *cm_id)
 {
        struct cm_id_private *cm_id_priv;
        struct cm_work *work;
@@ -3047,16 +3085,53 @@ int ib_cm_establish(struct ib_cm_id *cm_id)
         * we need to find the cm_id once we're in the context of the
         * worker thread, rather than holding a reference on it.
         */
-       INIT_WORK(&work->work, cm_work_handler, work);
+       INIT_DELAYED_WORK(&work->work, cm_work_handler);
        work->local_id = cm_id->local_id;
        work->remote_id = cm_id->remote_id;
        work->mad_recv_wc = NULL;
        work->cm_event.event = IB_CM_USER_ESTABLISHED;
-       queue_work(cm.wq, &work->work);
+       queue_delayed_work(cm.wq, &work->work, 0);
 out:
        return ret;
 }
-EXPORT_SYMBOL(ib_cm_establish);
+
+static int cm_migrate(struct ib_cm_id *cm_id)
+{
+       struct cm_id_private *cm_id_priv;
+       unsigned long flags;
+       int ret = 0;
+
+       cm_id_priv = container_of(cm_id, struct cm_id_private, id);
+       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       if (cm_id->state == IB_CM_ESTABLISHED &&
+           (cm_id->lap_state == IB_CM_LAP_UNINIT ||
+            cm_id->lap_state == IB_CM_LAP_IDLE)) {
+               cm_id->lap_state = IB_CM_LAP_IDLE;
+               cm_id_priv->av = cm_id_priv->alt_av;
+       } else
+               ret = -EINVAL;
+       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+
+       return ret;
+}
+
+int ib_cm_notify(struct ib_cm_id *cm_id, enum ib_event_type event)
+{
+       int ret;
+
+       switch (event) {
+       case IB_EVENT_COMM_EST:
+               ret = cm_establish(cm_id);
+               break;
+       case IB_EVENT_PATH_MIG:
+               ret = cm_migrate(cm_id);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       return ret;
+}
+EXPORT_SYMBOL(ib_cm_notify);
 
 static void cm_recv_handler(struct ib_mad_agent *mad_agent,
                            struct ib_mad_recv_wc *mad_recv_wc)
@@ -3114,11 +3189,11 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
                return;
        }
 
-       INIT_WORK(&work->work, cm_work_handler, work);
+       INIT_DELAYED_WORK(&work->work, cm_work_handler);
        work->cm_event.event = event;
        work->mad_recv_wc = mad_recv_wc;
        work->port = (struct cm_port *)mad_agent->context;
-       queue_work(cm.wq, &work->work);
+       queue_delayed_work(cm.wq, &work->work, 0);
 }
 
 static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv,
@@ -3141,8 +3216,7 @@ static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv,
        case IB_CM_ESTABLISHED:
                *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS |
                                IB_QP_PKEY_INDEX | IB_QP_PORT;
-               qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
-                                          IB_ACCESS_REMOTE_WRITE;
+               qp_attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE;
                if (cm_id_priv->responder_resources)
                        qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_READ |
                                                    IB_ACCESS_REMOTE_ATOMIC;
@@ -3190,6 +3264,9 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
                if (cm_id_priv->alt_av.ah_attr.dlid) {
                        *qp_attr_mask |= IB_QP_ALT_PATH;
                        qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
+                       qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
+                       qp_attr->alt_timeout =
+                                       cm_id_priv->alt_av.packet_life_time + 1;
                        qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
                }
                ret = 0;
@@ -3211,24 +3288,40 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
 
        spin_lock_irqsave(&cm_id_priv->lock, flags);
        switch (cm_id_priv->id.state) {
+       /* Allow transition to RTS before sending REP */
+       case IB_CM_REQ_RCVD:
+       case IB_CM_MRA_REQ_SENT:
+
        case IB_CM_REP_RCVD:
        case IB_CM_MRA_REP_SENT:
        case IB_CM_REP_SENT:
        case IB_CM_MRA_REP_RCVD:
        case IB_CM_ESTABLISHED:
-               *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
-               qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
-               if (cm_id_priv->qp_type == IB_QPT_RC) {
-                       *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
-                                        IB_QP_RNR_RETRY |
-                                        IB_QP_MAX_QP_RD_ATOMIC;
-                       qp_attr->timeout = cm_id_priv->local_ack_timeout;
-                       qp_attr->retry_cnt = cm_id_priv->retry_count;
-                       qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
-                       qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
-               }
-               if (cm_id_priv->alt_av.ah_attr.dlid) {
-                       *qp_attr_mask |= IB_QP_PATH_MIG_STATE;
+               if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
+                       *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
+                       qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
+                       if (cm_id_priv->qp_type == IB_QPT_RC) {
+                               *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
+                                                IB_QP_RNR_RETRY |
+                                                IB_QP_MAX_QP_RD_ATOMIC;
+                               qp_attr->timeout =
+                                       cm_id_priv->av.packet_life_time + 1;
+                               qp_attr->retry_cnt = cm_id_priv->retry_count;
+                               qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
+                               qp_attr->max_rd_atomic =
+                                       cm_id_priv->initiator_depth;
+                       }
+                       if (cm_id_priv->alt_av.ah_attr.dlid) {
+                               *qp_attr_mask |= IB_QP_PATH_MIG_STATE;
+                               qp_attr->path_mig_state = IB_MIG_REARM;
+                       }
+               } else {
+                       *qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE;
+                       qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
+                       qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
+                       qp_attr->alt_timeout =
+                               cm_id_priv->alt_av.packet_life_time + 1;
+                       qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
                        qp_attr->path_mig_state = IB_MIG_REARM;
                }
                ret = 0;
@@ -3291,7 +3384,6 @@ static void cm_add_one(struct ib_device *device)
                return;
 
        cm_dev->device = device;
-       cm_dev->ca_guid = device->node_guid;
 
        set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
        for (i = 1; i <= device->phys_port_cnt; i++) {
@@ -3374,6 +3466,7 @@ static int __init ib_cm_init(void)
        idr_init(&cm.local_id_table);
        get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand);
        idr_pre_get(&cm.local_id_table, GFP_KERNEL);
+       INIT_LIST_HEAD(&cm.timewait_list);
 
        cm.wq = create_workqueue("ib_cm");
        if (!cm.wq)
@@ -3391,7 +3484,20 @@ error:
 
 static void __exit ib_cm_cleanup(void)
 {
+       struct cm_timewait_info *timewait_info, *tmp;
+
+       spin_lock_irq(&cm.lock);
+       list_for_each_entry(timewait_info, &cm.timewait_list, list)
+               cancel_delayed_work(&timewait_info->work.work);
+       spin_unlock_irq(&cm.lock);
+
        destroy_workqueue(cm.wq);
+
+       list_for_each_entry_safe(timewait_info, tmp, &cm.timewait_list, list) {
+               list_del(&timewait_info->list);
+               kfree(timewait_info);
+       }
+
        ib_unregister_client(&cm_client);
        idr_destroy(&cm.local_id_table);
 }