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

Merge tag 'mlx5e-updates-2018-12-11' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5e-updates-2018-12-11

From Eli Britstein,
Patches 1-10 adds remote mirroring support.
Patches 1-4 refactor encap related code as pre-steps for using per
destination encapsulation properties.
Patches 5-7 use extended destination feature for single/multi
destination scenarios that have a single encap destination.
Patches 8-10 enable multiple encap destinations for a TC flow.

From, Daniel Jurgens,
Patch 11, Use CQE padding for Ethernet CQs, PPC showed up to a 24%
improvement in small packet throughput

From Eyal Davidovich,
patches 12-14, FW monitor counter support
FW monitor counters feature came to solve the delayed reporting of
FW stats in the atomic get_stats64 ndo, since we can't access the
FW at that stage, this feature will enable immediate FW stats updates
in the driver via fw events on specific stats updates.

Patch 12, cleanup to avoid querying a FW counter when it is not
supported
Patch 13, Monitor counters FW commands support
Patch 14, Use monitor counters in ethernet netdevice to update FW
stats reported in the atomic get_stats64 ndo.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+393 -91
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/Makefile
··· 22 22 # 23 23 mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \ 24 24 en_tx.o en_rx.o en_dim.o en_txrx.o en/xdp.o en_stats.o \ 25 - en_selftest.o en/port.o 25 + en_selftest.o en/port.o en/monitor_stats.o 26 26 27 27 # 28 28 # Netdev extra
+3
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 685 685 struct work_struct set_rx_mode_work; 686 686 struct work_struct tx_timeout_work; 687 687 struct work_struct update_stats_work; 688 + struct work_struct monitor_counters_work; 689 + struct mlx5_nb monitor_counters_nb; 688 690 689 691 struct mlx5_core_dev *mdev; 690 692 struct net_device *netdev; ··· 942 940 void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv); 943 941 int mlx5e_close(struct net_device *netdev); 944 942 int mlx5e_open(struct net_device *netdev); 943 + void mlx5e_update_ndo_stats(struct mlx5e_priv *priv); 945 944 946 945 void mlx5e_queue_update_stats(struct mlx5e_priv *priv); 947 946 int mlx5e_bits_invert(unsigned long a, int size);
+169
drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2018 Mellanox Technologies. */ 3 + 4 + #include "en.h" 5 + #include "monitor_stats.h" 6 + #include "lib/eq.h" 7 + 8 + /* Driver will set the following watch counters list: 9 + * Ppcnt.802_3: 10 + * a_in_range_length_errors Type: 0x0, Counter: 0x0, group_id = N/A 11 + * a_out_of_range_length_field Type: 0x0, Counter: 0x1, group_id = N/A 12 + * a_frame_too_long_errors Type: 0x0, Counter: 0x2, group_id = N/A 13 + * a_frame_check_sequence_errors Type: 0x0, Counter: 0x3, group_id = N/A 14 + * a_alignment_errors Type: 0x0, Counter: 0x4, group_id = N/A 15 + * if_out_discards Type: 0x0, Counter: 0x5, group_id = N/A 16 + * Q_Counters: 17 + * Q[index].rx_out_of_buffer Type: 0x1, Counter: 0x4, group_id = counter_ix 18 + */ 19 + 20 + #define NUM_REQ_PPCNT_COUNTER_S1 MLX5_CMD_SET_MONITOR_NUM_PPCNT_COUNTER_SET1 21 + #define NUM_REQ_Q_COUNTERS_S1 MLX5_CMD_SET_MONITOR_NUM_Q_COUNTERS_SET1 22 + 23 + int mlx5e_monitor_counter_supported(struct mlx5e_priv *priv) 24 + { 25 + struct mlx5_core_dev *mdev = priv->mdev; 26 + 27 + if (!MLX5_CAP_GEN(mdev, max_num_of_monitor_counters)) 28 + return false; 29 + if (MLX5_CAP_PCAM_REG(mdev, ppcnt) && 30 + MLX5_CAP_GEN(mdev, num_ppcnt_monitor_counters) < 31 + NUM_REQ_PPCNT_COUNTER_S1) 32 + return false; 33 + if (MLX5_CAP_GEN(mdev, num_q_monitor_counters) < 34 + NUM_REQ_Q_COUNTERS_S1) 35 + return false; 36 + return true; 37 + } 38 + 39 + void mlx5e_monitor_counter_arm(struct mlx5e_priv *priv) 40 + { 41 + u32 in[MLX5_ST_SZ_DW(arm_monitor_counter_in)] = {}; 42 + u32 out[MLX5_ST_SZ_DW(arm_monitor_counter_out)] = {}; 43 + 44 + MLX5_SET(arm_monitor_counter_in, in, opcode, 45 + MLX5_CMD_OP_ARM_MONITOR_COUNTER); 46 + mlx5_cmd_exec(priv->mdev, in, sizeof(in), out, sizeof(out)); 47 + } 48 + 49 + static void mlx5e_monitor_counters_work(struct work_struct *work) 50 + { 51 + struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv, 52 + monitor_counters_work); 53 + 54 + mutex_lock(&priv->state_lock); 55 + mlx5e_update_ndo_stats(priv); 56 + mutex_unlock(&priv->state_lock); 57 + mlx5e_monitor_counter_arm(priv); 58 + } 59 + 60 + static int mlx5e_monitor_event_handler(struct notifier_block *nb, 61 + unsigned long event, void *eqe) 62 + { 63 + struct mlx5e_priv *priv = mlx5_nb_cof(nb, struct mlx5e_priv, 64 + monitor_counters_nb); 65 + queue_work(priv->wq, &priv->monitor_counters_work); 66 + return NOTIFY_OK; 67 + } 68 + 69 + void mlx5e_monitor_counter_start(struct mlx5e_priv *priv) 70 + { 71 + MLX5_NB_INIT(&priv->monitor_counters_nb, mlx5e_monitor_event_handler, 72 + MONITOR_COUNTER); 73 + mlx5_eq_notifier_register(priv->mdev, &priv->monitor_counters_nb); 74 + } 75 + 76 + static void mlx5e_monitor_counter_stop(struct mlx5e_priv *priv) 77 + { 78 + mlx5_eq_notifier_unregister(priv->mdev, &priv->monitor_counters_nb); 79 + cancel_work_sync(&priv->monitor_counters_work); 80 + } 81 + 82 + static int fill_monitor_counter_ppcnt_set1(int cnt, u32 *in) 83 + { 84 + enum mlx5_monitor_counter_ppcnt ppcnt_cnt; 85 + 86 + for (ppcnt_cnt = 0; 87 + ppcnt_cnt < NUM_REQ_PPCNT_COUNTER_S1; 88 + ppcnt_cnt++, cnt++) { 89 + MLX5_SET(set_monitor_counter_in, in, 90 + monitor_counter[cnt].type, 91 + MLX5_QUERY_MONITOR_CNT_TYPE_PPCNT); 92 + MLX5_SET(set_monitor_counter_in, in, 93 + monitor_counter[cnt].counter, 94 + ppcnt_cnt); 95 + } 96 + return ppcnt_cnt; 97 + } 98 + 99 + static int fill_monitor_counter_q_counter_set1(int cnt, int q_counter, u32 *in) 100 + { 101 + MLX5_SET(set_monitor_counter_in, in, 102 + monitor_counter[cnt].type, 103 + MLX5_QUERY_MONITOR_CNT_TYPE_Q_COUNTER); 104 + MLX5_SET(set_monitor_counter_in, in, 105 + monitor_counter[cnt].counter, 106 + MLX5_QUERY_MONITOR_Q_COUNTER_RX_OUT_OF_BUFFER); 107 + MLX5_SET(set_monitor_counter_in, in, 108 + monitor_counter[cnt].counter_group_id, 109 + q_counter); 110 + return 1; 111 + } 112 + 113 + /* check if mlx5e_monitor_counter_supported before calling this function*/ 114 + static void mlx5e_set_monitor_counter(struct mlx5e_priv *priv) 115 + { 116 + struct mlx5_core_dev *mdev = priv->mdev; 117 + int max_num_of_counters = MLX5_CAP_GEN(mdev, max_num_of_monitor_counters); 118 + int num_q_counters = MLX5_CAP_GEN(mdev, num_q_monitor_counters); 119 + int num_ppcnt_counters = !MLX5_CAP_PCAM_REG(mdev, ppcnt) ? 0 : 120 + MLX5_CAP_GEN(mdev, num_ppcnt_monitor_counters); 121 + u32 in[MLX5_ST_SZ_DW(set_monitor_counter_in)] = {}; 122 + u32 out[MLX5_ST_SZ_DW(set_monitor_counter_out)] = {}; 123 + int q_counter = priv->q_counter; 124 + int cnt = 0; 125 + 126 + if (num_ppcnt_counters >= NUM_REQ_PPCNT_COUNTER_S1 && 127 + max_num_of_counters >= (NUM_REQ_PPCNT_COUNTER_S1 + cnt)) 128 + cnt += fill_monitor_counter_ppcnt_set1(cnt, in); 129 + 130 + if (num_q_counters >= NUM_REQ_Q_COUNTERS_S1 && 131 + max_num_of_counters >= (NUM_REQ_Q_COUNTERS_S1 + cnt) && 132 + q_counter) 133 + cnt += fill_monitor_counter_q_counter_set1(cnt, q_counter, in); 134 + 135 + MLX5_SET(set_monitor_counter_in, in, num_of_counters, cnt); 136 + MLX5_SET(set_monitor_counter_in, in, opcode, 137 + MLX5_CMD_OP_SET_MONITOR_COUNTER); 138 + 139 + mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 140 + } 141 + 142 + /* check if mlx5e_monitor_counter_supported before calling this function*/ 143 + void mlx5e_monitor_counter_init(struct mlx5e_priv *priv) 144 + { 145 + INIT_WORK(&priv->monitor_counters_work, mlx5e_monitor_counters_work); 146 + mlx5e_monitor_counter_start(priv); 147 + mlx5e_set_monitor_counter(priv); 148 + mlx5e_monitor_counter_arm(priv); 149 + queue_work(priv->wq, &priv->update_stats_work); 150 + } 151 + 152 + static void mlx5e_monitor_counter_disable(struct mlx5e_priv *priv) 153 + { 154 + u32 in[MLX5_ST_SZ_DW(set_monitor_counter_in)] = {}; 155 + u32 out[MLX5_ST_SZ_DW(set_monitor_counter_out)] = {}; 156 + 157 + MLX5_SET(set_monitor_counter_in, in, num_of_counters, 0); 158 + MLX5_SET(set_monitor_counter_in, in, opcode, 159 + MLX5_CMD_OP_SET_MONITOR_COUNTER); 160 + 161 + mlx5_cmd_exec(priv->mdev, in, sizeof(in), out, sizeof(out)); 162 + } 163 + 164 + /* check if mlx5e_monitor_counter_supported before calling this function*/ 165 + void mlx5e_monitor_counter_cleanup(struct mlx5e_priv *priv) 166 + { 167 + mlx5e_monitor_counter_disable(priv); 168 + mlx5e_monitor_counter_stop(priv); 169 + }
+12
drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2 + /* Copyright (c) 2018 Mellanox Technologies. */ 3 + 4 + #ifndef __MLX5_MONITOR_H__ 5 + #define __MLX5_MONITOR_H__ 6 + 7 + int mlx5e_monitor_counter_supported(struct mlx5e_priv *priv); 8 + void mlx5e_monitor_counter_init(struct mlx5e_priv *priv); 9 + void mlx5e_monitor_counter_cleanup(struct mlx5e_priv *priv); 10 + void mlx5e_monitor_counter_arm(struct mlx5e_priv *priv); 11 + 12 + #endif /* __MLX5_MONITOR_H__ */
+13 -3
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 50 50 #include "en/port.h" 51 51 #include "en/xdp.h" 52 52 #include "lib/eq.h" 53 + #include "en/monitor_stats.h" 53 54 54 55 struct mlx5e_rq_param { 55 56 u32 rqc[MLX5_ST_SZ_DW(rqc)]; ··· 264 263 mlx5e_stats_grps[i].update_stats(priv); 265 264 } 266 265 267 - static void mlx5e_update_ndo_stats(struct mlx5e_priv *priv) 266 + void mlx5e_update_ndo_stats(struct mlx5e_priv *priv) 268 267 { 269 268 int i; 270 269 ··· 2225 2224 void *cqc = param->cqc; 2226 2225 2227 2226 MLX5_SET(cqc, cqc, uar_page, priv->mdev->priv.uar->index); 2227 + if (MLX5_CAP_GEN(priv->mdev, cqe_128_always) && cache_line_size() >= 128) 2228 + MLX5_SET(cqc, cqc, cqe_sz, CQE_STRIDE_128_PAD); 2228 2229 } 2229 2230 2230 2231 static void mlx5e_build_rx_cq_param(struct mlx5e_priv *priv, ··· 3460 3457 struct mlx5e_vport_stats *vstats = &priv->stats.vport; 3461 3458 struct mlx5e_pport_stats *pstats = &priv->stats.pport; 3462 3459 3463 - /* update HW stats in background for next time */ 3464 - mlx5e_queue_update_stats(priv); 3460 + if (!mlx5e_monitor_counter_supported(priv)) { 3461 + /* update HW stats in background for next time */ 3462 + mlx5e_queue_update_stats(priv); 3463 + } 3465 3464 3466 3465 if (mlx5e_is_uplink_rep(priv)) { 3467 3466 stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok); ··· 4904 4899 mlx5_lag_add(mdev, netdev); 4905 4900 4906 4901 mlx5e_enable_async_events(priv); 4902 + if (mlx5e_monitor_counter_supported(priv)) 4903 + mlx5e_monitor_counter_init(priv); 4907 4904 4908 4905 if (MLX5_ESWITCH_MANAGER(priv->mdev)) 4909 4906 mlx5e_register_vport_reps(priv); ··· 4944 4937 4945 4938 if (MLX5_ESWITCH_MANAGER(priv->mdev)) 4946 4939 mlx5e_unregister_vport_reps(priv); 4940 + 4941 + if (mlx5e_monitor_counter_supported(priv)) 4942 + mlx5e_monitor_counter_cleanup(priv); 4947 4943 4948 4944 mlx5e_disable_async_events(priv); 4949 4945 mlx5_lag_remove(mdev);
+12
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
··· 483 483 return idx; 484 484 } 485 485 486 + #define MLX5_BASIC_PPCNT_SUPPORTED(mdev) \ 487 + (MLX5_CAP_GEN(mdev, pcam_reg) ? MLX5_CAP_PCAM_REG(mdev, ppcnt) : 1) 488 + 486 489 static void mlx5e_grp_802_3_update_stats(struct mlx5e_priv *priv) 487 490 { 488 491 struct mlx5e_pport_stats *pstats = &priv->stats.pport; ··· 493 490 u32 in[MLX5_ST_SZ_DW(ppcnt_reg)] = {0}; 494 491 int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); 495 492 void *out; 493 + 494 + if (!MLX5_BASIC_PPCNT_SUPPORTED(mdev)) 495 + return; 496 496 497 497 MLX5_SET(ppcnt_reg, in, local_port, 1); 498 498 out = pstats->IEEE_802_3_counters; ··· 608 602 u32 in[MLX5_ST_SZ_DW(ppcnt_reg)] = {0}; 609 603 int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); 610 604 void *out; 605 + 606 + if (!MLX5_BASIC_PPCNT_SUPPORTED(mdev)) 607 + return; 611 608 612 609 MLX5_SET(ppcnt_reg, in, local_port, 1); 613 610 out = pstats->RFC_2819_counters; ··· 1086 1077 int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); 1087 1078 int prio; 1088 1079 void *out; 1080 + 1081 + if (!MLX5_BASIC_PPCNT_SUPPORTED(mdev)) 1082 + return; 1089 1083 1090 1084 MLX5_SET(ppcnt_reg, in, local_port, 1); 1091 1085 MLX5_SET(ppcnt_reg, in, grp, MLX5_PER_PRIORITY_COUNTERS_GROUP);
+125 -56
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
··· 78 78 79 79 #define MLX5E_TC_MAX_SPLITS 1 80 80 81 + /* Helper struct for accessing a struct containing list_head array. 82 + * Containing struct 83 + * |- Helper array 84 + * [0] Helper item 0 85 + * |- list_head item 0 86 + * |- index (0) 87 + * [1] Helper item 1 88 + * |- list_head item 1 89 + * |- index (1) 90 + * To access the containing struct from one of the list_head items: 91 + * 1. Get the helper item from the list_head item using 92 + * helper item = 93 + * container_of(list_head item, helper struct type, list_head field) 94 + * 2. Get the contining struct from the helper item and its index in the array: 95 + * containing struct = 96 + * container_of(helper item, containing struct type, helper field[index]) 97 + */ 98 + struct encap_flow_item { 99 + struct list_head list; 100 + int index; 101 + }; 102 + 81 103 struct mlx5e_tc_flow { 82 104 struct rhash_head node; 83 105 struct mlx5e_priv *priv; 84 106 u64 cookie; 85 107 u16 flags; 86 108 struct mlx5_flow_handle *rule[MLX5E_TC_MAX_SPLITS + 1]; 87 - struct list_head encap; /* flows sharing the same encap ID */ 109 + /* Flow can be associated with multiple encap IDs. 110 + * The number of encaps is bounded by the number of supported 111 + * destinations. 112 + */ 113 + struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS]; 88 114 struct list_head mod_hdr; /* flows sharing the same mod hdr ID */ 89 115 struct list_head hairpin; /* flows sharing the same hairpin */ 90 116 union { ··· 120 94 }; 121 95 122 96 struct mlx5e_tc_flow_parse_attr { 123 - struct ip_tunnel_info tun_info; 97 + struct ip_tunnel_info tun_info[MLX5_MAX_FLOW_FWD_VPORTS]; 124 98 struct net_device *filter_dev; 125 99 struct mlx5_flow_spec spec; 126 100 int num_mod_hdr_actions; 127 101 void *mod_hdr_actions; 128 - int mirred_ifindex; 102 + int mirred_ifindex[MLX5_MAX_FLOW_FWD_VPORTS]; 129 103 }; 130 104 131 105 #define MLX5E_TC_TABLE_NUM_GROUPS 4 ··· 597 571 struct mlx5e_tc_flow_parse_attr *parse_attr, 598 572 struct netlink_ext_ack *extack) 599 573 { 600 - int peer_ifindex = parse_attr->mirred_ifindex; 574 + int peer_ifindex = parse_attr->mirred_ifindex[0]; 601 575 struct mlx5_hairpin_params params; 602 576 struct mlx5_core_dev *peer_mdev; 603 577 struct mlx5e_hairpin_entry *hpe; ··· 843 817 } 844 818 845 819 static void mlx5e_detach_encap(struct mlx5e_priv *priv, 846 - struct mlx5e_tc_flow *flow); 820 + struct mlx5e_tc_flow *flow, int out_index); 847 821 848 822 static int mlx5e_attach_encap(struct mlx5e_priv *priv, 849 823 struct ip_tunnel_info *tun_info, 850 824 struct net_device *mirred_dev, 851 825 struct net_device **encap_dev, 852 826 struct mlx5e_tc_flow *flow, 853 - struct netlink_ext_ack *extack); 827 + struct netlink_ext_ack *extack, 828 + int out_index); 854 829 855 830 static struct mlx5_flow_handle * 856 831 mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw, ··· 865 838 if (IS_ERR(rule)) 866 839 return rule; 867 840 868 - if (attr->mirror_count) { 841 + if (attr->split_count) { 869 842 flow->rule[1] = mlx5_eswitch_add_fwd_rule(esw, spec, attr); 870 843 if (IS_ERR(flow->rule[1])) { 871 844 mlx5_eswitch_del_offloaded_rule(esw, rule, attr); ··· 884 857 { 885 858 flow->flags &= ~MLX5E_TC_FLOW_OFFLOADED; 886 859 887 - if (attr->mirror_count) 860 + if (attr->split_count) 888 861 mlx5_eswitch_del_fwd_rule(esw, flow->rule[1], attr); 889 862 890 863 mlx5_eswitch_del_offloaded_rule(esw, flow->rule[0], attr); ··· 900 873 901 874 memcpy(slow_attr, flow->esw_attr, sizeof(*slow_attr)); 902 875 slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, 903 - slow_attr->mirror_count = 0, 876 + slow_attr->split_count = 0, 904 877 slow_attr->dest_chain = FDB_SLOW_PATH_CHAIN, 905 878 906 879 rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, slow_attr); ··· 935 908 struct mlx5e_rep_priv *rpriv; 936 909 struct mlx5e_priv *out_priv; 937 910 int err = 0, encap_err = 0; 911 + int out_index; 938 912 939 913 /* if prios are not supported, keep the old behaviour of using same prio 940 914 * for all offloaded rules. ··· 955 927 goto err_max_prio_chain; 956 928 } 957 929 958 - if (attr->action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) { 930 + for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) { 931 + int mirred_ifindex; 932 + 933 + if (!(attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) 934 + continue; 935 + 936 + mirred_ifindex = attr->parse_attr->mirred_ifindex[out_index]; 959 937 out_dev = __dev_get_by_index(dev_net(priv->netdev), 960 - attr->parse_attr->mirred_ifindex); 961 - encap_err = mlx5e_attach_encap(priv, &parse_attr->tun_info, 962 - out_dev, &encap_dev, flow, 963 - extack); 964 - if (encap_err && encap_err != -EAGAIN) { 965 - err = encap_err; 938 + mirred_ifindex); 939 + err = mlx5e_attach_encap(priv, 940 + &parse_attr->tun_info[out_index], 941 + out_dev, &encap_dev, flow, 942 + extack, out_index); 943 + if (err && err != -EAGAIN) 966 944 goto err_attach_encap; 967 - } 945 + if (err == -EAGAIN) 946 + encap_err = err; 968 947 out_priv = netdev_priv(encap_dev); 969 948 rpriv = out_priv->ppriv; 970 - attr->out_rep[attr->out_count] = rpriv->rep; 971 - attr->out_mdev[attr->out_count++] = out_priv->mdev; 949 + attr->dests[out_index].rep = rpriv->rep; 950 + attr->dests[out_index].mdev = out_priv->mdev; 972 951 } 973 952 974 953 err = mlx5_eswitch_add_vlan_action(esw, attr); ··· 1026 991 err_mod_hdr: 1027 992 mlx5_eswitch_del_vlan_action(esw, attr); 1028 993 err_add_vlan: 1029 - if (attr->action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) 1030 - mlx5e_detach_encap(priv, flow); 994 + for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) 995 + if (attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP) 996 + mlx5e_detach_encap(priv, flow, out_index); 1031 997 err_attach_encap: 1032 998 err_max_prio_chain: 1033 999 return err; ··· 1040 1004 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1041 1005 struct mlx5_esw_flow_attr *attr = flow->esw_attr; 1042 1006 struct mlx5_esw_flow_attr slow_attr; 1007 + int out_index; 1043 1008 1044 1009 if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) { 1045 1010 if (flow->flags & MLX5E_TC_FLOW_SLOW) ··· 1051 1014 1052 1015 mlx5_eswitch_del_vlan_action(esw, attr); 1053 1016 1054 - if (attr->action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) { 1055 - mlx5e_detach_encap(priv, flow); 1056 - kvfree(attr->parse_attr); 1057 - } 1017 + for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) 1018 + if (attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP) 1019 + mlx5e_detach_encap(priv, flow, out_index); 1020 + kvfree(attr->parse_attr); 1058 1021 1059 1022 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) 1060 1023 mlx5e_detach_mod_hdr(priv, flow); ··· 1070 1033 struct mlx5_esw_flow_attr slow_attr, *esw_attr; 1071 1034 struct mlx5_flow_handle *rule; 1072 1035 struct mlx5_flow_spec *spec; 1036 + struct encap_flow_item *efi; 1073 1037 struct mlx5e_tc_flow *flow; 1074 1038 int err; 1075 1039 ··· 1087 1049 e->flags |= MLX5_ENCAP_ENTRY_VALID; 1088 1050 mlx5e_rep_queue_neigh_stats_work(priv); 1089 1051 1090 - list_for_each_entry(flow, &e->flows, encap) { 1052 + list_for_each_entry(efi, &e->flows, list) { 1053 + bool all_flow_encaps_valid = true; 1054 + int i; 1055 + 1056 + flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); 1091 1057 esw_attr = flow->esw_attr; 1092 - esw_attr->encap_id = e->encap_id; 1093 1058 spec = &esw_attr->parse_attr->spec; 1094 1059 1060 + esw_attr->dests[efi->index].encap_id = e->encap_id; 1061 + esw_attr->dests[efi->index].flags |= MLX5_ESW_DEST_ENCAP_VALID; 1062 + /* Flow can be associated with multiple encap entries. 1063 + * Before offloading the flow verify that all of them have 1064 + * a valid neighbour. 1065 + */ 1066 + for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) { 1067 + if (!(esw_attr->dests[i].flags & MLX5_ESW_DEST_ENCAP)) 1068 + continue; 1069 + if (!(esw_attr->dests[i].flags & MLX5_ESW_DEST_ENCAP_VALID)) { 1070 + all_flow_encaps_valid = false; 1071 + break; 1072 + } 1073 + } 1074 + /* Do not offload flows with unresolved neighbors */ 1075 + if (!all_flow_encaps_valid) 1076 + continue; 1095 1077 /* update from slow path rule to encap rule */ 1096 1078 rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, esw_attr); 1097 1079 if (IS_ERR(rule)) { ··· 1134 1076 struct mlx5_esw_flow_attr slow_attr; 1135 1077 struct mlx5_flow_handle *rule; 1136 1078 struct mlx5_flow_spec *spec; 1079 + struct encap_flow_item *efi; 1137 1080 struct mlx5e_tc_flow *flow; 1138 1081 int err; 1139 1082 1140 - list_for_each_entry(flow, &e->flows, encap) { 1083 + list_for_each_entry(efi, &e->flows, list) { 1084 + flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); 1141 1085 spec = &flow->esw_attr->parse_attr->spec; 1142 1086 1143 1087 /* update from encap rule to slow path rule */ 1144 1088 rule = mlx5e_tc_offload_to_slow_path(esw, flow, spec, &slow_attr); 1089 + /* mark the flow's encap dest as non-valid */ 1090 + flow->esw_attr->dests[efi->index].flags &= ~MLX5_ESW_DEST_ENCAP_VALID; 1145 1091 1146 1092 if (IS_ERR(rule)) { 1147 1093 err = PTR_ERR(rule); ··· 1194 1132 return; 1195 1133 1196 1134 list_for_each_entry(e, &nhe->encap_list, encap_list) { 1135 + struct encap_flow_item *efi; 1197 1136 if (!(e->flags & MLX5_ENCAP_ENTRY_VALID)) 1198 1137 continue; 1199 - list_for_each_entry(flow, &e->flows, encap) { 1138 + list_for_each_entry(efi, &e->flows, list) { 1139 + flow = container_of(efi, struct mlx5e_tc_flow, 1140 + encaps[efi->index]); 1200 1141 if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) { 1201 1142 counter = mlx5e_tc_get_counter(flow); 1202 1143 mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse); ··· 1229 1164 } 1230 1165 1231 1166 static void mlx5e_detach_encap(struct mlx5e_priv *priv, 1232 - struct mlx5e_tc_flow *flow) 1167 + struct mlx5e_tc_flow *flow, int out_index) 1233 1168 { 1234 - struct list_head *next = flow->encap.next; 1169 + struct list_head *next = flow->encaps[out_index].list.next; 1235 1170 1236 - list_del(&flow->encap); 1171 + list_del(&flow->encaps[out_index].list); 1237 1172 if (list_empty(next)) { 1238 1173 struct mlx5e_encap_entry *e; 1239 1174 ··· 2275 2210 2276 2211 if (priv->netdev->netdev_ops == peer_dev->netdev_ops && 2277 2212 same_hw_devs(priv, netdev_priv(peer_dev))) { 2278 - parse_attr->mirred_ifindex = peer_dev->ifindex; 2213 + parse_attr->mirred_ifindex[0] = peer_dev->ifindex; 2279 2214 flow->flags |= MLX5E_TC_FLOW_HAIRPIN; 2280 2215 action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 2281 2216 MLX5_FLOW_CONTEXT_ACTION_COUNT; ··· 2346 2281 struct net_device *mirred_dev, 2347 2282 struct net_device **encap_dev, 2348 2283 struct mlx5e_tc_flow *flow, 2349 - struct netlink_ext_ack *extack) 2284 + struct netlink_ext_ack *extack, 2285 + int out_index) 2350 2286 { 2351 2287 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 2352 2288 unsigned short family = ip_tunnel_info_af(tun_info); ··· 2394 2328 hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key); 2395 2329 2396 2330 attach_flow: 2397 - list_add(&flow->encap, &e->flows); 2331 + list_add(&flow->encaps[out_index].list, &e->flows); 2332 + flow->encaps[out_index].index = out_index; 2398 2333 *encap_dev = e->out_dev; 2399 - if (e->flags & MLX5_ENCAP_ENTRY_VALID) 2400 - attr->encap_id = e->encap_id; 2401 - else 2334 + if (e->flags & MLX5_ENCAP_ENTRY_VALID) { 2335 + attr->dests[out_index].encap_id = e->encap_id; 2336 + attr->dests[out_index].flags |= MLX5_ESW_DEST_ENCAP_VALID; 2337 + } else { 2402 2338 err = -EAGAIN; 2339 + } 2403 2340 2404 2341 return err; 2405 2342 ··· 2496 2427 return err; 2497 2428 2498 2429 action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 2499 - attr->mirror_count = attr->out_count; 2430 + attr->split_count = attr->out_count; 2500 2431 continue; 2501 2432 } 2502 2433 ··· 2530 2461 return -EOPNOTSUPP; 2531 2462 } 2532 2463 2464 + action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 2465 + MLX5_FLOW_CONTEXT_ACTION_COUNT; 2533 2466 if (switchdev_port_same_parent_id(priv->netdev, 2534 2467 out_dev) || 2535 2468 is_merged_eswitch_dev(priv, out_dev)) { 2536 - action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 2537 - MLX5_FLOW_CONTEXT_ACTION_COUNT; 2538 2469 out_priv = netdev_priv(out_dev); 2539 2470 rpriv = out_priv->ppriv; 2540 - attr->out_rep[attr->out_count] = rpriv->rep; 2541 - attr->out_mdev[attr->out_count++] = out_priv->mdev; 2471 + attr->dests[attr->out_count].rep = rpriv->rep; 2472 + attr->dests[attr->out_count].mdev = out_priv->mdev; 2473 + attr->out_count++; 2542 2474 } else if (encap) { 2543 - parse_attr->mirred_ifindex = out_dev->ifindex; 2544 - parse_attr->tun_info = *info; 2475 + parse_attr->mirred_ifindex[attr->out_count] = 2476 + out_dev->ifindex; 2477 + parse_attr->tun_info[attr->out_count] = *info; 2478 + encap = false; 2545 2479 attr->parse_attr = parse_attr; 2546 - action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT | 2547 - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 2548 - MLX5_FLOW_CONTEXT_ACTION_COUNT; 2549 - /* attr->out_rep is resolved when we handle encap */ 2480 + attr->dests[attr->out_count].flags |= 2481 + MLX5_ESW_DEST_ENCAP; 2482 + attr->out_count++; 2483 + /* attr->dests[].rep is resolved when we 2484 + * handle encap 2485 + */ 2550 2486 } else if (parse_attr->filter_dev != priv->netdev) { 2551 2487 /* All mlx5 devices are called to configure 2552 2488 * high level device filters. Therefore, the ··· 2575 2501 encap = true; 2576 2502 else 2577 2503 return -EOPNOTSUPP; 2578 - attr->mirror_count = attr->out_count; 2579 2504 continue; 2580 2505 } 2581 2506 ··· 2584 2511 if (err) 2585 2512 return err; 2586 2513 2587 - attr->mirror_count = attr->out_count; 2514 + attr->split_count = attr->out_count; 2588 2515 continue; 2589 2516 } 2590 2517 ··· 2619 2546 if (!actions_match_supported(priv, exts, parse_attr, flow, extack)) 2620 2547 return -EOPNOTSUPP; 2621 2548 2622 - if (attr->mirror_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) { 2549 + if (attr->split_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) { 2623 2550 NL_SET_ERR_MSG_MOD(extack, 2624 2551 "current firmware doesn't support split rule for port mirroring"); 2625 2552 netdev_warn_once(priv->netdev, "current firmware doesn't support split rule for port mirroring\n"); ··· 2726 2653 err = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow, extack); 2727 2654 if (err) 2728 2655 goto err_free; 2729 - 2730 - if (!(flow->esw_attr->action & 2731 - MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT)) 2732 - kvfree(parse_attr); 2733 2656 2734 2657 *__flow = flow; 2735 2658
+12 -4
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
··· 281 281 /* current maximum for flow based vport multicasting */ 282 282 #define MLX5_MAX_FLOW_FWD_VPORTS 2 283 283 284 + enum { 285 + MLX5_ESW_DEST_ENCAP = BIT(0), 286 + MLX5_ESW_DEST_ENCAP_VALID = BIT(1), 287 + }; 288 + 284 289 struct mlx5_esw_flow_attr { 285 290 struct mlx5_eswitch_rep *in_rep; 286 - struct mlx5_eswitch_rep *out_rep[MLX5_MAX_FLOW_FWD_VPORTS]; 287 - struct mlx5_core_dev *out_mdev[MLX5_MAX_FLOW_FWD_VPORTS]; 288 291 struct mlx5_core_dev *in_mdev; 289 292 290 - int mirror_count; 293 + int split_count; 291 294 int out_count; 292 295 293 296 int action; ··· 299 296 u8 vlan_prio[MLX5_FS_VLAN_DEPTH]; 300 297 u8 total_vlan; 301 298 bool vlan_handled; 302 - u32 encap_id; 299 + struct { 300 + u32 flags; 301 + struct mlx5_eswitch_rep *rep; 302 + struct mlx5_core_dev *mdev; 303 + u32 encap_id; 304 + } dests[MLX5_MAX_FLOW_FWD_VPORTS]; 303 305 u32 mod_hdr_id; 304 306 u8 match_level; 305 307 struct mlx5_fc *counter;
+26 -18
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
··· 81 81 { 82 82 struct mlx5_flow_destination dest[MLX5_MAX_FLOW_FWD_VPORTS + 1] = {}; 83 83 struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND, }; 84 - bool mirror = !!(attr->mirror_count); 84 + bool split = !!(attr->split_count); 85 85 struct mlx5_flow_handle *rule; 86 86 struct mlx5_flow_table *fdb; 87 87 int j, i = 0; ··· 120 120 dest[i].ft = ft; 121 121 i++; 122 122 } else { 123 - for (j = attr->mirror_count; j < attr->out_count; j++) { 123 + for (j = attr->split_count; j < attr->out_count; j++) { 124 124 dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT; 125 - dest[i].vport.num = attr->out_rep[j]->vport; 125 + dest[i].vport.num = attr->dests[j].rep->vport; 126 126 dest[i].vport.vhca_id = 127 - MLX5_CAP_GEN(attr->out_mdev[j], vhca_id); 127 + MLX5_CAP_GEN(attr->dests[j].mdev, vhca_id); 128 128 if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) 129 129 dest[i].vport.flags |= 130 130 MLX5_FLOW_DEST_VPORT_VHCA_ID; 131 + if (attr->dests[j].flags & MLX5_ESW_DEST_ENCAP) { 132 + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; 133 + flow_act.reformat_id = attr->dests[j].encap_id; 134 + dest[i].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID; 135 + dest[i].vport.reformat_id = 136 + attr->dests[j].encap_id; 137 + } 131 138 i++; 132 139 } 133 140 } ··· 171 164 if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) 172 165 flow_act.modify_id = attr->mod_hdr_id; 173 166 174 - if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) 175 - flow_act.reformat_id = attr->encap_id; 176 - 177 - fdb = esw_get_prio_table(esw, attr->chain, attr->prio, !!mirror); 167 + fdb = esw_get_prio_table(esw, attr->chain, attr->prio, !!split); 178 168 if (IS_ERR(fdb)) { 179 169 rule = ERR_CAST(fdb); 180 170 goto err_esw_get; ··· 186 182 return rule; 187 183 188 184 err_add_rule: 189 - esw_put_prio_table(esw, attr->chain, attr->prio, !!mirror); 185 + esw_put_prio_table(esw, attr->chain, attr->prio, !!split); 190 186 err_esw_get: 191 187 if (attr->dest_chain) 192 188 esw_put_prio_table(esw, attr->dest_chain, 1, 0); ··· 220 216 } 221 217 222 218 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 223 - for (i = 0; i < attr->mirror_count; i++) { 219 + for (i = 0; i < attr->split_count; i++) { 224 220 dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT; 225 - dest[i].vport.num = attr->out_rep[i]->vport; 221 + dest[i].vport.num = attr->dests[i].rep->vport; 226 222 dest[i].vport.vhca_id = 227 - MLX5_CAP_GEN(attr->out_mdev[i], vhca_id); 223 + MLX5_CAP_GEN(attr->dests[i].mdev, vhca_id); 228 224 if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) 229 225 dest[i].vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID; 226 + if (attr->dests[i].flags & MLX5_ESW_DEST_ENCAP) { 227 + dest[i].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID; 228 + dest[i].vport.reformat_id = attr->dests[i].encap_id; 229 + } 230 230 } 231 231 dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 232 232 dest[i].ft = fwd_fdb, ··· 278 270 struct mlx5_esw_flow_attr *attr, 279 271 bool fwd_rule) 280 272 { 281 - bool mirror = (attr->mirror_count > 0); 273 + bool split = (attr->split_count > 0); 282 274 283 275 mlx5_del_flow_rules(rule); 284 276 esw->offloads.num_flows--; ··· 287 279 esw_put_prio_table(esw, attr->chain, attr->prio, 1); 288 280 esw_put_prio_table(esw, attr->chain, attr->prio, 0); 289 281 } else { 290 - esw_put_prio_table(esw, attr->chain, attr->prio, !!mirror); 282 + esw_put_prio_table(esw, attr->chain, attr->prio, !!split); 291 283 if (attr->dest_chain) 292 284 esw_put_prio_table(esw, attr->dest_chain, 1, 0); 293 285 } ··· 335 327 struct mlx5_eswitch_rep *in_rep, *out_rep, *vport = NULL; 336 328 337 329 in_rep = attr->in_rep; 338 - out_rep = attr->out_rep[0]; 330 + out_rep = attr->dests[0].rep; 339 331 340 332 if (push) 341 333 vport = in_rep; ··· 356 348 goto out_notsupp; 357 349 358 350 in_rep = attr->in_rep; 359 - out_rep = attr->out_rep[0]; 351 + out_rep = attr->dests[0].rep; 360 352 361 353 if (push && in_rep->vport == FDB_UPLINK_VPORT) 362 354 goto out_notsupp; ··· 408 400 409 401 if (!push && !pop && fwd) { 410 402 /* tracks VF --> wire rules without vlan push action */ 411 - if (attr->out_rep[0]->vport == FDB_UPLINK_VPORT) { 403 + if (attr->dests[0].rep->vport == FDB_UPLINK_VPORT) { 412 404 vport->vlan_refcount++; 413 405 attr->vlan_handled = true; 414 406 } ··· 468 460 469 461 if (!push && !pop && fwd) { 470 462 /* tracks VF --> wire rules without vlan push action */ 471 - if (attr->out_rep[0]->vport == FDB_UPLINK_VPORT) 463 + if (attr->dests[0].rep->vport == FDB_UPLINK_VPORT) 472 464 vport->vlan_refcount--; 473 465 474 466 return 0;
+4 -1
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
··· 1373 1373 { 1374 1374 if (d1->type == d2->type) { 1375 1375 if ((d1->type == MLX5_FLOW_DESTINATION_TYPE_VPORT && 1376 - d1->vport.num == d2->vport.num) || 1376 + d1->vport.num == d2->vport.num && 1377 + d1->vport.flags == d2->vport.flags && 1378 + ((d1->vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID) ? 1379 + (d1->vport.reformat_id == d2->vport.reformat_id) : true)) || 1377 1380 (d1->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE && 1378 1381 d1->ft == d2->ft) || 1379 1382 (d1->type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/wq.c
··· 155 155 void *cqc, struct mlx5_cqwq *wq, 156 156 struct mlx5_wq_ctrl *wq_ctrl) 157 157 { 158 - u8 log_wq_stride = MLX5_GET(cqc, cqc, cqe_sz) + 6; 158 + /* CQE_STRIDE_128 and CQE_STRIDE_128_PAD both mean 128B stride */ 159 + u8 log_wq_stride = MLX5_GET(cqc, cqc, cqe_sz) == CQE_STRIDE_64 ? 6 : 7; 159 160 u8 log_wq_sz = MLX5_GET(cqc, cqc, log_cq_size); 160 161 int err; 161 162
+6 -1
drivers/net/ethernet/mellanox/mlx5/core/wq.h
··· 179 179 180 180 static inline struct mlx5_cqe64 *mlx5_cqwq_get_wqe(struct mlx5_cqwq *wq, u32 ix) 181 181 { 182 - return mlx5_frag_buf_get_wqe(&wq->fbc, ix); 182 + struct mlx5_cqe64 *cqe = mlx5_frag_buf_get_wqe(&wq->fbc, ix); 183 + 184 + /* For 128B CQEs the data is in the last 64B */ 185 + cqe += wq->fbc.log_stride == 7; 186 + 187 + return cqe; 183 188 } 184 189 185 190 static inline u32 mlx5_cqwq_get_ctr_wrap_cnt(struct mlx5_cqwq *wq, u32 ctr)
+5 -5
include/linux/mlx5/cq.h
··· 125 125 }; 126 126 127 127 enum { 128 - CQE_SIZE_64 = 0, 129 - CQE_SIZE_128 = 1, 130 - CQE_SIZE_128_PAD = 2, 128 + CQE_STRIDE_64 = 0, 129 + CQE_STRIDE_128 = 1, 130 + CQE_STRIDE_128_PAD = 2, 131 131 }; 132 132 133 133 #define MLX5_MAX_CQ_PERIOD (BIT(__mlx5_bit_sz(cqc, cq_period)) - 1) ··· 135 135 136 136 static inline int cqe_sz_to_mlx_sz(u8 size, int padding_128_en) 137 137 { 138 - return padding_128_en ? CQE_SIZE_128_PAD : 139 - size == 64 ? CQE_SIZE_64 : CQE_SIZE_128; 138 + return padding_128_en ? CQE_STRIDE_128_PAD : 139 + size == 64 ? CQE_STRIDE_64 : CQE_STRIDE_128; 140 140 } 141 141 142 142 static inline void mlx5_cq_set_ci(struct mlx5_core_cq *cq)
+3 -1
include/linux/mlx5/mlx5_ifc.h
··· 8283 8283 u8 port_access_reg_cap_mask_31_to_13[0x13]; 8284 8284 u8 pbmc[0x1]; 8285 8285 u8 pptb[0x1]; 8286 - u8 port_access_reg_cap_mask_10_to_0[0xb]; 8286 + u8 port_access_reg_cap_mask_10_to_09[0x2]; 8287 + u8 ppcnt[0x1]; 8288 + u8 port_access_reg_cap_mask_07_to_00[0x8]; 8287 8289 }; 8288 8290 8289 8291 struct mlx5_ifc_pcam_reg_bits {