diff options
-rw-r--r-- | drivers/infiniband/core/cm.c | 89 |
1 files changed, 66 insertions, 23 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index c0150147d347..638b727d42e0 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -974,6 +974,9 @@ static void cm_format_req(struct cm_req_msg *req_msg, | |||
974 | struct cm_id_private *cm_id_priv, | 974 | struct cm_id_private *cm_id_priv, |
975 | struct ib_cm_req_param *param) | 975 | struct ib_cm_req_param *param) |
976 | { | 976 | { |
977 | struct ib_sa_path_rec *pri_path = param->primary_path; | ||
978 | struct ib_sa_path_rec *alt_path = param->alternate_path; | ||
979 | |||
977 | cm_format_mad_hdr(&req_msg->hdr, CM_REQ_ATTR_ID, | 980 | cm_format_mad_hdr(&req_msg->hdr, CM_REQ_ATTR_ID, |
978 | cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_REQ)); | 981 | cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_REQ)); |
979 | 982 | ||
@@ -997,35 +1000,46 @@ static void cm_format_req(struct cm_req_msg *req_msg, | |||
997 | cm_req_set_max_cm_retries(req_msg, param->max_cm_retries); | 1000 | cm_req_set_max_cm_retries(req_msg, param->max_cm_retries); |
998 | cm_req_set_srq(req_msg, param->srq); | 1001 | cm_req_set_srq(req_msg, param->srq); |
999 | 1002 | ||
1000 | req_msg->primary_local_lid = param->primary_path->slid; | 1003 | if (pri_path->hop_limit <= 1) { |
1001 | req_msg->primary_remote_lid = param->primary_path->dlid; | 1004 | req_msg->primary_local_lid = pri_path->slid; |
1002 | req_msg->primary_local_gid = param->primary_path->sgid; | 1005 | req_msg->primary_remote_lid = pri_path->dlid; |
1003 | req_msg->primary_remote_gid = param->primary_path->dgid; | 1006 | } else { |
1004 | cm_req_set_primary_flow_label(req_msg, param->primary_path->flow_label); | 1007 | /* Work-around until there's a way to obtain remote LID info */ |
1005 | cm_req_set_primary_packet_rate(req_msg, param->primary_path->rate); | 1008 | req_msg->primary_local_lid = IB_LID_PERMISSIVE; |
1006 | req_msg->primary_traffic_class = param->primary_path->traffic_class; | 1009 | req_msg->primary_remote_lid = IB_LID_PERMISSIVE; |
1007 | req_msg->primary_hop_limit = param->primary_path->hop_limit; | 1010 | } |
1008 | cm_req_set_primary_sl(req_msg, param->primary_path->sl); | 1011 | req_msg->primary_local_gid = pri_path->sgid; |
1009 | cm_req_set_primary_subnet_local(req_msg, 1); /* local only... */ | 1012 | req_msg->primary_remote_gid = pri_path->dgid; |
1013 | cm_req_set_primary_flow_label(req_msg, pri_path->flow_label); | ||
1014 | cm_req_set_primary_packet_rate(req_msg, pri_path->rate); | ||
1015 | req_msg->primary_traffic_class = pri_path->traffic_class; | ||
1016 | req_msg->primary_hop_limit = pri_path->hop_limit; | ||
1017 | cm_req_set_primary_sl(req_msg, pri_path->sl); | ||
1018 | cm_req_set_primary_subnet_local(req_msg, (pri_path->hop_limit <= 1)); | ||
1010 | cm_req_set_primary_local_ack_timeout(req_msg, | 1019 | cm_req_set_primary_local_ack_timeout(req_msg, |
1011 | cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay, | 1020 | cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay, |
1012 | param->primary_path->packet_life_time)); | 1021 | pri_path->packet_life_time)); |
1013 | 1022 | ||
1014 | if (param->alternate_path) { | 1023 | if (alt_path) { |
1015 | req_msg->alt_local_lid = param->alternate_path->slid; | 1024 | if (alt_path->hop_limit <= 1) { |
1016 | req_msg->alt_remote_lid = param->alternate_path->dlid; | 1025 | req_msg->alt_local_lid = alt_path->slid; |
1017 | req_msg->alt_local_gid = param->alternate_path->sgid; | 1026 | req_msg->alt_remote_lid = alt_path->dlid; |
1018 | req_msg->alt_remote_gid = param->alternate_path->dgid; | 1027 | } else { |
1028 | req_msg->alt_local_lid = IB_LID_PERMISSIVE; | ||
1029 | req_msg->alt_remote_lid = IB_LID_PERMISSIVE; | ||
1030 | } | ||
1031 | req_msg->alt_local_gid = alt_path->sgid; | ||
1032 | req_msg->alt_remote_gid = alt_path->dgid; | ||
1019 | cm_req_set_alt_flow_label(req_msg, | 1033 | cm_req_set_alt_flow_label(req_msg, |
1020 | param->alternate_path->flow_label); | 1034 | alt_path->flow_label); |
1021 | cm_req_set_alt_packet_rate(req_msg, param->alternate_path->rate); | 1035 | cm_req_set_alt_packet_rate(req_msg, alt_path->rate); |
1022 | req_msg->alt_traffic_class = param->alternate_path->traffic_class; | 1036 | req_msg->alt_traffic_class = alt_path->traffic_class; |
1023 | req_msg->alt_hop_limit = param->alternate_path->hop_limit; | 1037 | req_msg->alt_hop_limit = alt_path->hop_limit; |
1024 | cm_req_set_alt_sl(req_msg, param->alternate_path->sl); | 1038 | cm_req_set_alt_sl(req_msg, alt_path->sl); |
1025 | cm_req_set_alt_subnet_local(req_msg, 1); /* local only... */ | 1039 | cm_req_set_alt_subnet_local(req_msg, (alt_path->hop_limit <= 1)); |
1026 | cm_req_set_alt_local_ack_timeout(req_msg, | 1040 | cm_req_set_alt_local_ack_timeout(req_msg, |
1027 | cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay, | 1041 | cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay, |
1028 | param->alternate_path->packet_life_time)); | 1042 | alt_path->packet_life_time)); |
1029 | } | 1043 | } |
1030 | 1044 | ||
1031 | if (param->private_data && param->private_data_len) | 1045 | if (param->private_data && param->private_data_len) |
@@ -1441,6 +1455,34 @@ out: | |||
1441 | return listen_cm_id_priv; | 1455 | return listen_cm_id_priv; |
1442 | } | 1456 | } |
1443 | 1457 | ||
1458 | /* | ||
1459 | * Work-around for inter-subnet connections. If the LIDs are permissive, | ||
1460 | * we need to override the LID/SL data in the REQ with the LID information | ||
1461 | * in the work completion. | ||
1462 | */ | ||
1463 | static void cm_process_routed_req(struct cm_req_msg *req_msg, struct ib_wc *wc) | ||
1464 | { | ||
1465 | if (!cm_req_get_primary_subnet_local(req_msg)) { | ||
1466 | if (req_msg->primary_local_lid == IB_LID_PERMISSIVE) { | ||
1467 | req_msg->primary_local_lid = cpu_to_be16(wc->slid); | ||
1468 | cm_req_set_primary_sl(req_msg, wc->sl); | ||
1469 | } | ||
1470 | |||
1471 | if (req_msg->primary_remote_lid == IB_LID_PERMISSIVE) | ||
1472 | req_msg->primary_remote_lid = cpu_to_be16(wc->dlid_path_bits); | ||
1473 | } | ||
1474 | |||
1475 | if (!cm_req_get_alt_subnet_local(req_msg)) { | ||
1476 | if (req_msg->alt_local_lid == IB_LID_PERMISSIVE) { | ||
1477 | req_msg->alt_local_lid = cpu_to_be16(wc->slid); | ||
1478 | cm_req_set_alt_sl(req_msg, wc->sl); | ||
1479 | } | ||
1480 | |||
1481 | if (req_msg->alt_remote_lid == IB_LID_PERMISSIVE) | ||
1482 | req_msg->alt_remote_lid = cpu_to_be16(wc->dlid_path_bits); | ||
1483 | } | ||
1484 | } | ||
1485 | |||
1444 | static int cm_req_handler(struct cm_work *work) | 1486 | static int cm_req_handler(struct cm_work *work) |
1445 | { | 1487 | { |
1446 | struct ib_cm_id *cm_id; | 1488 | struct ib_cm_id *cm_id; |
@@ -1481,6 +1523,7 @@ static int cm_req_handler(struct cm_work *work) | |||
1481 | cm_id_priv->id.service_id = req_msg->service_id; | 1523 | cm_id_priv->id.service_id = req_msg->service_id; |
1482 | cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL); | 1524 | cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL); |
1483 | 1525 | ||
1526 | cm_process_routed_req(req_msg, work->mad_recv_wc->wc); | ||
1484 | cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]); | 1527 | cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]); |
1485 | ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av); | 1528 | ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av); |
1486 | if (ret) { | 1529 | if (ret) { |