aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2006-11-28 17:57:13 -0500
committerRoland Dreier <rolandd@cisco.com>2006-11-29 18:33:10 -0500
commite1444b5a163e81138754cab27c4fa1637b5a2239 (patch)
tree090ef599a01da78e86d0e527ee3938f96fd0842e /drivers
parent2745b5b713bf3457d8977c62dc2b3aa61f4a14b0 (diff)
IB/cm: Fix automatic path migration support
The ib_cm_establish() function is replaced with a more generic ib_cm_notify(). This routine is used to notify the CM that failover has occurred, so that future CM messages (LAP, DREQ) reach the remote CM. (Currently, we continue to use the original path) This bumps the userspace CM ABI. New alternate path information is captured when a LAP message is sent or received. This allows QP attributes to be initialized for the user when a new path is loaded after failover occurs. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/core/cm.c115
-rw-r--r--drivers/infiniband/core/ucm.c12
2 files changed, 94 insertions, 33 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 78d9c0c33148..e5dc4530808a 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -147,12 +147,12 @@ struct cm_id_private {
147 __be32 rq_psn; 147 __be32 rq_psn;
148 int timeout_ms; 148 int timeout_ms;
149 enum ib_mtu path_mtu; 149 enum ib_mtu path_mtu;
150 __be16 pkey;
150 u8 private_data_len; 151 u8 private_data_len;
151 u8 max_cm_retries; 152 u8 max_cm_retries;
152 u8 peer_to_peer; 153 u8 peer_to_peer;
153 u8 responder_resources; 154 u8 responder_resources;
154 u8 initiator_depth; 155 u8 initiator_depth;
155 u8 local_ack_timeout;
156 u8 retry_count; 156 u8 retry_count;
157 u8 rnr_retry_count; 157 u8 rnr_retry_count;
158 u8 service_timeout; 158 u8 service_timeout;
@@ -690,7 +690,7 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv)
690 * timewait before notifying the user that we've exited timewait. 690 * timewait before notifying the user that we've exited timewait.
691 */ 691 */
692 cm_id_priv->id.state = IB_CM_TIMEWAIT; 692 cm_id_priv->id.state = IB_CM_TIMEWAIT;
693 wait_time = cm_convert_to_ms(cm_id_priv->local_ack_timeout); 693 wait_time = cm_convert_to_ms(cm_id_priv->av.packet_life_time + 1);
694 queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work, 694 queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
695 msecs_to_jiffies(wait_time)); 695 msecs_to_jiffies(wait_time));
696 cm_id_priv->timewait_info = NULL; 696 cm_id_priv->timewait_info = NULL;
@@ -1009,6 +1009,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
1009 cm_id_priv->responder_resources = param->responder_resources; 1009 cm_id_priv->responder_resources = param->responder_resources;
1010 cm_id_priv->retry_count = param->retry_count; 1010 cm_id_priv->retry_count = param->retry_count;
1011 cm_id_priv->path_mtu = param->primary_path->mtu; 1011 cm_id_priv->path_mtu = param->primary_path->mtu;
1012 cm_id_priv->pkey = param->primary_path->pkey;
1012 cm_id_priv->qp_type = param->qp_type; 1013 cm_id_priv->qp_type = param->qp_type;
1013 1014
1014 ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg); 1015 ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg);
@@ -1023,8 +1024,6 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
1023 1024
1024 cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg); 1025 cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg);
1025 cm_id_priv->rq_psn = cm_req_get_starting_psn(req_msg); 1026 cm_id_priv->rq_psn = cm_req_get_starting_psn(req_msg);
1026 cm_id_priv->local_ack_timeout =
1027 cm_req_get_primary_local_ack_timeout(req_msg);
1028 1027
1029 spin_lock_irqsave(&cm_id_priv->lock, flags); 1028 spin_lock_irqsave(&cm_id_priv->lock, flags);
1030 ret = ib_post_send_mad(cm_id_priv->msg, NULL); 1029 ret = ib_post_send_mad(cm_id_priv->msg, NULL);
@@ -1409,9 +1408,8 @@ static int cm_req_handler(struct cm_work *work)
1409 cm_id_priv->initiator_depth = cm_req_get_resp_res(req_msg); 1408 cm_id_priv->initiator_depth = cm_req_get_resp_res(req_msg);
1410 cm_id_priv->responder_resources = cm_req_get_init_depth(req_msg); 1409 cm_id_priv->responder_resources = cm_req_get_init_depth(req_msg);
1411 cm_id_priv->path_mtu = cm_req_get_path_mtu(req_msg); 1410 cm_id_priv->path_mtu = cm_req_get_path_mtu(req_msg);
1411 cm_id_priv->pkey = req_msg->pkey;
1412 cm_id_priv->sq_psn = cm_req_get_starting_psn(req_msg); 1412 cm_id_priv->sq_psn = cm_req_get_starting_psn(req_msg);
1413 cm_id_priv->local_ack_timeout =
1414 cm_req_get_primary_local_ack_timeout(req_msg);
1415 cm_id_priv->retry_count = cm_req_get_retry_count(req_msg); 1413 cm_id_priv->retry_count = cm_req_get_retry_count(req_msg);
1416 cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg); 1414 cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);
1417 cm_id_priv->qp_type = cm_req_get_qp_type(req_msg); 1415 cm_id_priv->qp_type = cm_req_get_qp_type(req_msg);
@@ -1715,7 +1713,7 @@ static int cm_establish_handler(struct cm_work *work)
1715 unsigned long flags; 1713 unsigned long flags;
1716 int ret; 1714 int ret;
1717 1715
1718 /* See comment in ib_cm_establish about lookup. */ 1716 /* See comment in cm_establish about lookup. */
1719 cm_id_priv = cm_acquire_id(work->local_id, work->remote_id); 1717 cm_id_priv = cm_acquire_id(work->local_id, work->remote_id);
1720 if (!cm_id_priv) 1718 if (!cm_id_priv)
1721 return -EINVAL; 1719 return -EINVAL;
@@ -2401,11 +2399,16 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
2401 cm_id_priv = container_of(cm_id, struct cm_id_private, id); 2399 cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2402 spin_lock_irqsave(&cm_id_priv->lock, flags); 2400 spin_lock_irqsave(&cm_id_priv->lock, flags);
2403 if (cm_id->state != IB_CM_ESTABLISHED || 2401 if (cm_id->state != IB_CM_ESTABLISHED ||
2404 cm_id->lap_state != IB_CM_LAP_IDLE) { 2402 (cm_id->lap_state != IB_CM_LAP_UNINIT &&
2403 cm_id->lap_state != IB_CM_LAP_IDLE)) {
2405 ret = -EINVAL; 2404 ret = -EINVAL;
2406 goto out; 2405 goto out;
2407 } 2406 }
2408 2407
2408 ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av);
2409 if (ret)
2410 goto out;
2411
2409 ret = cm_alloc_msg(cm_id_priv, &msg); 2412 ret = cm_alloc_msg(cm_id_priv, &msg);
2410 if (ret) 2413 if (ret)
2411 goto out; 2414 goto out;
@@ -2430,7 +2433,8 @@ out: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2430} 2433}
2431EXPORT_SYMBOL(ib_send_cm_lap); 2434EXPORT_SYMBOL(ib_send_cm_lap);
2432 2435
2433static void cm_format_path_from_lap(struct ib_sa_path_rec *path, 2436static void cm_format_path_from_lap(struct cm_id_private *cm_id_priv,
2437 struct ib_sa_path_rec *path,
2434 struct cm_lap_msg *lap_msg) 2438 struct cm_lap_msg *lap_msg)
2435{ 2439{
2436 memset(path, 0, sizeof *path); 2440 memset(path, 0, sizeof *path);
@@ -2442,10 +2446,10 @@ static void cm_format_path_from_lap(struct ib_sa_path_rec *path,
2442 path->hop_limit = lap_msg->alt_hop_limit; 2446 path->hop_limit = lap_msg->alt_hop_limit;
2443 path->traffic_class = cm_lap_get_traffic_class(lap_msg); 2447 path->traffic_class = cm_lap_get_traffic_class(lap_msg);
2444 path->reversible = 1; 2448 path->reversible = 1;
2445 /* pkey is same as in REQ */ 2449 path->pkey = cm_id_priv->pkey;
2446 path->sl = cm_lap_get_sl(lap_msg); 2450 path->sl = cm_lap_get_sl(lap_msg);
2447 path->mtu_selector = IB_SA_EQ; 2451 path->mtu_selector = IB_SA_EQ;
2448 /* mtu is same as in REQ */ 2452 path->mtu = cm_id_priv->path_mtu;
2449 path->rate_selector = IB_SA_EQ; 2453 path->rate_selector = IB_SA_EQ;
2450 path->rate = cm_lap_get_packet_rate(lap_msg); 2454 path->rate = cm_lap_get_packet_rate(lap_msg);
2451 path->packet_life_time_selector = IB_SA_EQ; 2455 path->packet_life_time_selector = IB_SA_EQ;
@@ -2471,7 +2475,7 @@ static int cm_lap_handler(struct cm_work *work)
2471 2475
2472 param = &work->cm_event.param.lap_rcvd; 2476 param = &work->cm_event.param.lap_rcvd;
2473 param->alternate_path = &work->path[0]; 2477 param->alternate_path = &work->path[0];
2474 cm_format_path_from_lap(param->alternate_path, lap_msg); 2478 cm_format_path_from_lap(cm_id_priv, param->alternate_path, lap_msg);
2475 work->cm_event.private_data = &lap_msg->private_data; 2479 work->cm_event.private_data = &lap_msg->private_data;
2476 2480
2477 spin_lock_irqsave(&cm_id_priv->lock, flags); 2481 spin_lock_irqsave(&cm_id_priv->lock, flags);
@@ -2479,6 +2483,7 @@ static int cm_lap_handler(struct cm_work *work)
2479 goto unlock; 2483 goto unlock;
2480 2484
2481 switch (cm_id_priv->id.lap_state) { 2485 switch (cm_id_priv->id.lap_state) {
2486 case IB_CM_LAP_UNINIT:
2482 case IB_CM_LAP_IDLE: 2487 case IB_CM_LAP_IDLE:
2483 break; 2488 break;
2484 case IB_CM_MRA_LAP_SENT: 2489 case IB_CM_MRA_LAP_SENT:
@@ -2501,6 +2506,10 @@ static int cm_lap_handler(struct cm_work *work)
2501 2506
2502 cm_id_priv->id.lap_state = IB_CM_LAP_RCVD; 2507 cm_id_priv->id.lap_state = IB_CM_LAP_RCVD;
2503 cm_id_priv->tid = lap_msg->hdr.tid; 2508 cm_id_priv->tid = lap_msg->hdr.tid;
2509 cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
2510 work->mad_recv_wc->recv_buf.grh,
2511 &cm_id_priv->av);
2512 cm_init_av_by_path(param->alternate_path, &cm_id_priv->alt_av);
2504 ret = atomic_inc_and_test(&cm_id_priv->work_count); 2513 ret = atomic_inc_and_test(&cm_id_priv->work_count);
2505 if (!ret) 2514 if (!ret)
2506 list_add_tail(&work->list, &cm_id_priv->work_list); 2515 list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -3039,7 +3048,7 @@ static void cm_work_handler(void *data)
3039 cm_free_work(work); 3048 cm_free_work(work);
3040} 3049}
3041 3050
3042int ib_cm_establish(struct ib_cm_id *cm_id) 3051static int cm_establish(struct ib_cm_id *cm_id)
3043{ 3052{
3044 struct cm_id_private *cm_id_priv; 3053 struct cm_id_private *cm_id_priv;
3045 struct cm_work *work; 3054 struct cm_work *work;
@@ -3087,7 +3096,44 @@ int ib_cm_establish(struct ib_cm_id *cm_id)
3087out: 3096out:
3088 return ret; 3097 return ret;
3089} 3098}
3090EXPORT_SYMBOL(ib_cm_establish); 3099
3100static int cm_migrate(struct ib_cm_id *cm_id)
3101{
3102 struct cm_id_private *cm_id_priv;
3103 unsigned long flags;
3104 int ret = 0;
3105
3106 cm_id_priv = container_of(cm_id, struct cm_id_private, id);
3107 spin_lock_irqsave(&cm_id_priv->lock, flags);
3108 if (cm_id->state == IB_CM_ESTABLISHED &&
3109 (cm_id->lap_state == IB_CM_LAP_UNINIT ||
3110 cm_id->lap_state == IB_CM_LAP_IDLE)) {
3111 cm_id->lap_state = IB_CM_LAP_IDLE;
3112 cm_id_priv->av = cm_id_priv->alt_av;
3113 } else
3114 ret = -EINVAL;
3115 spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3116
3117 return ret;
3118}
3119
3120int ib_cm_notify(struct ib_cm_id *cm_id, enum ib_event_type event)
3121{
3122 int ret;
3123
3124 switch (event) {
3125 case IB_EVENT_COMM_EST:
3126 ret = cm_establish(cm_id);
3127 break;
3128 case IB_EVENT_PATH_MIG:
3129 ret = cm_migrate(cm_id);
3130 break;
3131 default:
3132 ret = -EINVAL;
3133 }
3134 return ret;
3135}
3136EXPORT_SYMBOL(ib_cm_notify);
3091 3137
3092static void cm_recv_handler(struct ib_mad_agent *mad_agent, 3138static void cm_recv_handler(struct ib_mad_agent *mad_agent,
3093 struct ib_mad_recv_wc *mad_recv_wc) 3139 struct ib_mad_recv_wc *mad_recv_wc)
@@ -3220,6 +3266,9 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
3220 if (cm_id_priv->alt_av.ah_attr.dlid) { 3266 if (cm_id_priv->alt_av.ah_attr.dlid) {
3221 *qp_attr_mask |= IB_QP_ALT_PATH; 3267 *qp_attr_mask |= IB_QP_ALT_PATH;
3222 qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num; 3268 qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
3269 qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
3270 qp_attr->alt_timeout =
3271 cm_id_priv->alt_av.packet_life_time + 1;
3223 qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr; 3272 qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
3224 } 3273 }
3225 ret = 0; 3274 ret = 0;
@@ -3246,19 +3295,31 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
3246 case IB_CM_REP_SENT: 3295 case IB_CM_REP_SENT:
3247 case IB_CM_MRA_REP_RCVD: 3296 case IB_CM_MRA_REP_RCVD:
3248 case IB_CM_ESTABLISHED: 3297 case IB_CM_ESTABLISHED:
3249 *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN; 3298 if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
3250 qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn); 3299 *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
3251 if (cm_id_priv->qp_type == IB_QPT_RC) { 3300 qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
3252 *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT | 3301 if (cm_id_priv->qp_type == IB_QPT_RC) {
3253 IB_QP_RNR_RETRY | 3302 *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
3254 IB_QP_MAX_QP_RD_ATOMIC; 3303 IB_QP_RNR_RETRY |
3255 qp_attr->timeout = cm_id_priv->local_ack_timeout; 3304 IB_QP_MAX_QP_RD_ATOMIC;
3256 qp_attr->retry_cnt = cm_id_priv->retry_count; 3305 qp_attr->timeout =
3257 qp_attr->rnr_retry = cm_id_priv->rnr_retry_count; 3306 cm_id_priv->av.packet_life_time + 1;
3258 qp_attr->max_rd_atomic = cm_id_priv->initiator_depth; 3307 qp_attr->retry_cnt = cm_id_priv->retry_count;
3259 } 3308 qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
3260 if (cm_id_priv->alt_av.ah_attr.dlid) { 3309 qp_attr->max_rd_atomic =
3261 *qp_attr_mask |= IB_QP_PATH_MIG_STATE; 3310 cm_id_priv->initiator_depth;
3311 }
3312 if (cm_id_priv->alt_av.ah_attr.dlid) {
3313 *qp_attr_mask |= IB_QP_PATH_MIG_STATE;
3314 qp_attr->path_mig_state = IB_MIG_REARM;
3315 }
3316 } else {
3317 *qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE;
3318 qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
3319 qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
3320 qp_attr->alt_timeout =
3321 cm_id_priv->alt_av.packet_life_time + 1;
3322 qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
3262 qp_attr->path_mig_state = IB_MIG_REARM; 3323 qp_attr->path_mig_state = IB_MIG_REARM;
3263 } 3324 }
3264 ret = 0; 3325 ret = 0;
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index b4894ba223b7..1f4f2d2cfa2e 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -683,11 +683,11 @@ out:
683 return result; 683 return result;
684} 684}
685 685
686static ssize_t ib_ucm_establish(struct ib_ucm_file *file, 686static ssize_t ib_ucm_notify(struct ib_ucm_file *file,
687 const char __user *inbuf, 687 const char __user *inbuf,
688 int in_len, int out_len) 688 int in_len, int out_len)
689{ 689{
690 struct ib_ucm_establish cmd; 690 struct ib_ucm_notify cmd;
691 struct ib_ucm_context *ctx; 691 struct ib_ucm_context *ctx;
692 int result; 692 int result;
693 693
@@ -698,7 +698,7 @@ static ssize_t ib_ucm_establish(struct ib_ucm_file *file,
698 if (IS_ERR(ctx)) 698 if (IS_ERR(ctx))
699 return PTR_ERR(ctx); 699 return PTR_ERR(ctx);
700 700
701 result = ib_cm_establish(ctx->cm_id); 701 result = ib_cm_notify(ctx->cm_id, (enum ib_event_type) cmd.event);
702 ib_ucm_ctx_put(ctx); 702 ib_ucm_ctx_put(ctx);
703 return result; 703 return result;
704} 704}
@@ -1105,7 +1105,7 @@ static ssize_t (*ucm_cmd_table[])(struct ib_ucm_file *file,
1105 [IB_USER_CM_CMD_DESTROY_ID] = ib_ucm_destroy_id, 1105 [IB_USER_CM_CMD_DESTROY_ID] = ib_ucm_destroy_id,
1106 [IB_USER_CM_CMD_ATTR_ID] = ib_ucm_attr_id, 1106 [IB_USER_CM_CMD_ATTR_ID] = ib_ucm_attr_id,
1107 [IB_USER_CM_CMD_LISTEN] = ib_ucm_listen, 1107 [IB_USER_CM_CMD_LISTEN] = ib_ucm_listen,
1108 [IB_USER_CM_CMD_ESTABLISH] = ib_ucm_establish, 1108 [IB_USER_CM_CMD_NOTIFY] = ib_ucm_notify,
1109 [IB_USER_CM_CMD_SEND_REQ] = ib_ucm_send_req, 1109 [IB_USER_CM_CMD_SEND_REQ] = ib_ucm_send_req,
1110 [IB_USER_CM_CMD_SEND_REP] = ib_ucm_send_rep, 1110 [IB_USER_CM_CMD_SEND_REP] = ib_ucm_send_rep,
1111 [IB_USER_CM_CMD_SEND_RTU] = ib_ucm_send_rtu, 1111 [IB_USER_CM_CMD_SEND_RTU] = ib_ucm_send_rtu,