aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/cm.c89
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 */
1463static 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
1444static int cm_req_handler(struct cm_work *work) 1486static 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) {