diff options
-rw-r--r-- | drivers/infiniband/core/cm.c | 71 | ||||
-rw-r--r-- | drivers/infiniband/core/cma.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/core/ucm.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_cm.c | 1 | ||||
-rw-r--r-- | include/rdma/ib_cm.h | 1 |
5 files changed, 57 insertions, 18 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 16181d655854..c7007c45889a 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -87,6 +87,7 @@ struct cm_port { | |||
87 | struct cm_device { | 87 | struct cm_device { |
88 | struct list_head list; | 88 | struct list_head list; |
89 | struct ib_device *device; | 89 | struct ib_device *device; |
90 | u8 ack_delay; | ||
90 | struct cm_port port[0]; | 91 | struct cm_port port[0]; |
91 | }; | 92 | }; |
92 | 93 | ||
@@ -95,7 +96,7 @@ struct cm_av { | |||
95 | union ib_gid dgid; | 96 | union ib_gid dgid; |
96 | struct ib_ah_attr ah_attr; | 97 | struct ib_ah_attr ah_attr; |
97 | u16 pkey_index; | 98 | u16 pkey_index; |
98 | u8 packet_life_time; | 99 | u8 timeout; |
99 | }; | 100 | }; |
100 | 101 | ||
101 | struct cm_work { | 102 | struct cm_work { |
@@ -154,6 +155,7 @@ struct cm_id_private { | |||
154 | u8 retry_count; | 155 | u8 retry_count; |
155 | u8 rnr_retry_count; | 156 | u8 rnr_retry_count; |
156 | u8 service_timeout; | 157 | u8 service_timeout; |
158 | u8 target_ack_delay; | ||
157 | 159 | ||
158 | struct list_head work_list; | 160 | struct list_head work_list; |
159 | atomic_t work_count; | 161 | atomic_t work_count; |
@@ -293,7 +295,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av) | |||
293 | av->port = port; | 295 | av->port = port; |
294 | ib_init_ah_from_path(cm_dev->device, port->port_num, path, | 296 | ib_init_ah_from_path(cm_dev->device, port->port_num, path, |
295 | &av->ah_attr); | 297 | &av->ah_attr); |
296 | av->packet_life_time = path->packet_life_time; | 298 | av->timeout = path->packet_life_time + 1; |
297 | return 0; | 299 | return 0; |
298 | } | 300 | } |
299 | 301 | ||
@@ -643,6 +645,25 @@ static inline int cm_convert_to_ms(int iba_time) | |||
643 | return 1 << max(iba_time - 8, 0); | 645 | return 1 << max(iba_time - 8, 0); |
644 | } | 646 | } |
645 | 647 | ||
648 | /* | ||
649 | * calculate: 4.096x2^ack_timeout = 4.096x2^ack_delay + 2x4.096x2^life_time | ||
650 | * Because of how ack_timeout is stored, adding one doubles the timeout. | ||
651 | * To avoid large timeouts, select the max(ack_delay, life_time + 1), and | ||
652 | * increment it (round up) only if the other is within 50%. | ||
653 | */ | ||
654 | static u8 cm_ack_timeout(u8 ca_ack_delay, u8 packet_life_time) | ||
655 | { | ||
656 | int ack_timeout = packet_life_time + 1; | ||
657 | |||
658 | if (ack_timeout >= ca_ack_delay) | ||
659 | ack_timeout += (ca_ack_delay >= (ack_timeout - 1)); | ||
660 | else | ||
661 | ack_timeout = ca_ack_delay + | ||
662 | (ack_timeout >= (ca_ack_delay - 1)); | ||
663 | |||
664 | return min(31, ack_timeout); | ||
665 | } | ||
666 | |||
646 | static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info) | 667 | static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info) |
647 | { | 668 | { |
648 | if (timewait_info->inserted_remote_id) { | 669 | if (timewait_info->inserted_remote_id) { |
@@ -686,7 +707,7 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv) | |||
686 | * timewait before notifying the user that we've exited timewait. | 707 | * timewait before notifying the user that we've exited timewait. |
687 | */ | 708 | */ |
688 | cm_id_priv->id.state = IB_CM_TIMEWAIT; | 709 | cm_id_priv->id.state = IB_CM_TIMEWAIT; |
689 | wait_time = cm_convert_to_ms(cm_id_priv->av.packet_life_time + 1); | 710 | wait_time = cm_convert_to_ms(cm_id_priv->av.timeout); |
690 | queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work, | 711 | queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work, |
691 | msecs_to_jiffies(wait_time)); | 712 | msecs_to_jiffies(wait_time)); |
692 | cm_id_priv->timewait_info = NULL; | 713 | cm_id_priv->timewait_info = NULL; |
@@ -908,7 +929,8 @@ static void cm_format_req(struct cm_req_msg *req_msg, | |||
908 | cm_req_set_primary_sl(req_msg, param->primary_path->sl); | 929 | cm_req_set_primary_sl(req_msg, param->primary_path->sl); |
909 | cm_req_set_primary_subnet_local(req_msg, 1); /* local only... */ | 930 | cm_req_set_primary_subnet_local(req_msg, 1); /* local only... */ |
910 | cm_req_set_primary_local_ack_timeout(req_msg, | 931 | cm_req_set_primary_local_ack_timeout(req_msg, |
911 | min(31, param->primary_path->packet_life_time + 1)); | 932 | cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay, |
933 | param->primary_path->packet_life_time)); | ||
912 | 934 | ||
913 | if (param->alternate_path) { | 935 | if (param->alternate_path) { |
914 | req_msg->alt_local_lid = param->alternate_path->slid; | 936 | req_msg->alt_local_lid = param->alternate_path->slid; |
@@ -923,7 +945,8 @@ static void cm_format_req(struct cm_req_msg *req_msg, | |||
923 | cm_req_set_alt_sl(req_msg, param->alternate_path->sl); | 945 | cm_req_set_alt_sl(req_msg, param->alternate_path->sl); |
924 | cm_req_set_alt_subnet_local(req_msg, 1); /* local only... */ | 946 | cm_req_set_alt_subnet_local(req_msg, 1); /* local only... */ |
925 | cm_req_set_alt_local_ack_timeout(req_msg, | 947 | cm_req_set_alt_local_ack_timeout(req_msg, |
926 | min(31, param->alternate_path->packet_life_time + 1)); | 948 | cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay, |
949 | param->alternate_path->packet_life_time)); | ||
927 | } | 950 | } |
928 | 951 | ||
929 | if (param->private_data && param->private_data_len) | 952 | if (param->private_data && param->private_data_len) |
@@ -1433,7 +1456,8 @@ static void cm_format_rep(struct cm_rep_msg *rep_msg, | |||
1433 | cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn)); | 1456 | cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn)); |
1434 | rep_msg->resp_resources = param->responder_resources; | 1457 | rep_msg->resp_resources = param->responder_resources; |
1435 | rep_msg->initiator_depth = param->initiator_depth; | 1458 | rep_msg->initiator_depth = param->initiator_depth; |
1436 | cm_rep_set_target_ack_delay(rep_msg, param->target_ack_delay); | 1459 | cm_rep_set_target_ack_delay(rep_msg, |
1460 | cm_id_priv->av.port->cm_dev->ack_delay); | ||
1437 | cm_rep_set_failover(rep_msg, param->failover_accepted); | 1461 | cm_rep_set_failover(rep_msg, param->failover_accepted); |
1438 | cm_rep_set_flow_ctrl(rep_msg, param->flow_control); | 1462 | cm_rep_set_flow_ctrl(rep_msg, param->flow_control); |
1439 | cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count); | 1463 | cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count); |
@@ -1680,6 +1704,13 @@ static int cm_rep_handler(struct cm_work *work) | |||
1680 | cm_id_priv->responder_resources = rep_msg->initiator_depth; | 1704 | cm_id_priv->responder_resources = rep_msg->initiator_depth; |
1681 | cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg); | 1705 | cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg); |
1682 | cm_id_priv->rnr_retry_count = cm_rep_get_rnr_retry_count(rep_msg); | 1706 | cm_id_priv->rnr_retry_count = cm_rep_get_rnr_retry_count(rep_msg); |
1707 | cm_id_priv->target_ack_delay = cm_rep_get_target_ack_delay(rep_msg); | ||
1708 | cm_id_priv->av.timeout = | ||
1709 | cm_ack_timeout(cm_id_priv->target_ack_delay, | ||
1710 | cm_id_priv->av.timeout - 1); | ||
1711 | cm_id_priv->alt_av.timeout = | ||
1712 | cm_ack_timeout(cm_id_priv->target_ack_delay, | ||
1713 | cm_id_priv->alt_av.timeout - 1); | ||
1683 | 1714 | ||
1684 | /* todo: handle peer_to_peer */ | 1715 | /* todo: handle peer_to_peer */ |
1685 | 1716 | ||
@@ -2291,7 +2322,7 @@ static int cm_mra_handler(struct cm_work *work) | |||
2291 | work->cm_event.param.mra_rcvd.service_timeout = | 2322 | work->cm_event.param.mra_rcvd.service_timeout = |
2292 | cm_mra_get_service_timeout(mra_msg); | 2323 | cm_mra_get_service_timeout(mra_msg); |
2293 | timeout = cm_convert_to_ms(cm_mra_get_service_timeout(mra_msg)) + | 2324 | timeout = cm_convert_to_ms(cm_mra_get_service_timeout(mra_msg)) + |
2294 | cm_convert_to_ms(cm_id_priv->av.packet_life_time); | 2325 | cm_convert_to_ms(cm_id_priv->av.timeout); |
2295 | 2326 | ||
2296 | spin_lock_irq(&cm_id_priv->lock); | 2327 | spin_lock_irq(&cm_id_priv->lock); |
2297 | switch (cm_id_priv->id.state) { | 2328 | switch (cm_id_priv->id.state) { |
@@ -2363,7 +2394,8 @@ static void cm_format_lap(struct cm_lap_msg *lap_msg, | |||
2363 | cm_lap_set_sl(lap_msg, alternate_path->sl); | 2394 | cm_lap_set_sl(lap_msg, alternate_path->sl); |
2364 | cm_lap_set_subnet_local(lap_msg, 1); /* local only... */ | 2395 | cm_lap_set_subnet_local(lap_msg, 1); /* local only... */ |
2365 | cm_lap_set_local_ack_timeout(lap_msg, | 2396 | cm_lap_set_local_ack_timeout(lap_msg, |
2366 | min(31, alternate_path->packet_life_time + 1)); | 2397 | cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay, |
2398 | alternate_path->packet_life_time)); | ||
2367 | 2399 | ||
2368 | if (private_data && private_data_len) | 2400 | if (private_data && private_data_len) |
2369 | memcpy(lap_msg->private_data, private_data, private_data_len); | 2401 | memcpy(lap_msg->private_data, private_data, private_data_len); |
@@ -2394,6 +2426,9 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id, | |||
2394 | ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av); | 2426 | ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av); |
2395 | if (ret) | 2427 | if (ret) |
2396 | goto out; | 2428 | goto out; |
2429 | cm_id_priv->alt_av.timeout = | ||
2430 | cm_ack_timeout(cm_id_priv->target_ack_delay, | ||
2431 | cm_id_priv->alt_av.timeout - 1); | ||
2397 | 2432 | ||
2398 | ret = cm_alloc_msg(cm_id_priv, &msg); | 2433 | ret = cm_alloc_msg(cm_id_priv, &msg); |
2399 | if (ret) | 2434 | if (ret) |
@@ -3248,8 +3283,7 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv, | |||
3248 | *qp_attr_mask |= IB_QP_ALT_PATH; | 3283 | *qp_attr_mask |= IB_QP_ALT_PATH; |
3249 | qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num; | 3284 | qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num; |
3250 | qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index; | 3285 | qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index; |
3251 | qp_attr->alt_timeout = | 3286 | qp_attr->alt_timeout = cm_id_priv->alt_av.timeout; |
3252 | cm_id_priv->alt_av.packet_life_time + 1; | ||
3253 | qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr; | 3287 | qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr; |
3254 | } | 3288 | } |
3255 | ret = 0; | 3289 | ret = 0; |
@@ -3287,8 +3321,7 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv, | |||
3287 | *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT | | 3321 | *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT | |
3288 | IB_QP_RNR_RETRY | | 3322 | IB_QP_RNR_RETRY | |
3289 | IB_QP_MAX_QP_RD_ATOMIC; | 3323 | IB_QP_MAX_QP_RD_ATOMIC; |
3290 | qp_attr->timeout = | 3324 | qp_attr->timeout = cm_id_priv->av.timeout; |
3291 | cm_id_priv->av.packet_life_time + 1; | ||
3292 | qp_attr->retry_cnt = cm_id_priv->retry_count; | 3325 | qp_attr->retry_cnt = cm_id_priv->retry_count; |
3293 | qp_attr->rnr_retry = cm_id_priv->rnr_retry_count; | 3326 | qp_attr->rnr_retry = cm_id_priv->rnr_retry_count; |
3294 | qp_attr->max_rd_atomic = | 3327 | qp_attr->max_rd_atomic = |
@@ -3302,8 +3335,7 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv, | |||
3302 | *qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE; | 3335 | *qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE; |
3303 | qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num; | 3336 | qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num; |
3304 | qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index; | 3337 | qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index; |
3305 | qp_attr->alt_timeout = | 3338 | qp_attr->alt_timeout = cm_id_priv->alt_av.timeout; |
3306 | cm_id_priv->alt_av.packet_life_time + 1; | ||
3307 | qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr; | 3339 | qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr; |
3308 | qp_attr->path_mig_state = IB_MIG_REARM; | 3340 | qp_attr->path_mig_state = IB_MIG_REARM; |
3309 | } | 3341 | } |
@@ -3343,6 +3375,16 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id, | |||
3343 | } | 3375 | } |
3344 | EXPORT_SYMBOL(ib_cm_init_qp_attr); | 3376 | EXPORT_SYMBOL(ib_cm_init_qp_attr); |
3345 | 3377 | ||
3378 | void cm_get_ack_delay(struct cm_device *cm_dev) | ||
3379 | { | ||
3380 | struct ib_device_attr attr; | ||
3381 | |||
3382 | if (ib_query_device(cm_dev->device, &attr)) | ||
3383 | cm_dev->ack_delay = 0; /* acks will rely on packet life time */ | ||
3384 | else | ||
3385 | cm_dev->ack_delay = attr.local_ca_ack_delay; | ||
3386 | } | ||
3387 | |||
3346 | static void cm_add_one(struct ib_device *device) | 3388 | static void cm_add_one(struct ib_device *device) |
3347 | { | 3389 | { |
3348 | struct cm_device *cm_dev; | 3390 | struct cm_device *cm_dev; |
@@ -3367,6 +3409,7 @@ static void cm_add_one(struct ib_device *device) | |||
3367 | return; | 3409 | return; |
3368 | 3410 | ||
3369 | cm_dev->device = device; | 3411 | cm_dev->device = device; |
3412 | cm_get_ack_delay(cm_dev); | ||
3370 | 3413 | ||
3371 | set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); | 3414 | set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); |
3372 | for (i = 1; i <= device->phys_port_cnt; i++) { | 3415 | for (i = 1; i <= device->phys_port_cnt; i++) { |
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 32a0e66d2a23..23af7a032a03 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -2326,7 +2326,6 @@ static int cma_accept_ib(struct rdma_id_private *id_priv, | |||
2326 | rep.private_data_len = conn_param->private_data_len; | 2326 | rep.private_data_len = conn_param->private_data_len; |
2327 | rep.responder_resources = conn_param->responder_resources; | 2327 | rep.responder_resources = conn_param->responder_resources; |
2328 | rep.initiator_depth = conn_param->initiator_depth; | 2328 | rep.initiator_depth = conn_param->initiator_depth; |
2329 | rep.target_ack_delay = CMA_CM_RESPONSE_TIMEOUT; | ||
2330 | rep.failover_accepted = 0; | 2329 | rep.failover_accepted = 0; |
2331 | rep.flow_control = conn_param->flow_control; | 2330 | rep.flow_control = conn_param->flow_control; |
2332 | rep.rnr_retry_count = conn_param->rnr_retry_count; | 2331 | rep.rnr_retry_count = conn_param->rnr_retry_count; |
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 2586a3ee8eba..424983f5b1ee 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
@@ -823,7 +823,6 @@ static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file, | |||
823 | param.private_data_len = cmd.len; | 823 | param.private_data_len = cmd.len; |
824 | param.responder_resources = cmd.responder_resources; | 824 | param.responder_resources = cmd.responder_resources; |
825 | param.initiator_depth = cmd.initiator_depth; | 825 | param.initiator_depth = cmd.initiator_depth; |
826 | param.target_ack_delay = cmd.target_ack_delay; | ||
827 | param.failover_accepted = cmd.failover_accepted; | 826 | param.failover_accepted = cmd.failover_accepted; |
828 | param.flow_control = cmd.flow_control; | 827 | param.flow_control = cmd.flow_control; |
829 | param.rnr_retry_count = cmd.rnr_retry_count; | 828 | param.rnr_retry_count = cmd.rnr_retry_count; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 6764d216c887..08b4676a3820 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
@@ -281,7 +281,6 @@ static int ipoib_cm_send_rep(struct net_device *dev, struct ib_cm_id *cm_id, | |||
281 | rep.private_data_len = sizeof data; | 281 | rep.private_data_len = sizeof data; |
282 | rep.flow_control = 0; | 282 | rep.flow_control = 0; |
283 | rep.rnr_retry_count = req->rnr_retry_count; | 283 | rep.rnr_retry_count = req->rnr_retry_count; |
284 | rep.target_ack_delay = 20; /* FIXME */ | ||
285 | rep.srq = 1; | 284 | rep.srq = 1; |
286 | rep.qp_num = qp->qp_num; | 285 | rep.qp_num = qp->qp_num; |
287 | rep.starting_psn = psn; | 286 | rep.starting_psn = psn; |
diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h index 5c070176d9ab..12243e80c706 100644 --- a/include/rdma/ib_cm.h +++ b/include/rdma/ib_cm.h | |||
@@ -385,7 +385,6 @@ struct ib_cm_rep_param { | |||
385 | u8 private_data_len; | 385 | u8 private_data_len; |
386 | u8 responder_resources; | 386 | u8 responder_resources; |
387 | u8 initiator_depth; | 387 | u8 initiator_depth; |
388 | u8 target_ack_delay; | ||
389 | u8 failover_accepted; | 388 | u8 failover_accepted; |
390 | u8 flow_control; | 389 | u8 flow_control; |
391 | u8 rnr_retry_count; | 390 | u8 rnr_retry_count; |