ARM: multi_v7_defconfig: Enable support for the ADC thermal sensor
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / esw / acl / egress_lgcy.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2020 Mellanox Technologies Inc. All rights reserved. */
3
4 #include "mlx5_core.h"
5 #include "eswitch.h"
6 #include "helper.h"
7 #include "lgcy.h"
8
9 static void esw_acl_egress_lgcy_rules_destroy(struct mlx5_vport *vport)
10 {
11         esw_acl_egress_vlan_destroy(vport);
12         if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_rule)) {
13                 mlx5_del_flow_rules(vport->egress.legacy.drop_rule);
14                 vport->egress.legacy.drop_rule = NULL;
15         }
16 }
17
18 static int esw_acl_egress_lgcy_groups_create(struct mlx5_eswitch *esw,
19                                              struct mlx5_vport *vport)
20 {
21         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
22         struct mlx5_core_dev *dev = esw->dev;
23         struct mlx5_flow_group *drop_grp;
24         u32 *flow_group_in;
25         int err = 0;
26
27         err = esw_acl_egress_vlan_grp_create(esw, vport);
28         if (err)
29                 return err;
30
31         flow_group_in = kvzalloc(inlen, GFP_KERNEL);
32         if (!flow_group_in) {
33                 err = -ENOMEM;
34                 goto alloc_err;
35         }
36
37         MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
38         MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
39         drop_grp = mlx5_create_flow_group(vport->egress.acl, flow_group_in);
40         if (IS_ERR(drop_grp)) {
41                 err = PTR_ERR(drop_grp);
42                 esw_warn(dev, "Failed to create E-Switch vport[%d] egress drop flow group, err(%d)\n",
43                          vport->vport, err);
44                 goto drop_grp_err;
45         }
46
47         vport->egress.legacy.drop_grp = drop_grp;
48         kvfree(flow_group_in);
49         return 0;
50
51 drop_grp_err:
52         kvfree(flow_group_in);
53 alloc_err:
54         esw_acl_egress_vlan_grp_destroy(vport);
55         return err;
56 }
57
58 static void esw_acl_egress_lgcy_groups_destroy(struct mlx5_vport *vport)
59 {
60         if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_grp)) {
61                 mlx5_destroy_flow_group(vport->egress.legacy.drop_grp);
62                 vport->egress.legacy.drop_grp = NULL;
63         }
64         esw_acl_egress_vlan_grp_destroy(vport);
65 }
66
67 int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw,
68                               struct mlx5_vport *vport)
69 {
70         struct mlx5_flow_destination drop_ctr_dst = {};
71         struct mlx5_flow_destination *dst = NULL;
72         struct mlx5_fc *drop_counter = NULL;
73         struct mlx5_flow_act flow_act = {};
74         /* The egress acl table contains 2 rules:
75          * 1)Allow traffic with vlan_tag=vst_vlan_id
76          * 2)Drop all other traffic.
77          */
78         int table_size = 2;
79         int dest_num = 0;
80         int err = 0;
81
82         if (MLX5_CAP_ESW_EGRESS_ACL(esw->dev, flow_counter)) {
83                 drop_counter = mlx5_fc_create(esw->dev, false);
84                 if (IS_ERR(drop_counter))
85                         esw_warn(esw->dev,
86                                  "vport[%d] configure egress drop rule counter err(%ld)\n",
87                                  vport->vport, PTR_ERR(drop_counter));
88                 vport->egress.legacy.drop_counter = drop_counter;
89         }
90
91         esw_acl_egress_lgcy_rules_destroy(vport);
92
93         if (!vport->info.vlan && !vport->info.qos) {
94                 esw_acl_egress_lgcy_cleanup(esw, vport);
95                 return 0;
96         }
97
98         if (!IS_ERR_OR_NULL(vport->egress.acl))
99                 return 0;
100
101         vport->egress.acl = esw_acl_table_create(esw, vport->vport,
102                                                  MLX5_FLOW_NAMESPACE_ESW_EGRESS,
103                                                  table_size);
104         if (IS_ERR(vport->egress.acl)) {
105                 err = PTR_ERR(vport->egress.acl);
106                 vport->egress.acl = NULL;
107                 goto out;
108         }
109
110         err = esw_acl_egress_lgcy_groups_create(esw, vport);
111         if (err)
112                 goto out;
113
114         esw_debug(esw->dev,
115                   "vport[%d] configure egress rules, vlan(%d) qos(%d)\n",
116                   vport->vport, vport->info.vlan, vport->info.qos);
117
118         /* Allowed vlan rule */
119         err = esw_egress_acl_vlan_create(esw, vport, NULL, vport->info.vlan,
120                                          MLX5_FLOW_CONTEXT_ACTION_ALLOW);
121         if (err)
122                 goto out;
123
124         flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
125
126         /* Attach egress drop flow counter */
127         if (!IS_ERR_OR_NULL(drop_counter)) {
128                 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
129                 drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
130                 drop_ctr_dst.counter_id = mlx5_fc_id(drop_counter);
131                 dst = &drop_ctr_dst;
132                 dest_num++;
133         }
134         vport->egress.legacy.drop_rule =
135                 mlx5_add_flow_rules(vport->egress.acl, NULL,
136                                     &flow_act, dst, dest_num);
137         if (IS_ERR(vport->egress.legacy.drop_rule)) {
138                 err = PTR_ERR(vport->egress.legacy.drop_rule);
139                 esw_warn(esw->dev,
140                          "vport[%d] configure egress drop rule failed, err(%d)\n",
141                          vport->vport, err);
142                 vport->egress.legacy.drop_rule = NULL;
143                 goto out;
144         }
145
146         return err;
147
148 out:
149         esw_acl_egress_lgcy_cleanup(esw, vport);
150         return err;
151 }
152
153 void esw_acl_egress_lgcy_cleanup(struct mlx5_eswitch *esw,
154                                  struct mlx5_vport *vport)
155 {
156         if (IS_ERR_OR_NULL(vport->egress.acl))
157                 goto clean_drop_counter;
158
159         esw_debug(esw->dev, "Destroy vport[%d] E-Switch egress ACL\n", vport->vport);
160
161         esw_acl_egress_lgcy_rules_destroy(vport);
162         esw_acl_egress_lgcy_groups_destroy(vport);
163         esw_acl_egress_table_destroy(vport);
164
165 clean_drop_counter:
166         if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter)) {
167                 mlx5_fc_destroy(esw->dev, vport->egress.legacy.drop_counter);
168                 vport->egress.legacy.drop_counter = NULL;
169         }
170 }