Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/mthca: Add support for automatic path migration (APM)

Add code to modify QP operation to handle setting alternate paths for
connected QPs.

Signed-off-by: Dotan Barak <dotanb@mellanox.co.il>
Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>

authored by

Dotan Barak and committed by
Roland Dreier
4de144bf 0f8e8f96

+37 -20
+37 -20
drivers/infiniband/hw/mthca/mthca_qp.c
··· 549 549 return cpu_to_be32(hw_access_flags); 550 550 } 551 551 552 + static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path) 553 + { 554 + path->g_mylmc = ah->src_path_bits & 0x7f; 555 + path->rlid = cpu_to_be16(ah->dlid); 556 + path->static_rate = !!ah->static_rate; 557 + 558 + if (ah->ah_flags & IB_AH_GRH) { 559 + path->g_mylmc |= 1 << 7; 560 + path->mgid_index = ah->grh.sgid_index; 561 + path->hop_limit = ah->grh.hop_limit; 562 + path->sl_tclass_flowlabel = 563 + cpu_to_be32((ah->sl << 28) | 564 + (ah->grh.traffic_class << 20) | 565 + (ah->grh.flow_label)); 566 + memcpy(path->rgid, ah->grh.dgid.raw, 16); 567 + } else 568 + path->sl_tclass_flowlabel = cpu_to_be32(ah->sl << 28); 569 + } 570 + 552 571 int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) 553 572 { 554 573 struct mthca_dev *dev = to_mdev(ibqp->device); ··· 731 712 } 732 713 733 714 if (attr_mask & IB_QP_RNR_RETRY) { 734 - qp_context->pri_path.rnr_retry = attr->rnr_retry << 5; 735 - qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY); 715 + qp_context->alt_path.rnr_retry = qp_context->pri_path.rnr_retry = 716 + attr->rnr_retry << 5; 717 + qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY | 718 + MTHCA_QP_OPTPAR_ALT_RNR_RETRY); 736 719 } 737 720 738 721 if (attr_mask & IB_QP_AV) { 739 - qp_context->pri_path.g_mylmc = attr->ah_attr.src_path_bits & 0x7f; 740 - qp_context->pri_path.rlid = cpu_to_be16(attr->ah_attr.dlid); 741 - qp_context->pri_path.static_rate = !!attr->ah_attr.static_rate; 742 - if (attr->ah_attr.ah_flags & IB_AH_GRH) { 743 - qp_context->pri_path.g_mylmc |= 1 << 7; 744 - qp_context->pri_path.mgid_index = attr->ah_attr.grh.sgid_index; 745 - qp_context->pri_path.hop_limit = attr->ah_attr.grh.hop_limit; 746 - qp_context->pri_path.sl_tclass_flowlabel = 747 - cpu_to_be32((attr->ah_attr.sl << 28) | 748 - (attr->ah_attr.grh.traffic_class << 20) | 749 - (attr->ah_attr.grh.flow_label)); 750 - memcpy(qp_context->pri_path.rgid, 751 - attr->ah_attr.grh.dgid.raw, 16); 752 - } else { 753 - qp_context->pri_path.sl_tclass_flowlabel = 754 - cpu_to_be32(attr->ah_attr.sl << 28); 755 - } 722 + mthca_path_set(&attr->ah_attr, &qp_context->pri_path); 756 723 qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH); 757 724 } 758 725 ··· 747 742 qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT); 748 743 } 749 744 750 - /* XXX alt_path */ 745 + if (attr_mask & IB_QP_ALT_PATH) { 746 + if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) { 747 + mthca_dbg(dev, "Alternate port number (%u) is invalid\n", 748 + attr->alt_port_num); 749 + return -EINVAL; 750 + } 751 + 752 + mthca_path_set(&attr->alt_ah_attr, &qp_context->alt_path); 753 + qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index | 754 + attr->alt_port_num << 24); 755 + qp_context->alt_path.ackto = attr->alt_timeout << 3; 756 + qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ALT_ADDR_PATH); 757 + } 751 758 752 759 /* leave rdd as 0 */ 753 760 qp_context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pd_num);