aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/cm.c
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2007-12-10 18:53:25 -0500
committerRoland Dreier <rolandd@cisco.com>2008-02-04 23:20:42 -0500
commit3971c9f6dbf26f077b929dbe14ced60a697ebcf0 (patch)
tree005053ac7b0b42f43b296cfc0384bf11567673e3 /drivers/infiniband/core/cm.c
parente8f9b2ed9882874ca96716597bd8c7113289e77b (diff)
IB/cm: Add interim support for routed paths
Paths with hop_limit > 1 indicate that the connection will be routed between IB subnets. Update the subnet local field in the CM REQ based on the hop_limit value. In addition, if the path is routed, then set the LIDs in the REQ to the permissive LIDs. This is used to indicate to the passive side that it should use the LIDs in the received local route header (LRH) associated with the REQ when programming the QP. This is a temporary work-around to the IB CM to support IB router development until the IB router specification is completed. It is not anticipated that this work-around will cause any interoperability issues with existing stacks or future stacks that will properly support IB routers when defined. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/core/cm.c')
-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 c0150147d34..638b727d42e 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) {