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

IB/mlx4: Handle Ethernet L2 parameters for IP based GID addressing

IP based RoCE gids don't store Ethernet L2 parameters, MAC and VLAN.

Therefore, we need to extract them from the CQE and place them in
struct ib_wc (to be used for cases were they were taken from the gid).

Also, when modifying a QP or building address handle, instead of
parsing the dgid to get the MAC and VLAN, take them from the address
handle attributes.

Signed-off-by: Moni Shoua <monis@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>

authored by

Moni Shoua and committed by
Roland Dreier
297e0dad d487ee77

+130 -62
+9 -31
drivers/infiniband/hw/mlx4/ah.c
··· 39 39 40 40 #include "mlx4_ib.h" 41 41 42 - int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr, 43 - u8 *mac, int *is_mcast, u8 port) 44 - { 45 - struct in6_addr in6; 46 - 47 - *is_mcast = 0; 48 - 49 - memcpy(&in6, ah_attr->grh.dgid.raw, sizeof in6); 50 - if (rdma_link_local_addr(&in6)) 51 - rdma_get_ll_mac(&in6, mac); 52 - else if (rdma_is_multicast_addr(&in6)) { 53 - rdma_get_mcast_mac(&in6, mac); 54 - *is_mcast = 1; 55 - } else 56 - return -EINVAL; 57 - 58 - return 0; 59 - } 60 - 61 42 static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr, 62 43 struct mlx4_ib_ah *ah) 63 44 { ··· 73 92 { 74 93 struct mlx4_ib_dev *ibdev = to_mdev(pd->device); 75 94 struct mlx4_dev *dev = ibdev->dev; 76 - union ib_gid sgid; 77 - u8 mac[6]; 78 - int err; 79 95 int is_mcast; 96 + struct in6_addr in6; 80 97 u16 vlan_tag; 81 98 82 - err = mlx4_ib_resolve_grh(ibdev, ah_attr, mac, &is_mcast, ah_attr->port_num); 83 - if (err) 84 - return ERR_PTR(err); 85 - 86 - memcpy(ah->av.eth.mac, mac, 6); 87 - err = ib_get_cached_gid(pd->device, ah_attr->port_num, ah_attr->grh.sgid_index, &sgid); 88 - if (err) 89 - return ERR_PTR(err); 90 - vlan_tag = rdma_get_vlan_id(&sgid); 99 + memcpy(&in6, ah_attr->grh.dgid.raw, sizeof(in6)); 100 + if (rdma_is_multicast_addr(&in6)) { 101 + is_mcast = 1; 102 + rdma_get_mcast_mac(&in6, ah->av.eth.mac); 103 + } else { 104 + memcpy(ah->av.eth.mac, ah_attr->dmac, ETH_ALEN); 105 + } 106 + vlan_tag = ah_attr->vlan_id; 91 107 if (vlan_tag < 0x1000) 92 108 vlan_tag |= (ah_attr->sl & 7) << 13; 93 109 ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
+9
drivers/infiniband/hw/mlx4/cq.c
··· 798 798 wc->sl = be16_to_cpu(cqe->sl_vid) >> 13; 799 799 else 800 800 wc->sl = be16_to_cpu(cqe->sl_vid) >> 12; 801 + if (be32_to_cpu(cqe->vlan_my_qpn) & MLX4_CQE_VLAN_PRESENT_MASK) { 802 + wc->vlan_id = be16_to_cpu(cqe->sl_vid) & 803 + MLX4_CQE_VID_MASK; 804 + } else { 805 + wc->vlan_id = 0xffff; 806 + } 807 + wc->wc_flags |= IB_WC_WITH_VLAN; 808 + memcpy(wc->smac, cqe->smac, ETH_ALEN); 809 + wc->wc_flags |= IB_WC_WITH_SMAC; 801 810 } 802 811 803 812 return 0;
-3
drivers/infiniband/hw/mlx4/mlx4_ib.h
··· 678 678 int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, 679 679 union ib_gid *gid, int netw_view); 680 680 681 - int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr, 682 - u8 *mac, int *is_mcast, u8 port); 683 - 684 681 static inline bool mlx4_ib_ah_grh_present(struct mlx4_ib_ah *ah) 685 682 { 686 683 u8 port = be32_to_cpu(ah->av.ib.port_pd) >> 24 & 3;
+81 -24
drivers/infiniband/hw/mlx4/qp.c
··· 90 90 MLX4_RAW_QP_MSGMAX = 31, 91 91 }; 92 92 93 + #ifndef ETH_ALEN 94 + #define ETH_ALEN 6 95 + #endif 96 + static inline u64 mlx4_mac_to_u64(u8 *addr) 97 + { 98 + u64 mac = 0; 99 + int i; 100 + 101 + for (i = 0; i < ETH_ALEN; i++) { 102 + mac <<= 8; 103 + mac |= addr[i]; 104 + } 105 + return mac; 106 + } 107 + 93 108 static const __be32 mlx4_ib_opcode[] = { 94 109 [IB_WR_SEND] = cpu_to_be32(MLX4_OPCODE_SEND), 95 110 [IB_WR_LSO] = cpu_to_be32(MLX4_OPCODE_LSO), ··· 1159 1144 path->sched_queue = (path->sched_queue & 0xbf) | ((port - 1) << 6); 1160 1145 } 1161 1146 1162 - static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah, 1163 - struct mlx4_qp_path *path, u8 port) 1147 + static int _mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah, 1148 + u64 smac, u16 vlan_tag, struct mlx4_qp_path *path, 1149 + u8 port) 1164 1150 { 1165 - int err; 1166 1151 int is_eth = rdma_port_get_link_layer(&dev->ib_dev, port) == 1167 1152 IB_LINK_LAYER_ETHERNET; 1168 - u8 mac[6]; 1169 - int is_mcast; 1170 - u16 vlan_tag; 1171 1153 int vidx; 1154 + int smac_index; 1155 + 1172 1156 1173 1157 path->grh_mylmc = ah->src_path_bits & 0x7f; 1174 1158 path->rlid = cpu_to_be16(ah->dlid); ··· 1202 1188 if (!(ah->ah_flags & IB_AH_GRH)) 1203 1189 return -1; 1204 1190 1205 - err = mlx4_ib_resolve_grh(dev, ah, mac, &is_mcast, port); 1206 - if (err) 1207 - return err; 1208 - 1209 - memcpy(path->dmac, mac, 6); 1191 + memcpy(path->dmac, ah->dmac, ETH_ALEN); 1210 1192 path->ackto = MLX4_IB_LINK_TYPE_ETH; 1211 - /* use index 0 into MAC table for IBoE */ 1212 - path->grh_mylmc &= 0x80; 1193 + /* find the index into MAC table for IBoE */ 1194 + if (!is_zero_ether_addr((const u8 *)&smac)) { 1195 + if (mlx4_find_cached_mac(dev->dev, port, smac, 1196 + &smac_index)) 1197 + return -ENOENT; 1198 + } else { 1199 + smac_index = 0; 1200 + } 1213 1201 1214 - vlan_tag = rdma_get_vlan_id(&dev->iboe.gid_table[port - 1][ah->grh.sgid_index]); 1202 + path->grh_mylmc &= 0x80 | smac_index; 1203 + 1204 + path->feup |= MLX4_FEUP_FORCE_ETH_UP; 1215 1205 if (vlan_tag < 0x1000) { 1216 1206 if (mlx4_find_cached_vlan(dev->dev, port, vlan_tag, &vidx)) 1217 1207 return -ENOENT; 1218 1208 1219 1209 path->vlan_index = vidx; 1220 1210 path->fl = 1 << 6; 1211 + path->feup |= MLX4_FVL_FORCE_ETH_VLAN; 1221 1212 } 1222 1213 } else 1223 1214 path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | 1224 1215 ((port - 1) << 6) | ((ah->sl & 0xf) << 2); 1225 1216 1226 1217 return 0; 1218 + } 1219 + 1220 + static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_qp_attr *qp, 1221 + enum ib_qp_attr_mask qp_attr_mask, 1222 + struct mlx4_qp_path *path, u8 port) 1223 + { 1224 + return _mlx4_set_path(dev, &qp->ah_attr, 1225 + mlx4_mac_to_u64((u8 *)qp->smac), 1226 + (qp_attr_mask & IB_QP_VID) ? qp->vlan_id : 0xffff, 1227 + path, port); 1228 + } 1229 + 1230 + static int mlx4_set_alt_path(struct mlx4_ib_dev *dev, 1231 + const struct ib_qp_attr *qp, 1232 + enum ib_qp_attr_mask qp_attr_mask, 1233 + struct mlx4_qp_path *path, u8 port) 1234 + { 1235 + return _mlx4_set_path(dev, &qp->alt_ah_attr, 1236 + mlx4_mac_to_u64((u8 *)qp->alt_smac), 1237 + (qp_attr_mask & IB_QP_ALT_VID) ? 1238 + qp->alt_vlan_id : 0xffff, 1239 + path, port); 1227 1240 } 1228 1241 1229 1242 static void update_mcg_macs(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp) ··· 1370 1329 } 1371 1330 1372 1331 if (attr_mask & IB_QP_AV) { 1373 - if (mlx4_set_path(dev, &attr->ah_attr, &context->pri_path, 1332 + if (mlx4_set_path(dev, attr, attr_mask, &context->pri_path, 1374 1333 attr_mask & IB_QP_PORT ? 1375 1334 attr->port_num : qp->port)) 1376 1335 goto out; ··· 1393 1352 dev->dev->caps.pkey_table_len[attr->alt_port_num]) 1394 1353 goto out; 1395 1354 1396 - if (mlx4_set_path(dev, &attr->alt_ah_attr, &context->alt_path, 1397 - attr->alt_port_num)) 1355 + if (mlx4_set_alt_path(dev, attr, attr_mask, &context->alt_path, 1356 + attr->alt_port_num)) 1398 1357 goto out; 1399 1358 1400 1359 context->alt_path.pkey_index = attr->alt_pkey_index; ··· 1505 1464 context->pri_path.ackto = (context->pri_path.ackto & 0xf8) | 1506 1465 MLX4_IB_LINK_TYPE_ETH; 1507 1466 1467 + if (ibqp->qp_type == IB_QPT_UD && (new_state == IB_QPS_RTR)) { 1468 + int is_eth = rdma_port_get_link_layer( 1469 + &dev->ib_dev, qp->port) == 1470 + IB_LINK_LAYER_ETHERNET; 1471 + if (is_eth) { 1472 + context->pri_path.ackto = MLX4_IB_LINK_TYPE_ETH; 1473 + optpar |= MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH; 1474 + } 1475 + } 1476 + 1477 + 1508 1478 if (cur_state == IB_QPS_RTS && new_state == IB_QPS_SQD && 1509 1479 attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY && attr->en_sqd_async_notify) 1510 1480 sqd_event = 1; ··· 1613 1561 struct mlx4_ib_qp *qp = to_mqp(ibqp); 1614 1562 enum ib_qp_state cur_state, new_state; 1615 1563 int err = -EINVAL; 1616 - int p = attr_mask & IB_QP_PORT ? attr->port_num : qp->port; 1564 + int ll; 1617 1565 mutex_lock(&qp->mutex); 1618 1566 1619 1567 cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state; 1620 1568 new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; 1621 1569 1622 - if (cur_state == new_state && cur_state == IB_QPS_RESET) 1623 - p = IB_LINK_LAYER_UNSPECIFIED; 1570 + if (cur_state == new_state && cur_state == IB_QPS_RESET) { 1571 + ll = IB_LINK_LAYER_UNSPECIFIED; 1572 + } else { 1573 + int port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port; 1574 + ll = rdma_port_get_link_layer(&dev->ib_dev, port); 1575 + } 1624 1576 1625 1577 if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, 1626 - attr_mask, 1627 - rdma_port_get_link_layer(&dev->ib_dev, p))) { 1578 + attr_mask, ll)) { 1628 1579 pr_debug("qpn 0x%x: invalid attribute mask specified " 1629 1580 "for transition %d to %d. qp_type %d," 1630 1581 " attr_mask 0x%x\n", ··· 1844 1789 return err; 1845 1790 } 1846 1791 1847 - vlan = rdma_get_vlan_id(&sgid); 1848 - is_vlan = vlan < 0x1000; 1792 + if (ah->av.eth.vlan != 0xffff) { 1793 + vlan = be16_to_cpu(ah->av.eth.vlan) & 0x0fff; 1794 + is_vlan = 1; 1795 + } 1849 1796 } 1850 1797 ib_ud_header_init(send_size, !is_eth, is_eth, is_vlan, is_grh, 0, &sqp->ud_header); 1851 1798
+20
drivers/net/ethernet/mellanox/mlx4/port.c
··· 123 123 return err; 124 124 } 125 125 126 + int mlx4_find_cached_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *idx) 127 + { 128 + struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; 129 + struct mlx4_mac_table *table = &info->mac_table; 130 + int i; 131 + 132 + for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { 133 + if (!table->refs[i]) 134 + continue; 135 + 136 + if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { 137 + *idx = i; 138 + return 0; 139 + } 140 + } 141 + 142 + return -ENOENT; 143 + } 144 + EXPORT_SYMBOL_GPL(mlx4_find_cached_mac); 145 + 126 146 int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 127 147 { 128 148 struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
+11 -4
include/linux/mlx4/cq.h
··· 34 34 #define MLX4_CQ_H 35 35 36 36 #include <linux/types.h> 37 + #include <uapi/linux/if_ether.h> 37 38 38 39 #include <linux/mlx4/device.h> 39 40 #include <linux/mlx4/doorbell.h> ··· 44 43 __be32 immed_rss_invalid; 45 44 __be32 g_mlpath_rqpn; 46 45 __be16 sl_vid; 47 - __be16 rlid; 48 - __be16 status; 49 - u8 ipv6_ext_mask; 50 - u8 badfcs_enc; 46 + union { 47 + struct { 48 + __be16 rlid; 49 + __be16 status; 50 + u8 ipv6_ext_mask; 51 + u8 badfcs_enc; 52 + }; 53 + u8 smac[ETH_ALEN]; 54 + }; 51 55 __be32 byte_cnt; 52 56 __be16 wqe_index; 53 57 __be16 checksum; ··· 89 83 enum { 90 84 MLX4_CQE_VLAN_PRESENT_MASK = 1 << 29, 91 85 MLX4_CQE_QPN_MASK = 0xffffff, 86 + MLX4_CQE_VID_MASK = 0xfff, 92 87 }; 93 88 94 89 enum {