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

Merge tag 'mlx5-updates-2021-10-04' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2021-10-04

Misc updates for mlx5 driver

1) Add TX max rate support for MQPRIO channel mode
2) Trivial TC action and modify header refactoring
3) TC support for accept action in fdb offloads
4) Allow single IRQ for PCI functions

5) Bridge offload: Pop PVID VLAN header on egress miss

Vlad Buslov says:
=================

With current architecture of mlx5 bridge offload it is possible for a
packet to match in ingress table by source MAC (resulting VLAN header push
in case of port with configured PVID) and then miss in egress table when
destination MAC is not in FDB. Due to the lack of hardware learning in
NICs, this, in turn, results packet going to software data path with PVID
VLAN already added by hardware. This doesn't break software bridge since it
accepts either untagged packets or packets with any provisioned VLAN on
ports with PVID, but can break ingress TC, if affected part of Ethernet
header is matched by classifier.

Improve compatibility with software TC by restoring the packet header on
egress miss. Effectively, this change implements atomicity of mlx5 bridge
offload implementation - packet is either modified and redirected to
destination port or appears unmodified in software.

=================

=================

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

+597 -149
+1
drivers/infiniband/hw/mlx5/odp.c
··· 1559 1559 1560 1560 eq->irq_nb.notifier_call = mlx5_ib_eq_pf_int; 1561 1561 param = (struct mlx5_eq_param) { 1562 + .irq_index = MLX5_IRQ_EQ_CTRL, 1562 1563 .nent = MLX5_IB_NUM_PF_EQE, 1563 1564 }; 1564 1565 param.mask[0] = 1ull << MLX5_EVENT_TYPE_PAGE_FAULT;
+6 -1
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 251 251 u16 mode; 252 252 u8 num_tc; 253 253 struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE]; 254 + struct { 255 + struct mlx5e_mqprio_rl *rl; 256 + } channel; 254 257 } mqprio; 255 258 bool rx_cqe_compress_def; 256 259 bool tunneled_offload_en; ··· 880 877 #endif 881 878 struct mlx5e_scratchpad scratchpad; 882 879 struct mlx5e_htb htb; 880 + struct mlx5e_mqprio_rl *mqprio_rl; 883 881 }; 884 882 885 883 struct mlx5e_rx_handlers { ··· 1006 1002 struct mlx5e_modify_sq_param *p); 1007 1003 int mlx5e_open_txqsq(struct mlx5e_channel *c, u32 tisn, int txq_ix, 1008 1004 struct mlx5e_params *params, struct mlx5e_sq_param *param, 1009 - struct mlx5e_txqsq *sq, int tc, u16 qos_queue_group_id, u16 qos_qid); 1005 + struct mlx5e_txqsq *sq, int tc, u16 qos_queue_group_id, 1006 + struct mlx5e_sq_stats *sq_stats); 1010 1007 void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq); 1011 1008 void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq); 1012 1009 void mlx5e_free_txqsq(struct mlx5e_txqsq *sq);
+101 -1
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
··· 7 7 8 8 #define BYTES_IN_MBIT 125000 9 9 10 + int mlx5e_qos_bytes_rate_check(struct mlx5_core_dev *mdev, u64 nbytes) 11 + { 12 + if (nbytes < BYTES_IN_MBIT) { 13 + qos_warn(mdev, "Input rate (%llu Bytes/sec) below minimum supported (%u Bytes/sec)\n", 14 + nbytes, BYTES_IN_MBIT); 15 + return -EINVAL; 16 + } 17 + return 0; 18 + } 19 + 20 + static u32 mlx5e_qos_bytes2mbits(struct mlx5_core_dev *mdev, u64 nbytes) 21 + { 22 + return div_u64(nbytes, BYTES_IN_MBIT); 23 + } 24 + 10 25 int mlx5e_qos_max_leaf_nodes(struct mlx5_core_dev *mdev) 11 26 { 12 27 return min(MLX5E_QOS_MAX_LEAF_NODES, mlx5_qos_max_leaf_nodes(mdev)); ··· 253 238 if (err) 254 239 goto err_free_sq; 255 240 err = mlx5e_open_txqsq(c, priv->tisn[c->lag_port][0], txq_ix, params, 256 - &param_sq, sq, 0, node->hw_id, node->qid); 241 + &param_sq, sq, 0, node->hw_id, 242 + priv->htb.qos_sq_stats[node->qid]); 257 243 if (err) 258 244 goto err_close_cq; 259 245 ··· 994 978 err = mlx5e_qos_update_children(priv, node, extack); 995 979 996 980 return err; 981 + } 982 + 983 + struct mlx5e_mqprio_rl { 984 + struct mlx5_core_dev *mdev; 985 + u32 root_id; 986 + u32 *leaves_id; 987 + u8 num_tc; 988 + }; 989 + 990 + struct mlx5e_mqprio_rl *mlx5e_mqprio_rl_alloc(void) 991 + { 992 + return kvzalloc(sizeof(struct mlx5e_mqprio_rl), GFP_KERNEL); 993 + } 994 + 995 + void mlx5e_mqprio_rl_free(struct mlx5e_mqprio_rl *rl) 996 + { 997 + kvfree(rl); 998 + } 999 + 1000 + int mlx5e_mqprio_rl_init(struct mlx5e_mqprio_rl *rl, struct mlx5_core_dev *mdev, u8 num_tc, 1001 + u64 max_rate[]) 1002 + { 1003 + int err; 1004 + int tc; 1005 + 1006 + if (!mlx5_qos_is_supported(mdev)) { 1007 + qos_warn(mdev, "Missing QoS capabilities. Try disabling SRIOV or use a supported device."); 1008 + return -EOPNOTSUPP; 1009 + } 1010 + if (num_tc > mlx5e_qos_max_leaf_nodes(mdev)) 1011 + return -EINVAL; 1012 + 1013 + rl->mdev = mdev; 1014 + rl->num_tc = num_tc; 1015 + rl->leaves_id = kvcalloc(num_tc, sizeof(*rl->leaves_id), GFP_KERNEL); 1016 + if (!rl->leaves_id) 1017 + return -ENOMEM; 1018 + 1019 + err = mlx5_qos_create_root_node(mdev, &rl->root_id); 1020 + if (err) 1021 + goto err_free_leaves; 1022 + 1023 + qos_dbg(mdev, "Root created, id %#x\n", rl->root_id); 1024 + 1025 + for (tc = 0; tc < num_tc; tc++) { 1026 + u32 max_average_bw; 1027 + 1028 + max_average_bw = mlx5e_qos_bytes2mbits(mdev, max_rate[tc]); 1029 + err = mlx5_qos_create_leaf_node(mdev, rl->root_id, 0, max_average_bw, 1030 + &rl->leaves_id[tc]); 1031 + if (err) 1032 + goto err_destroy_leaves; 1033 + 1034 + qos_dbg(mdev, "Leaf[%d] created, id %#x, max average bw %u Mbits/sec\n", 1035 + tc, rl->leaves_id[tc], max_average_bw); 1036 + } 1037 + return 0; 1038 + 1039 + err_destroy_leaves: 1040 + while (--tc >= 0) 1041 + mlx5_qos_destroy_node(mdev, rl->leaves_id[tc]); 1042 + mlx5_qos_destroy_node(mdev, rl->root_id); 1043 + err_free_leaves: 1044 + kvfree(rl->leaves_id); 1045 + return err; 1046 + } 1047 + 1048 + void mlx5e_mqprio_rl_cleanup(struct mlx5e_mqprio_rl *rl) 1049 + { 1050 + int tc; 1051 + 1052 + for (tc = 0; tc < rl->num_tc; tc++) 1053 + mlx5_qos_destroy_node(rl->mdev, rl->leaves_id[tc]); 1054 + mlx5_qos_destroy_node(rl->mdev, rl->root_id); 1055 + kvfree(rl->leaves_id); 1056 + } 1057 + 1058 + int mlx5e_mqprio_rl_get_node_hw_id(struct mlx5e_mqprio_rl *rl, int tc, u32 *hw_id) 1059 + { 1060 + if (tc >= rl->num_tc) 1061 + return -EINVAL; 1062 + 1063 + *hw_id = rl->leaves_id[tc]; 1064 + return 0; 997 1065 }
+9
drivers/net/ethernet/mellanox/mlx5/core/en/qos.h
··· 12 12 struct mlx5e_channels; 13 13 struct mlx5e_channel; 14 14 15 + int mlx5e_qos_bytes_rate_check(struct mlx5_core_dev *mdev, u64 nbytes); 15 16 int mlx5e_qos_max_leaf_nodes(struct mlx5_core_dev *mdev); 16 17 int mlx5e_qos_cur_leaf_nodes(struct mlx5e_priv *priv); 17 18 ··· 42 41 int mlx5e_htb_node_modify(struct mlx5e_priv *priv, u16 classid, u64 rate, u64 ceil, 43 42 struct netlink_ext_ack *extack); 44 43 44 + /* MQPRIO TX rate limit */ 45 + struct mlx5e_mqprio_rl; 46 + struct mlx5e_mqprio_rl *mlx5e_mqprio_rl_alloc(void); 47 + void mlx5e_mqprio_rl_free(struct mlx5e_mqprio_rl *rl); 48 + int mlx5e_mqprio_rl_init(struct mlx5e_mqprio_rl *rl, struct mlx5_core_dev *mdev, u8 num_tc, 49 + u64 max_rate[]); 50 + void mlx5e_mqprio_rl_cleanup(struct mlx5e_mqprio_rl *rl); 51 + int mlx5e_mqprio_rl_get_node_hw_id(struct mlx5e_mqprio_rl *rl, int tc, u32 *hw_id); 45 52 #endif
+5 -16
drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c
··· 602 602 } 603 603 sample_flow->pre_attr = pre_attr; 604 604 605 - return sample_flow->post_rule; 605 + return sample_flow->pre_rule; 606 606 607 607 err_pre_offload_rule: 608 608 kfree(pre_attr); ··· 613 613 err_obj_id: 614 614 sampler_put(tc_psample, sample_flow->sampler); 615 615 err_sampler: 616 - if (!post_act_handle) 616 + if (sample_flow->post_rule) 617 617 del_post_rule(esw, sample_flow, attr); 618 618 err_post_rule: 619 619 if (post_act_handle) ··· 628 628 struct mlx5_flow_handle *rule, 629 629 struct mlx5_flow_attr *attr) 630 630 { 631 - struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr; 632 631 struct mlx5e_sample_flow *sample_flow; 633 - struct mlx5_vport_tbl_attr tbl_attr; 634 632 struct mlx5_eswitch *esw; 635 633 636 634 if (IS_ERR_OR_NULL(tc_psample)) ··· 648 650 */ 649 651 sample_flow = attr->sample_attr->sample_flow; 650 652 mlx5_eswitch_del_offloaded_rule(esw, sample_flow->pre_rule, sample_flow->pre_attr); 651 - if (!sample_flow->post_act_handle) 652 - mlx5_eswitch_del_offloaded_rule(esw, sample_flow->post_rule, 653 - sample_flow->post_attr); 654 653 655 654 sample_restore_put(tc_psample, sample_flow->restore); 656 655 mapping_remove(esw->offloads.reg_c0_obj_pool, attr->sample_attr->restore_obj_id); 657 656 sampler_put(tc_psample, sample_flow->sampler); 658 - if (sample_flow->post_act_handle) { 657 + if (sample_flow->post_act_handle) 659 658 mlx5e_tc_post_act_del(tc_psample->post_act, sample_flow->post_act_handle); 660 - } else { 661 - tbl_attr.chain = attr->chain; 662 - tbl_attr.prio = attr->prio; 663 - tbl_attr.vport = esw_attr->in_rep->vport; 664 - tbl_attr.vport_ns = &mlx5_esw_vport_tbl_sample_ns; 665 - mlx5_esw_vporttbl_put(esw, &tbl_attr); 666 - kfree(sample_flow->post_attr); 667 - } 659 + else 660 + del_post_rule(esw, sample_flow, attr); 668 661 669 662 kfree(sample_flow->pre_attr); 670 663 kfree(sample_flow);
+8
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
··· 118 118 119 119 uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH); 120 120 attr->fl.fl4.flowi4_oif = uplink_dev->ifindex; 121 + } else { 122 + struct mlx5e_tc_tunnel *tunnel = mlx5e_get_tc_tun(mirred_dev); 123 + 124 + if (tunnel && tunnel->get_remote_ifindex) 125 + attr->fl.fl4.flowi4_oif = tunnel->get_remote_ifindex(mirred_dev); 121 126 } 122 127 123 128 rt = ip_route_output_key(dev_net(mirred_dev), &attr->fl.fl4); ··· 440 435 struct net_device *mirred_dev, 441 436 struct mlx5e_tc_tun_route_attr *attr) 442 437 { 438 + struct mlx5e_tc_tunnel *tunnel = mlx5e_get_tc_tun(mirred_dev); 443 439 struct net_device *route_dev; 444 440 struct net_device *out_dev; 445 441 struct dst_entry *dst; 446 442 struct neighbour *n; 447 443 int ret; 448 444 445 + if (tunnel && tunnel->get_remote_ifindex) 446 + attr->fl.fl6.flowi6_oif = tunnel->get_remote_ifindex(mirred_dev); 449 447 dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(mirred_dev), NULL, &attr->fl.fl6, 450 448 NULL); 451 449 if (IS_ERR(dst))
+1
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
··· 51 51 void *headers_v); 52 52 bool (*encap_info_equal)(struct mlx5e_encap_key *a, 53 53 struct mlx5e_encap_key *b); 54 + int (*get_remote_ifindex)(struct net_device *mirred_dev); 54 55 }; 55 56 56 57 extern struct mlx5e_tc_tunnel vxlan_tunnel;
+9
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
··· 141 141 return 0; 142 142 } 143 143 144 + static int mlx5e_tc_tun_get_remote_ifindex(struct net_device *mirred_dev) 145 + { 146 + const struct vxlan_dev *vxlan = netdev_priv(mirred_dev); 147 + const struct vxlan_rdst *dst = &vxlan->default_dst; 148 + 149 + return dst->remote_ifindex; 150 + } 151 + 144 152 struct mlx5e_tc_tunnel vxlan_tunnel = { 145 153 .tunnel_type = MLX5E_TC_TUNNEL_TYPE_VXLAN, 146 154 .match_level = MLX5_MATCH_L4, ··· 159 151 .parse_udp_ports = mlx5e_tc_tun_parse_udp_ports_vxlan, 160 152 .parse_tunnel = mlx5e_tc_tun_parse_vxlan, 161 153 .encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic, 154 + .get_remote_ifindex = mlx5e_tc_tun_get_remote_ifindex, 162 155 };
+95 -11
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 1300 1300 1301 1301 int mlx5e_open_txqsq(struct mlx5e_channel *c, u32 tisn, int txq_ix, 1302 1302 struct mlx5e_params *params, struct mlx5e_sq_param *param, 1303 - struct mlx5e_txqsq *sq, int tc, u16 qos_queue_group_id, u16 qos_qid) 1303 + struct mlx5e_txqsq *sq, int tc, u16 qos_queue_group_id, 1304 + struct mlx5e_sq_stats *sq_stats) 1304 1305 { 1305 1306 struct mlx5e_create_sq_param csp = {}; 1306 1307 u32 tx_rate; ··· 1311 1310 if (err) 1312 1311 return err; 1313 1312 1314 - if (qos_queue_group_id) 1315 - sq->stats = c->priv->htb.qos_sq_stats[qos_qid]; 1316 - else 1317 - sq->stats = &c->priv->channel_stats[c->ix].sq[tc]; 1313 + sq->stats = sq_stats; 1318 1314 1319 1315 csp.tisn = tisn; 1320 1316 csp.tis_lst_sz = 1; ··· 1705 1707 mlx5e_close_cq(&c->sq[tc].cq); 1706 1708 } 1707 1709 1710 + static int mlx5e_mqprio_txq_to_tc(struct netdev_tc_txq *tc_to_txq, unsigned int txq) 1711 + { 1712 + int tc; 1713 + 1714 + for (tc = 0; tc < TC_MAX_QUEUE; tc++) 1715 + if (txq - tc_to_txq[tc].offset < tc_to_txq[tc].count) 1716 + return tc; 1717 + 1718 + WARN(1, "Unexpected TCs configuration. No match found for txq %u", txq); 1719 + return -ENOENT; 1720 + } 1721 + 1722 + static int mlx5e_txq_get_qos_node_hw_id(struct mlx5e_params *params, int txq_ix, 1723 + u32 *hw_id) 1724 + { 1725 + int tc; 1726 + 1727 + if (params->mqprio.mode != TC_MQPRIO_MODE_CHANNEL || 1728 + !params->mqprio.channel.rl) { 1729 + *hw_id = 0; 1730 + return 0; 1731 + } 1732 + 1733 + tc = mlx5e_mqprio_txq_to_tc(params->mqprio.tc_to_txq, txq_ix); 1734 + if (tc < 0) 1735 + return tc; 1736 + 1737 + return mlx5e_mqprio_rl_get_node_hw_id(params->mqprio.channel.rl, tc, hw_id); 1738 + } 1739 + 1708 1740 static int mlx5e_open_sqs(struct mlx5e_channel *c, 1709 1741 struct mlx5e_params *params, 1710 1742 struct mlx5e_channel_param *cparam) ··· 1743 1715 1744 1716 for (tc = 0; tc < mlx5e_get_dcb_num_tc(params); tc++) { 1745 1717 int txq_ix = c->ix + tc * params->num_channels; 1718 + u32 qos_queue_group_id; 1719 + 1720 + err = mlx5e_txq_get_qos_node_hw_id(params, txq_ix, &qos_queue_group_id); 1721 + if (err) 1722 + goto err_close_sqs; 1746 1723 1747 1724 err = mlx5e_open_txqsq(c, c->priv->tisn[c->lag_port][tc], txq_ix, 1748 - params, &cparam->txq_sq, &c->sq[tc], tc, 0, 0); 1725 + params, &cparam->txq_sq, &c->sq[tc], tc, 1726 + qos_queue_group_id, 1727 + &c->priv->channel_stats[c->ix].sq[tc]); 1749 1728 if (err) 1750 1729 goto err_close_sqs; 1751 1730 } ··· 2377 2342 netdev_warn(netdev, "netif_set_real_num_rx_queues failed, %d\n", err); 2378 2343 goto err_txqs; 2379 2344 } 2345 + if (priv->mqprio_rl != priv->channels.params.mqprio.channel.rl) { 2346 + if (priv->mqprio_rl) { 2347 + mlx5e_mqprio_rl_cleanup(priv->mqprio_rl); 2348 + mlx5e_mqprio_rl_free(priv->mqprio_rl); 2349 + } 2350 + priv->mqprio_rl = priv->channels.params.mqprio.channel.rl; 2351 + } 2380 2352 2381 2353 return 0; 2382 2354 ··· 2945 2903 { 2946 2904 params->mqprio.mode = TC_MQPRIO_MODE_DCB; 2947 2905 params->mqprio.num_tc = num_tc; 2906 + params->mqprio.channel.rl = NULL; 2948 2907 mlx5e_mqprio_build_default_tc_to_txq(params->mqprio.tc_to_txq, num_tc, 2949 2908 params->num_channels); 2950 2909 } 2951 2910 2952 2911 static void mlx5e_params_mqprio_channel_set(struct mlx5e_params *params, 2953 - struct tc_mqprio_qopt *qopt) 2912 + struct tc_mqprio_qopt *qopt, 2913 + struct mlx5e_mqprio_rl *rl) 2954 2914 { 2955 2915 params->mqprio.mode = TC_MQPRIO_MODE_CHANNEL; 2956 2916 params->mqprio.num_tc = qopt->num_tc; 2917 + params->mqprio.channel.rl = rl; 2957 2918 mlx5e_mqprio_build_tc_to_txq(params->mqprio.tc_to_txq, qopt); 2958 2919 } 2959 2920 ··· 3016 2971 netdev_err(netdev, "Min tx rate is not supported\n"); 3017 2972 return -EINVAL; 3018 2973 } 2974 + 3019 2975 if (mqprio->max_rate[i]) { 3020 - netdev_err(netdev, "Max tx rate is not supported\n"); 3021 - return -EINVAL; 2976 + int err; 2977 + 2978 + err = mlx5e_qos_bytes_rate_check(priv->mdev, mqprio->max_rate[i]); 2979 + if (err) 2980 + return err; 3022 2981 } 3023 2982 3024 2983 if (mqprio->qopt.offset[i] != agg_count) { ··· 3041 2992 return 0; 3042 2993 } 3043 2994 2995 + static bool mlx5e_mqprio_rate_limit(struct tc_mqprio_qopt_offload *mqprio) 2996 + { 2997 + int tc; 2998 + 2999 + for (tc = 0; tc < mqprio->qopt.num_tc; tc++) 3000 + if (mqprio->max_rate[tc]) 3001 + return true; 3002 + return false; 3003 + } 3004 + 3044 3005 static int mlx5e_setup_tc_mqprio_channel(struct mlx5e_priv *priv, 3045 3006 struct tc_mqprio_qopt_offload *mqprio) 3046 3007 { 3047 3008 mlx5e_fp_preactivate preactivate; 3048 3009 struct mlx5e_params new_params; 3010 + struct mlx5e_mqprio_rl *rl; 3049 3011 bool nch_changed; 3050 3012 int err; 3051 3013 ··· 3064 3004 if (err) 3065 3005 return err; 3066 3006 3007 + rl = NULL; 3008 + if (mlx5e_mqprio_rate_limit(mqprio)) { 3009 + rl = mlx5e_mqprio_rl_alloc(); 3010 + if (!rl) 3011 + return -ENOMEM; 3012 + err = mlx5e_mqprio_rl_init(rl, priv->mdev, mqprio->qopt.num_tc, 3013 + mqprio->max_rate); 3014 + if (err) { 3015 + mlx5e_mqprio_rl_free(rl); 3016 + return err; 3017 + } 3018 + } 3019 + 3067 3020 new_params = priv->channels.params; 3068 - mlx5e_params_mqprio_channel_set(&new_params, &mqprio->qopt); 3021 + mlx5e_params_mqprio_channel_set(&new_params, &mqprio->qopt, rl); 3069 3022 3070 3023 nch_changed = mlx5e_get_dcb_num_tc(&priv->channels.params) > 1; 3071 3024 preactivate = nch_changed ? mlx5e_num_channels_changed_ctx : 3072 3025 mlx5e_update_netdev_queues_ctx; 3073 - return mlx5e_safe_switch_params(priv, &new_params, preactivate, NULL, true); 3026 + err = mlx5e_safe_switch_params(priv, &new_params, preactivate, NULL, true); 3027 + if (err && rl) { 3028 + mlx5e_mqprio_rl_cleanup(rl); 3029 + mlx5e_mqprio_rl_free(rl); 3030 + } 3031 + 3032 + return err; 3074 3033 } 3075 3034 3076 3035 static int mlx5e_setup_tc_mqprio(struct mlx5e_priv *priv, ··· 4888 4809 for (i = 0; i < priv->htb.max_qos_sqs; i++) 4889 4810 kfree(priv->htb.qos_sq_stats[i]); 4890 4811 kvfree(priv->htb.qos_sq_stats); 4812 + 4813 + if (priv->mqprio_rl) { 4814 + mlx5e_mqprio_rl_cleanup(priv->mqprio_rl); 4815 + mlx5e_mqprio_rl_free(priv->mqprio_rl); 4816 + } 4891 4817 4892 4818 memset(priv, 0, sizeof(*priv)); 4893 4819 }
+108 -71
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
··· 3169 3169 return true; 3170 3170 } 3171 3171 3172 - static bool actions_match_supported(struct mlx5e_priv *priv, 3173 - struct flow_action *flow_action, 3174 - struct mlx5e_tc_flow_parse_attr *parse_attr, 3175 - struct mlx5e_tc_flow *flow, 3176 - struct netlink_ext_ack *extack) 3172 + static bool 3173 + actions_match_supported_fdb(struct mlx5e_priv *priv, 3174 + struct mlx5e_tc_flow_parse_attr *parse_attr, 3175 + struct mlx5e_tc_flow *flow, 3176 + struct netlink_ext_ack *extack) 3177 3177 { 3178 - bool ct_flow = false, ct_clear = false; 3179 - u32 actions; 3178 + struct mlx5_esw_flow_attr *esw_attr = flow->attr->esw_attr; 3179 + bool ct_flow, ct_clear; 3180 3180 3181 - ct_clear = flow->attr->ct_attr.ct_action & 3182 - TCA_CT_ACT_CLEAR; 3181 + ct_clear = flow->attr->ct_attr.ct_action & TCA_CT_ACT_CLEAR; 3183 3182 ct_flow = flow_flag_test(flow, CT) && !ct_clear; 3184 - actions = flow->attr->action; 3183 + 3184 + if (esw_attr->split_count && ct_flow && 3185 + !MLX5_CAP_GEN(esw_attr->in_mdev, reg_c_preserve)) { 3186 + /* All registers used by ct are cleared when using 3187 + * split rules. 3188 + */ 3189 + NL_SET_ERR_MSG_MOD(extack, "Can't offload mirroring with action ct"); 3190 + return false; 3191 + } 3192 + 3193 + if (esw_attr->split_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) { 3194 + NL_SET_ERR_MSG_MOD(extack, 3195 + "current firmware doesn't support split rule for port mirroring"); 3196 + netdev_warn_once(priv->netdev, 3197 + "current firmware doesn't support split rule for port mirroring\n"); 3198 + return false; 3199 + } 3200 + 3201 + return true; 3202 + } 3203 + 3204 + static bool 3205 + actions_match_supported(struct mlx5e_priv *priv, 3206 + struct flow_action *flow_action, 3207 + struct mlx5e_tc_flow_parse_attr *parse_attr, 3208 + struct mlx5e_tc_flow *flow, 3209 + struct netlink_ext_ack *extack) 3210 + { 3211 + u32 actions = flow->attr->action; 3212 + bool ct_flow, ct_clear; 3213 + 3214 + ct_clear = flow->attr->ct_attr.ct_action & TCA_CT_ACT_CLEAR; 3215 + ct_flow = flow_flag_test(flow, CT) && !ct_clear; 3185 3216 3186 3217 if (!(actions & 3187 3218 (MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) { ··· 3220 3189 return false; 3221 3190 } 3222 3191 3223 - if (mlx5e_is_eswitch_flow(flow)) { 3224 - if (flow->attr->esw_attr->split_count && ct_flow && 3225 - !MLX5_CAP_GEN(flow->attr->esw_attr->in_mdev, reg_c_preserve)) { 3226 - /* All registers used by ct are cleared when using 3227 - * split rules. 3228 - */ 3229 - NL_SET_ERR_MSG_MOD(extack, 3230 - "Can't offload mirroring with action ct"); 3231 - return false; 3232 - } 3233 - } 3192 + if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR && 3193 + !modify_header_match_supported(priv, &parse_attr->spec, flow_action, 3194 + actions, ct_flow, ct_clear, extack)) 3195 + return false; 3234 3196 3235 - if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) 3236 - return modify_header_match_supported(priv, &parse_attr->spec, 3237 - flow_action, actions, 3238 - ct_flow, ct_clear, 3239 - extack); 3197 + if (mlx5e_is_eswitch_flow(flow) && 3198 + !actions_match_supported_fdb(priv, parse_attr, flow, extack)) 3199 + return false; 3240 3200 3241 3201 return true; 3242 3202 } ··· 3376 3354 return 0; 3377 3355 } 3378 3356 3379 - static int parse_tc_nic_actions(struct mlx5e_priv *priv, 3380 - struct flow_action *flow_action, 3357 + static int 3358 + actions_prepare_mod_hdr_actions(struct mlx5e_priv *priv, 3381 3359 struct mlx5e_tc_flow *flow, 3360 + struct mlx5_flow_attr *attr, 3361 + struct pedit_headers_action *hdrs, 3382 3362 struct netlink_ext_ack *extack) 3363 + { 3364 + struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr; 3365 + enum mlx5_flow_namespace_type ns_type; 3366 + int err; 3367 + 3368 + if (!hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits && 3369 + !hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) 3370 + return 0; 3371 + 3372 + ns_type = get_flow_name_space(flow); 3373 + 3374 + err = alloc_tc_pedit_action(priv, ns_type, parse_attr, hdrs, 3375 + &attr->action, extack); 3376 + if (err) 3377 + return err; 3378 + 3379 + /* In case all pedit actions are skipped, remove the MOD_HDR flag. */ 3380 + if (parse_attr->mod_hdr_acts.num_actions > 0) 3381 + return 0; 3382 + 3383 + attr->action &= ~MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 3384 + dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts); 3385 + 3386 + if (ns_type != MLX5_FLOW_NAMESPACE_FDB) 3387 + return 0; 3388 + 3389 + if (!((attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) || 3390 + (attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH))) 3391 + attr->esw_attr->split_count = 0; 3392 + 3393 + return 0; 3394 + } 3395 + 3396 + static int 3397 + parse_tc_nic_actions(struct mlx5e_priv *priv, 3398 + struct flow_action *flow_action, 3399 + struct mlx5e_tc_flow *flow, 3400 + struct netlink_ext_ack *extack) 3383 3401 { 3384 3402 struct mlx5e_tc_flow_parse_attr *parse_attr; 3385 3403 struct mlx5_flow_attr *attr = flow->attr; ··· 3529 3467 } 3530 3468 } 3531 3469 3532 - if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits || 3533 - hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) { 3534 - err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL, 3535 - parse_attr, hdrs, &action, extack); 3536 - if (err) 3537 - return err; 3538 - /* in case all pedit actions are skipped, remove the MOD_HDR 3539 - * flag. 3540 - */ 3541 - if (parse_attr->mod_hdr_acts.num_actions == 0) { 3542 - action &= ~MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 3543 - dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts); 3544 - } 3545 - } 3546 - 3547 3470 attr->action = action; 3548 3471 3549 3472 if (attr->dest_chain && parse_attr->mirred_ifindex[0]) { 3550 3473 NL_SET_ERR_MSG(extack, "Mirroring goto chain rules isn't supported"); 3551 3474 return -EOPNOTSUPP; 3552 3475 } 3476 + 3477 + err = actions_prepare_mod_hdr_actions(priv, flow, attr, hdrs, extack); 3478 + if (err) 3479 + return err; 3553 3480 3554 3481 if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack)) 3555 3482 return -EOPNOTSUPP; ··· 3810 3759 3811 3760 flow_action_for_each(i, act, flow_action) { 3812 3761 switch (act->id) { 3762 + case FLOW_ACTION_ACCEPT: 3763 + action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 3764 + MLX5_FLOW_CONTEXT_ACTION_COUNT; 3765 + attr->flags |= MLX5_ESW_ATTR_FLAG_ACCEPT; 3766 + break; 3813 3767 case FLOW_ACTION_DROP: 3814 3768 action |= MLX5_FLOW_CONTEXT_ACTION_DROP | 3815 3769 MLX5_FLOW_CONTEXT_ACTION_COUNT; ··· 4099 4043 return err; 4100 4044 } 4101 4045 4102 - if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits || 4103 - hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) { 4104 - err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_FDB, 4105 - parse_attr, hdrs, &action, extack); 4106 - if (err) 4107 - return err; 4108 - /* in case all pedit actions are skipped, remove the MOD_HDR 4109 - * flag. we might have set split_count either by pedit or 4110 - * pop/push. if there is no pop/push either, reset it too. 4111 - */ 4112 - if (parse_attr->mod_hdr_acts.num_actions == 0) { 4113 - action &= ~MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 4114 - dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts); 4115 - if (!((action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) || 4116 - (action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH))) 4117 - esw_attr->split_count = 0; 4118 - } 4119 - } 4120 - 4121 4046 attr->action = action; 4047 + 4048 + err = actions_prepare_mod_hdr_actions(priv, flow, attr, hdrs, extack); 4049 + if (err) 4050 + return err; 4051 + 4122 4052 if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack)) 4123 4053 return -EOPNOTSUPP; 4124 4054 ··· 4119 4077 4120 4078 NL_SET_ERR_MSG(extack, "Decap with goto isn't supported"); 4121 4079 netdev_warn(priv->netdev, "Decap with goto isn't supported"); 4122 - return -EOPNOTSUPP; 4123 - } 4124 - 4125 - if (esw_attr->split_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) { 4126 - NL_SET_ERR_MSG_MOD(extack, 4127 - "current firmware doesn't support split rule for port mirroring"); 4128 - netdev_warn_once(priv->netdev, "current firmware doesn't support split rule for port mirroring\n"); 4129 4080 return -EOPNOTSUPP; 4130 4081 } 4131 4082 ··· 5040 5005 } 5041 5006 uplink_priv->tunnel_mapping = mapping; 5042 5007 5043 - /* 0xFFF is reserved for stack devices slow path table mark */ 5008 + /* Two last values are reserved for stack devices slow path table mark 5009 + * and bridge ingress push mark. 5010 + */ 5044 5011 mapping = mapping_create_for_id(mapping_id, MAPPING_TYPE_TUNNEL_ENC_OPTS, 5045 - sz_enc_opts, ENC_OPTS_BITS_MASK - 1, true); 5012 + sz_enc_opts, ENC_OPTS_BITS_MASK - 2, true); 5046 5013 if (IS_ERR(mapping)) { 5047 5014 err = PTR_ERR(mapping); 5048 5015 goto err_enc_opts_mapping;
+5 -4
drivers/net/ethernet/mellanox/mlx5/core/eq.c
··· 632 632 mlx5_eq_notifier_register(dev, &table->cq_err_nb); 633 633 634 634 param = (struct mlx5_eq_param) { 635 + .irq_index = MLX5_IRQ_EQ_CTRL, 635 636 .nent = MLX5_NUM_CMD_EQE, 636 637 .mask[0] = 1ull << MLX5_EVENT_TYPE_CMD, 637 638 }; ··· 645 644 mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); 646 645 647 646 param = (struct mlx5_eq_param) { 647 + .irq_index = MLX5_IRQ_EQ_CTRL, 648 648 .nent = MLX5_NUM_ASYNC_EQE, 649 649 }; 650 650 ··· 655 653 goto err2; 656 654 657 655 param = (struct mlx5_eq_param) { 656 + .irq_index = MLX5_IRQ_EQ_CTRL, 658 657 .nent = /* TODO: sriov max_vf + */ 1, 659 658 .mask[0] = 1ull << MLX5_EVENT_TYPE_PAGE_REQUEST, 660 659 }; ··· 809 806 ncomp_eqs = table->num_comp_eqs; 810 807 nent = MLX5_COMP_EQ_SIZE; 811 808 for (i = 0; i < ncomp_eqs; i++) { 812 - int vecidx = i + MLX5_IRQ_VEC_COMP_BASE; 813 809 struct mlx5_eq_param param = {}; 810 + int vecidx = i; 814 811 815 812 eq = kzalloc(sizeof(*eq), GFP_KERNEL); 816 813 if (!eq) { ··· 956 953 goto err_out; 957 954 } 958 955 959 - vecidx = MLX5_IRQ_VEC_COMP_BASE; 960 - for (; vecidx < eq_table->num_comp_eqs + MLX5_IRQ_VEC_COMP_BASE; 961 - vecidx++) { 956 + for (vecidx = 0; vecidx < eq_table->num_comp_eqs; vecidx++) { 962 957 err = irq_cpu_rmap_add(eq_table->rmap, 963 958 pci_irq_vector(mdev->pdev, vecidx)); 964 959 if (err) {
+201 -26
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
··· 28 28 #define MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_TO (MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE / 2 - 1) 29 29 #define MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_FROM \ 30 30 (MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_TO + 1) 31 - #define MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_TO (MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE - 1) 31 + #define MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_TO (MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE - 2) 32 + #define MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_FROM \ 33 + (MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_TO + 1) 34 + #define MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_TO (MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE - 1) 32 35 33 36 #define MLX5_ESW_BRIDGE_SKIP_TABLE_SIZE 0 34 37 ··· 64 61 struct mlx5_flow_table *egress_ft; 65 62 struct mlx5_flow_group *egress_vlan_fg; 66 63 struct mlx5_flow_group *egress_mac_fg; 64 + struct mlx5_flow_group *egress_miss_fg; 65 + struct mlx5_pkt_reformat *egress_miss_pkt_reformat; 66 + struct mlx5_flow_handle *egress_miss_handle; 67 67 unsigned long ageing_time; 68 68 u32 flags; 69 69 }; ··· 90 84 mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr, 91 85 entry->key.vid, 92 86 SWITCHDEV_FDB_DEL_TO_BRIDGE); 87 + } 88 + 89 + static bool mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(struct mlx5_eswitch *esw) 90 + { 91 + return BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat_remove)) && 92 + MLX5_CAP_GEN_2(esw->dev, max_reformat_remove_size) >= sizeof(struct vlan_hdr) && 93 + MLX5_CAP_GEN_2(esw->dev, max_reformat_remove_offset) >= 94 + offsetof(struct vlan_ethhdr, h_vlan_proto); 95 + } 96 + 97 + static struct mlx5_pkt_reformat * 98 + mlx5_esw_bridge_pkt_reformat_vlan_pop_create(struct mlx5_eswitch *esw) 99 + { 100 + struct mlx5_pkt_reformat_params reformat_params = {}; 101 + 102 + reformat_params.type = MLX5_REFORMAT_TYPE_REMOVE_HDR; 103 + reformat_params.param_0 = MLX5_REFORMAT_CONTEXT_ANCHOR_MAC_START; 104 + reformat_params.param_1 = offsetof(struct vlan_ethhdr, h_vlan_proto); 105 + reformat_params.size = sizeof(struct vlan_hdr); 106 + return mlx5_packet_reformat_alloc(esw->dev, &reformat_params, MLX5_FLOW_NAMESPACE_FDB); 93 107 } 94 108 95 109 static struct mlx5_flow_table * ··· 313 287 return fg; 314 288 } 315 289 290 + static struct mlx5_flow_group * 291 + mlx5_esw_bridge_egress_miss_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft) 292 + { 293 + int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 294 + struct mlx5_flow_group *fg; 295 + u32 *in, *match; 296 + 297 + in = kvzalloc(inlen, GFP_KERNEL); 298 + if (!in) 299 + return ERR_PTR(-ENOMEM); 300 + 301 + MLX5_SET(create_flow_group_in, in, match_criteria_enable, MLX5_MATCH_MISC_PARAMETERS_2); 302 + match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 303 + 304 + MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK); 305 + 306 + MLX5_SET(create_flow_group_in, in, start_flow_index, 307 + MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_FROM); 308 + MLX5_SET(create_flow_group_in, in, end_flow_index, 309 + MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_TO); 310 + 311 + fg = mlx5_create_flow_group(egress_ft, in); 312 + if (IS_ERR(fg)) 313 + esw_warn(esw->dev, 314 + "Failed to create bridge egress table miss flow group (err=%ld)\n", 315 + PTR_ERR(fg)); 316 + kvfree(in); 317 + return fg; 318 + } 319 + 316 320 static int 317 321 mlx5_esw_bridge_ingress_table_init(struct mlx5_esw_bridge_offloads *br_offloads) 318 322 { 319 323 struct mlx5_flow_group *mac_fg, *filter_fg, *vlan_fg; 320 324 struct mlx5_flow_table *ingress_ft, *skip_ft; 325 + struct mlx5_eswitch *esw = br_offloads->esw; 321 326 int err; 322 327 323 - if (!mlx5_eswitch_vport_match_metadata_enabled(br_offloads->esw)) 328 + if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) 324 329 return -EOPNOTSUPP; 325 330 326 331 ingress_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE, 327 332 MLX5_ESW_BRIDGE_LEVEL_INGRESS_TABLE, 328 - br_offloads->esw); 333 + esw); 329 334 if (IS_ERR(ingress_ft)) 330 335 return PTR_ERR(ingress_ft); 331 336 332 337 skip_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_SKIP_TABLE_SIZE, 333 338 MLX5_ESW_BRIDGE_LEVEL_SKIP_TABLE, 334 - br_offloads->esw); 339 + esw); 335 340 if (IS_ERR(skip_ft)) { 336 341 err = PTR_ERR(skip_ft); 337 342 goto err_skip_tbl; 338 343 } 339 344 340 - vlan_fg = mlx5_esw_bridge_ingress_vlan_fg_create(br_offloads->esw, ingress_ft); 345 + vlan_fg = mlx5_esw_bridge_ingress_vlan_fg_create(esw, ingress_ft); 341 346 if (IS_ERR(vlan_fg)) { 342 347 err = PTR_ERR(vlan_fg); 343 348 goto err_vlan_fg; 344 349 } 345 350 346 - filter_fg = mlx5_esw_bridge_ingress_filter_fg_create(br_offloads->esw, ingress_ft); 351 + filter_fg = mlx5_esw_bridge_ingress_filter_fg_create(esw, ingress_ft); 347 352 if (IS_ERR(filter_fg)) { 348 353 err = PTR_ERR(filter_fg); 349 354 goto err_filter_fg; 350 355 } 351 356 352 - mac_fg = mlx5_esw_bridge_ingress_mac_fg_create(br_offloads->esw, ingress_ft); 357 + mac_fg = mlx5_esw_bridge_ingress_mac_fg_create(esw, ingress_ft); 353 358 if (IS_ERR(mac_fg)) { 354 359 err = PTR_ERR(mac_fg); 355 360 goto err_mac_fg; ··· 419 362 br_offloads->ingress_ft = NULL; 420 363 } 421 364 365 + static struct mlx5_flow_handle * 366 + mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft, 367 + struct mlx5_flow_table *skip_ft, 368 + struct mlx5_pkt_reformat *pkt_reformat); 369 + 422 370 static int 423 371 mlx5_esw_bridge_egress_table_init(struct mlx5_esw_bridge_offloads *br_offloads, 424 372 struct mlx5_esw_bridge *bridge) 425 373 { 426 - struct mlx5_flow_group *mac_fg, *vlan_fg; 374 + struct mlx5_flow_group *miss_fg = NULL, *mac_fg, *vlan_fg; 375 + struct mlx5_pkt_reformat *miss_pkt_reformat = NULL; 376 + struct mlx5_flow_handle *miss_handle = NULL; 377 + struct mlx5_eswitch *esw = br_offloads->esw; 427 378 struct mlx5_flow_table *egress_ft; 428 379 int err; 429 380 430 381 egress_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE, 431 382 MLX5_ESW_BRIDGE_LEVEL_EGRESS_TABLE, 432 - br_offloads->esw); 383 + esw); 433 384 if (IS_ERR(egress_ft)) 434 385 return PTR_ERR(egress_ft); 435 386 436 - vlan_fg = mlx5_esw_bridge_egress_vlan_fg_create(br_offloads->esw, egress_ft); 387 + vlan_fg = mlx5_esw_bridge_egress_vlan_fg_create(esw, egress_ft); 437 388 if (IS_ERR(vlan_fg)) { 438 389 err = PTR_ERR(vlan_fg); 439 390 goto err_vlan_fg; 440 391 } 441 392 442 - mac_fg = mlx5_esw_bridge_egress_mac_fg_create(br_offloads->esw, egress_ft); 393 + mac_fg = mlx5_esw_bridge_egress_mac_fg_create(esw, egress_ft); 443 394 if (IS_ERR(mac_fg)) { 444 395 err = PTR_ERR(mac_fg); 445 396 goto err_mac_fg; 446 397 } 447 398 399 + if (mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(esw)) { 400 + miss_fg = mlx5_esw_bridge_egress_miss_fg_create(esw, egress_ft); 401 + if (IS_ERR(miss_fg)) { 402 + esw_warn(esw->dev, "Failed to create miss flow group (err=%ld)\n", 403 + PTR_ERR(miss_fg)); 404 + miss_fg = NULL; 405 + goto skip_miss_flow; 406 + } 407 + 408 + miss_pkt_reformat = mlx5_esw_bridge_pkt_reformat_vlan_pop_create(esw); 409 + if (IS_ERR(miss_pkt_reformat)) { 410 + esw_warn(esw->dev, 411 + "Failed to alloc packet reformat REMOVE_HEADER (err=%ld)\n", 412 + PTR_ERR(miss_pkt_reformat)); 413 + miss_pkt_reformat = NULL; 414 + mlx5_destroy_flow_group(miss_fg); 415 + miss_fg = NULL; 416 + goto skip_miss_flow; 417 + } 418 + 419 + miss_handle = mlx5_esw_bridge_egress_miss_flow_create(egress_ft, 420 + br_offloads->skip_ft, 421 + miss_pkt_reformat); 422 + if (IS_ERR(miss_handle)) { 423 + esw_warn(esw->dev, "Failed to create miss flow (err=%ld)\n", 424 + PTR_ERR(miss_handle)); 425 + miss_handle = NULL; 426 + mlx5_packet_reformat_dealloc(esw->dev, miss_pkt_reformat); 427 + miss_pkt_reformat = NULL; 428 + mlx5_destroy_flow_group(miss_fg); 429 + miss_fg = NULL; 430 + goto skip_miss_flow; 431 + } 432 + } 433 + skip_miss_flow: 434 + 448 435 bridge->egress_ft = egress_ft; 449 436 bridge->egress_vlan_fg = vlan_fg; 450 437 bridge->egress_mac_fg = mac_fg; 438 + bridge->egress_miss_fg = miss_fg; 439 + bridge->egress_miss_pkt_reformat = miss_pkt_reformat; 440 + bridge->egress_miss_handle = miss_handle; 451 441 return 0; 452 442 453 443 err_mac_fg: ··· 507 403 static void 508 404 mlx5_esw_bridge_egress_table_cleanup(struct mlx5_esw_bridge *bridge) 509 405 { 406 + if (bridge->egress_miss_handle) 407 + mlx5_del_flow_rules(bridge->egress_miss_handle); 408 + if (bridge->egress_miss_pkt_reformat) 409 + mlx5_packet_reformat_dealloc(bridge->br_offloads->esw->dev, 410 + bridge->egress_miss_pkt_reformat); 411 + if (bridge->egress_miss_fg) 412 + mlx5_destroy_flow_group(bridge->egress_miss_fg); 510 413 mlx5_destroy_flow_group(bridge->egress_mac_fg); 511 414 mlx5_destroy_flow_group(bridge->egress_vlan_fg); 512 415 mlx5_destroy_flow_table(bridge->egress_ft); ··· 554 443 mlx5_eswitch_get_vport_metadata_for_match(esw, vport_num)); 555 444 556 445 if (vlan && vlan->pkt_reformat_push) { 557 - flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; 446 + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT | 447 + MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 558 448 flow_act.pkt_reformat = vlan->pkt_reformat_push; 449 + flow_act.modify_hdr = vlan->pkt_mod_hdr_push_mark; 559 450 } else if (vlan) { 560 451 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria, 561 452 outer_headers.cvlan_tag); ··· 707 594 dest.vport.vhca_id = esw_owner_vhca_id; 708 595 } 709 596 handle = mlx5_add_flow_rules(bridge->egress_ft, rule_spec, &flow_act, &dest, 1); 597 + 598 + kvfree(rule_spec); 599 + return handle; 600 + } 601 + 602 + static struct mlx5_flow_handle * 603 + mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft, 604 + struct mlx5_flow_table *skip_ft, 605 + struct mlx5_pkt_reformat *pkt_reformat) 606 + { 607 + struct mlx5_flow_destination dest = { 608 + .type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE, 609 + .ft = skip_ft, 610 + }; 611 + struct mlx5_flow_act flow_act = { 612 + .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 613 + MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT, 614 + .flags = FLOW_ACT_NO_APPEND, 615 + .pkt_reformat = pkt_reformat, 616 + }; 617 + struct mlx5_flow_spec *rule_spec; 618 + struct mlx5_flow_handle *handle; 619 + 620 + rule_spec = kvzalloc(sizeof(*rule_spec), GFP_KERNEL); 621 + if (!rule_spec) 622 + return ERR_PTR(-ENOMEM); 623 + 624 + rule_spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; 625 + 626 + MLX5_SET(fte_match_param, rule_spec->match_criteria, 627 + misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK); 628 + MLX5_SET(fte_match_param, rule_spec->match_value, misc_parameters_2.metadata_reg_c_1, 629 + ESW_TUN_BRIDGE_INGRESS_PUSH_VLAN_MARK); 630 + 631 + handle = mlx5_add_flow_rules(egress_ft, rule_spec, &flow_act, &dest, 1); 710 632 711 633 kvfree(rule_spec); 712 634 return handle; ··· 946 798 static int 947 799 mlx5_esw_bridge_vlan_pop_create(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw) 948 800 { 949 - struct mlx5_pkt_reformat_params reformat_params = {}; 950 801 struct mlx5_pkt_reformat *pkt_reformat; 951 802 952 - if (!BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat_remove)) || 953 - MLX5_CAP_GEN_2(esw->dev, max_reformat_remove_size) < sizeof(struct vlan_hdr) || 954 - MLX5_CAP_GEN_2(esw->dev, max_reformat_remove_offset) < 955 - offsetof(struct vlan_ethhdr, h_vlan_proto)) { 803 + if (!mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(esw)) { 956 804 esw_warn(esw->dev, "Packet reformat REMOVE_HEADER is not supported\n"); 957 805 return -EOPNOTSUPP; 958 806 } 959 807 960 - reformat_params.type = MLX5_REFORMAT_TYPE_REMOVE_HDR; 961 - reformat_params.param_0 = MLX5_REFORMAT_CONTEXT_ANCHOR_MAC_START; 962 - reformat_params.param_1 = offsetof(struct vlan_ethhdr, h_vlan_proto); 963 - reformat_params.size = sizeof(struct vlan_hdr); 964 - pkt_reformat = mlx5_packet_reformat_alloc(esw->dev, 965 - &reformat_params, 966 - MLX5_FLOW_NAMESPACE_FDB); 808 + pkt_reformat = mlx5_esw_bridge_pkt_reformat_vlan_pop_create(esw); 967 809 if (IS_ERR(pkt_reformat)) { 968 810 esw_warn(esw->dev, "Failed to alloc packet reformat REMOVE_HEADER (err=%ld)\n", 969 811 PTR_ERR(pkt_reformat)); ··· 969 831 { 970 832 mlx5_packet_reformat_dealloc(esw->dev, vlan->pkt_reformat_pop); 971 833 vlan->pkt_reformat_pop = NULL; 834 + } 835 + 836 + static int 837 + mlx5_esw_bridge_vlan_push_mark_create(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw) 838 + { 839 + u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; 840 + struct mlx5_modify_hdr *pkt_mod_hdr; 841 + 842 + MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); 843 + MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_C_1); 844 + MLX5_SET(set_action_in, action, offset, 8); 845 + MLX5_SET(set_action_in, action, length, ESW_TUN_OPTS_BITS + ESW_TUN_ID_BITS); 846 + MLX5_SET(set_action_in, action, data, ESW_TUN_BRIDGE_INGRESS_PUSH_VLAN); 847 + 848 + pkt_mod_hdr = mlx5_modify_header_alloc(esw->dev, MLX5_FLOW_NAMESPACE_FDB, 1, action); 849 + if (IS_ERR(pkt_mod_hdr)) 850 + return PTR_ERR(pkt_mod_hdr); 851 + 852 + vlan->pkt_mod_hdr_push_mark = pkt_mod_hdr; 853 + return 0; 854 + } 855 + 856 + static void 857 + mlx5_esw_bridge_vlan_push_mark_cleanup(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw) 858 + { 859 + mlx5_modify_header_dealloc(esw->dev, vlan->pkt_mod_hdr_push_mark); 860 + vlan->pkt_mod_hdr_push_mark = NULL; 972 861 } 973 862 974 863 static struct mlx5_esw_bridge_vlan * ··· 1017 852 err = mlx5_esw_bridge_vlan_push_create(vlan, esw); 1018 853 if (err) 1019 854 goto err_vlan_push; 855 + 856 + err = mlx5_esw_bridge_vlan_push_mark_create(vlan, esw); 857 + if (err) 858 + goto err_vlan_push_mark; 1020 859 } 1021 860 if (flags & BRIDGE_VLAN_INFO_UNTAGGED) { 1022 861 err = mlx5_esw_bridge_vlan_pop_create(vlan, esw); ··· 1039 870 if (vlan->pkt_reformat_pop) 1040 871 mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw); 1041 872 err_vlan_pop: 873 + if (vlan->pkt_mod_hdr_push_mark) 874 + mlx5_esw_bridge_vlan_push_mark_cleanup(vlan, esw); 875 + err_vlan_push_mark: 1042 876 if (vlan->pkt_reformat_push) 1043 877 mlx5_esw_bridge_vlan_push_cleanup(vlan, esw); 1044 878 err_vlan_push: ··· 1058 886 static void mlx5_esw_bridge_vlan_flush(struct mlx5_esw_bridge_vlan *vlan, 1059 887 struct mlx5_esw_bridge *bridge) 1060 888 { 889 + struct mlx5_eswitch *esw = bridge->br_offloads->esw; 1061 890 struct mlx5_esw_bridge_fdb_entry *entry, *tmp; 1062 891 1063 892 list_for_each_entry_safe(entry, tmp, &vlan->fdb_list, vlan_list) { ··· 1067 894 } 1068 895 1069 896 if (vlan->pkt_reformat_pop) 1070 - mlx5_esw_bridge_vlan_pop_cleanup(vlan, bridge->br_offloads->esw); 897 + mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw); 898 + if (vlan->pkt_mod_hdr_push_mark) 899 + mlx5_esw_bridge_vlan_push_mark_cleanup(vlan, esw); 1071 900 if (vlan->pkt_reformat_push) 1072 - mlx5_esw_bridge_vlan_push_cleanup(vlan, bridge->br_offloads->esw); 901 + mlx5_esw_bridge_vlan_push_cleanup(vlan, esw); 1073 902 } 1074 903 1075 904 static void mlx5_esw_bridge_vlan_cleanup(struct mlx5_esw_bridge_port *port,
+1
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h
··· 49 49 struct list_head fdb_list; 50 50 struct mlx5_pkt_reformat *pkt_reformat_push; 51 51 struct mlx5_pkt_reformat *pkt_reformat_pop; 52 + struct mlx5_modify_hdr *pkt_mod_hdr_push_mark; 52 53 }; 53 54 54 55 struct mlx5_esw_bridge_port {
+8
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
··· 447 447 MLX5_ESW_ATTR_FLAG_NO_IN_PORT = BIT(2), 448 448 MLX5_ESW_ATTR_FLAG_SRC_REWRITE = BIT(3), 449 449 MLX5_ESW_ATTR_FLAG_SAMPLE = BIT(4), 450 + MLX5_ESW_ATTR_FLAG_ACCEPT = BIT(5), 450 451 }; 452 + 453 + /* Returns true if any of the flags that require skipping further TC/NF processing are set. */ 454 + static inline bool 455 + mlx5_esw_attr_flags_skip(u32 attr_flags) 456 + { 457 + return attr_flags & (MLX5_ESW_ATTR_FLAG_SLOW_PATH | MLX5_ESW_ATTR_FLAG_ACCEPT); 458 + } 451 459 452 460 struct mlx5_esw_flow_attr { 453 461 struct mlx5_eswitch_rep *in_rep;
+3 -3
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
··· 440 440 } else if (attr->dest_ft) { 441 441 esw_setup_ft_dest(dest, flow_act, esw, attr, spec, *i); 442 442 (*i)++; 443 - } else if (attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) { 443 + } else if (mlx5_esw_attr_flags_skip(attr->flags)) { 444 444 esw_setup_slow_path_dest(dest, flow_act, chains, *i); 445 445 (*i)++; 446 446 } else if (attr->dest_chain) { ··· 467 467 468 468 if (attr->dest_ft) { 469 469 esw_cleanup_decap_indir(esw, attr); 470 - } else if (!(attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH)) { 470 + } else if (!mlx5_esw_attr_flags_skip(attr->flags)) { 471 471 if (attr->dest_chain) 472 472 esw_cleanup_chain_dest(chains, attr->dest_chain, 1, 0); 473 473 else if (esw_is_indir_table(esw, attr)) ··· 678 678 679 679 mlx5_del_flow_rules(rule); 680 680 681 - if (!(attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH)) { 681 + if (!mlx5_esw_attr_flags_skip(attr->flags)) { 682 682 /* unref the term table */ 683 683 for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) { 684 684 if (esw_attr->dests[i].termtbl)
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c
··· 219 219 220 220 if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, termination_table) || 221 221 !MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ignore_flow_level) || 222 - attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH || 222 + mlx5_esw_attr_flags_skip(attr->flags) || 223 223 !mlx5_eswitch_offload_is_uplink_port(esw, spec)) 224 224 return false; 225 225
-2
drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h
··· 8 8 9 9 #define MLX5_COMP_EQS_PER_SF 8 10 10 11 - #define MLX5_IRQ_EQ_CTRL (0) 12 - 13 11 struct mlx5_irq; 14 12 15 13 int mlx5_irq_table_init(struct mlx5_core_dev *dev);
+24 -12
drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
··· 194 194 snprintf(name, MLX5_MAX_IRQ_NAME, "%s%d", pool->name, vecidx); 195 195 } 196 196 197 - static void irq_set_name(char *name, int vecidx) 197 + static void irq_set_name(struct mlx5_irq_pool *pool, char *name, int vecidx) 198 198 { 199 - if (vecidx == 0) { 199 + if (!pool->xa_num_irqs.max) { 200 + /* in case we only have a single irq for the device */ 201 + snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_combined%d", vecidx); 202 + return; 203 + } 204 + 205 + if (vecidx == pool->xa_num_irqs.max) { 200 206 snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_async%d", vecidx); 201 207 return; 202 208 } 203 209 204 - snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", 205 - vecidx - MLX5_IRQ_VEC_COMP_BASE); 210 + snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", vecidx); 211 + } 212 + 213 + static bool irq_pool_is_sf_pool(struct mlx5_irq_pool *pool) 214 + { 215 + return !strncmp("mlx5_sf", pool->name, strlen("mlx5_sf")); 206 216 } 207 217 208 218 static struct mlx5_irq *irq_request(struct mlx5_irq_pool *pool, int i) ··· 226 216 if (!irq) 227 217 return ERR_PTR(-ENOMEM); 228 218 irq->irqn = pci_irq_vector(dev->pdev, i); 229 - if (!pool->name[0]) 230 - irq_set_name(name, i); 219 + if (!irq_pool_is_sf_pool(pool)) 220 + irq_set_name(pool, name, i); 231 221 else 232 222 irq_sf_set_name(pool, name, i); 233 223 ATOMIC_INIT_NOTIFIER_HEAD(&irq->nh); ··· 396 386 if (IS_ERR(irq) || !affinity) 397 387 goto unlock; 398 388 cpumask_copy(irq->mask, affinity); 389 + if (!irq_pool_is_sf_pool(pool) && !pool->xa_num_irqs.max && 390 + cpumask_empty(irq->mask)) 391 + cpumask_set_cpu(0, irq->mask); 399 392 irq_set_affinity_hint(irq->irqn, irq->mask); 400 393 unlock: 401 394 mutex_unlock(&pool->lock); ··· 453 440 } 454 441 pf_irq: 455 442 pool = irq_table->pf_pool; 443 + vecidx = (vecidx == MLX5_IRQ_EQ_CTRL) ? pool->xa_num_irqs.max : vecidx; 456 444 irq = irq_pool_request_vector(pool, vecidx, affinity); 457 445 out: 458 446 if (IS_ERR(irq)) ··· 591 577 592 578 int mlx5_irq_table_get_num_comp(struct mlx5_irq_table *table) 593 579 { 580 + if (!table->pf_pool->xa_num_irqs.max) 581 + return 1; 594 582 return table->pf_pool->xa_num_irqs.max - table->pf_pool->xa_num_irqs.min; 595 583 } 596 584 ··· 608 592 if (mlx5_core_is_sf(dev)) 609 593 return 0; 610 594 611 - pf_vec = MLX5_CAP_GEN(dev, num_ports) * num_online_cpus() + 612 - MLX5_IRQ_VEC_COMP_BASE; 595 + pf_vec = MLX5_CAP_GEN(dev, num_ports) * num_online_cpus() + 1; 613 596 pf_vec = min_t(int, pf_vec, num_eqs); 614 - if (pf_vec <= MLX5_IRQ_VEC_COMP_BASE) 615 - return -ENOMEM; 616 597 617 598 total_vec = pf_vec; 618 599 if (mlx5_sf_max_functions(dev)) 619 600 total_vec += MLX5_IRQ_CTRL_SF_MAX + 620 601 MLX5_COMP_EQS_PER_SF * mlx5_sf_max_functions(dev); 621 602 622 - total_vec = pci_alloc_irq_vectors(dev->pdev, MLX5_IRQ_VEC_COMP_BASE + 1, 623 - total_vec, PCI_IRQ_MSIX); 603 + total_vec = pci_alloc_irq_vectors(dev->pdev, 1, total_vec, PCI_IRQ_MSIX); 624 604 if (total_vec < 0) 625 605 return total_vec; 626 606 pf_vec = min(pf_vec, total_vec);
+2
include/linux/mlx5/driver.h
··· 59 59 60 60 #define MLX5_ADEV_NAME "mlx5_core" 61 61 62 + #define MLX5_IRQ_EQ_CTRL (U8_MAX) 63 + 62 64 enum { 63 65 MLX5_BOARD_ID_LEN = 64, 64 66 };
-1
include/linux/mlx5/eq.h
··· 4 4 #ifndef MLX5_CORE_EQ_H 5 5 #define MLX5_CORE_EQ_H 6 6 7 - #define MLX5_IRQ_VEC_COMP_BASE 1 8 7 #define MLX5_NUM_CMD_EQE (32) 9 8 #define MLX5_NUM_ASYNC_EQE (0x1000) 10 9 #define MLX5_NUM_SPARE_EQE (0x80)
+9
include/linux/mlx5/eswitch.h
··· 130 130 #define ESW_TUN_OPTS_MASK GENMASK(31 - ESW_TUN_ID_BITS - ESW_RESERVED_BITS, ESW_TUN_OPTS_OFFSET) 131 131 #define ESW_TUN_MASK GENMASK(31 - ESW_RESERVED_BITS, ESW_TUN_OFFSET) 132 132 #define ESW_TUN_ID_SLOW_TABLE_GOTO_VPORT 0 /* 0 is not a valid tunnel id */ 133 + #define ESW_TUN_ID_BRIDGE_INGRESS_PUSH_VLAN ESW_TUN_ID_SLOW_TABLE_GOTO_VPORT 133 134 /* 0x7FF is a reserved mapping */ 134 135 #define ESW_TUN_OPTS_SLOW_TABLE_GOTO_VPORT GENMASK(ESW_TUN_OPTS_BITS - 1, 0) 135 136 #define ESW_TUN_SLOW_TABLE_GOTO_VPORT ((ESW_TUN_ID_SLOW_TABLE_GOTO_VPORT << ESW_TUN_OPTS_BITS) | \ 136 137 ESW_TUN_OPTS_SLOW_TABLE_GOTO_VPORT) 137 138 #define ESW_TUN_SLOW_TABLE_GOTO_VPORT_MARK ESW_TUN_OPTS_MASK 139 + /* 0x7FE is a reserved mapping for bridge ingress push vlan mark */ 140 + #define ESW_TUN_OPTS_BRIDGE_INGRESS_PUSH_VLAN (ESW_TUN_OPTS_SLOW_TABLE_GOTO_VPORT - 1) 141 + #define ESW_TUN_BRIDGE_INGRESS_PUSH_VLAN ((ESW_TUN_ID_BRIDGE_INGRESS_PUSH_VLAN << \ 142 + ESW_TUN_OPTS_BITS) | \ 143 + ESW_TUN_OPTS_BRIDGE_INGRESS_PUSH_VLAN) 144 + #define ESW_TUN_BRIDGE_INGRESS_PUSH_VLAN_MARK \ 145 + GENMASK(31 - ESW_TUN_ID_BITS - ESW_RESERVED_BITS, \ 146 + ESW_TUN_OPTS_OFFSET + 1) 138 147 139 148 u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev); 140 149 u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev);