]> Git Repo - linux.git/blob - drivers/net/ethernet/microchip/sparx5/sparx5_tc.c
crypto: akcipher - Drop sign/verify operations
[linux.git] / drivers / net / ethernet / microchip / sparx5 / sparx5_tc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver
3  *
4  * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
5  */
6
7 #include <net/pkt_cls.h>
8 #include <net/pkt_sched.h>
9
10 #include "sparx5_tc.h"
11 #include "sparx5_main.h"
12 #include "sparx5_qos.h"
13
14 /* tc block handling */
15 static LIST_HEAD(sparx5_block_cb_list);
16
17 static int sparx5_tc_block_cb(enum tc_setup_type type,
18                               void *type_data,
19                               void *cb_priv, bool ingress)
20 {
21         struct net_device *ndev = cb_priv;
22
23         switch (type) {
24         case TC_SETUP_CLSMATCHALL:
25                 return sparx5_tc_matchall(ndev, type_data, ingress);
26         case TC_SETUP_CLSFLOWER:
27                 return sparx5_tc_flower(ndev, type_data, ingress);
28         default:
29                 return -EOPNOTSUPP;
30         }
31 }
32
33 static int sparx5_tc_block_cb_ingress(enum tc_setup_type type,
34                                       void *type_data,
35                                       void *cb_priv)
36 {
37         return sparx5_tc_block_cb(type, type_data, cb_priv, true);
38 }
39
40 static int sparx5_tc_block_cb_egress(enum tc_setup_type type,
41                                      void *type_data,
42                                      void *cb_priv)
43 {
44         return sparx5_tc_block_cb(type, type_data, cb_priv, false);
45 }
46
47 static int sparx5_tc_setup_block(struct net_device *ndev,
48                                  struct flow_block_offload *fbo)
49 {
50         flow_setup_cb_t *cb;
51
52         if (fbo->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
53                 cb = sparx5_tc_block_cb_ingress;
54         else if (fbo->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
55                 cb = sparx5_tc_block_cb_egress;
56         else
57                 return -EOPNOTSUPP;
58
59         return flow_block_cb_setup_simple(fbo, &sparx5_block_cb_list,
60                                           cb, ndev, ndev, false);
61 }
62
63 static void sparx5_tc_get_layer_and_idx(u32 parent, u32 portno, u32 *layer,
64                                         u32 *idx)
65 {
66         if (parent == TC_H_ROOT) {
67                 *layer = 2;
68                 *idx = portno;
69         } else {
70                 u32 queue = TC_H_MIN(parent) - 1;
71                 *layer = 0;
72                 *idx = SPX5_HSCH_L0_GET_IDX(portno, queue);
73         }
74 }
75
76 static int sparx5_tc_setup_qdisc_mqprio(struct net_device *ndev,
77                                         struct tc_mqprio_qopt_offload *m)
78 {
79         m->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS;
80
81         if (m->qopt.num_tc == 0)
82                 return sparx5_tc_mqprio_del(ndev);
83         else
84                 return sparx5_tc_mqprio_add(ndev, m->qopt.num_tc);
85 }
86
87 static int sparx5_tc_setup_qdisc_tbf(struct net_device *ndev,
88                                      struct tc_tbf_qopt_offload *qopt)
89 {
90         struct sparx5_port *port = netdev_priv(ndev);
91         u32 layer, se_idx;
92
93         sparx5_tc_get_layer_and_idx(qopt->parent, port->portno, &layer,
94                                     &se_idx);
95
96         switch (qopt->command) {
97         case TC_TBF_REPLACE:
98                 return sparx5_tc_tbf_add(port, &qopt->replace_params, layer,
99                                          se_idx);
100         case TC_TBF_DESTROY:
101                 return sparx5_tc_tbf_del(port, layer, se_idx);
102         case TC_TBF_STATS:
103                 return -EOPNOTSUPP;
104         default:
105                 return -EOPNOTSUPP;
106         }
107
108         return -EOPNOTSUPP;
109 }
110
111 static int sparx5_tc_setup_qdisc_ets(struct net_device *ndev,
112                                      struct tc_ets_qopt_offload *qopt)
113 {
114         struct tc_ets_qopt_offload_replace_params *params =
115                 &qopt->replace_params;
116         struct sparx5_port *port = netdev_priv(ndev);
117         int i;
118
119         /* Only allow ets on ports  */
120         if (qopt->parent != TC_H_ROOT)
121                 return -EOPNOTSUPP;
122
123         switch (qopt->command) {
124         case TC_ETS_REPLACE:
125
126                 /* We support eight priorities */
127                 if (params->bands != SPX5_PRIOS)
128                         return -EOPNOTSUPP;
129
130                 /* Sanity checks */
131                 for (i = 0; i < SPX5_PRIOS; ++i) {
132                         /* Priority map is *always* reverse e.g: 7 6 5 .. 0 */
133                         if (params->priomap[i] != (7 - i))
134                                 return -EOPNOTSUPP;
135                         /* Throw an error if we receive zero weights by tc */
136                         if (params->quanta[i] && params->weights[i] == 0) {
137                                 pr_err("Invalid ets configuration; band %d has weight zero",
138                                        i);
139                                 return -EINVAL;
140                         }
141                 }
142
143                 return sparx5_tc_ets_add(port, params);
144         case TC_ETS_DESTROY:
145
146                 return sparx5_tc_ets_del(port);
147         case TC_ETS_GRAFT:
148                 return -EOPNOTSUPP;
149
150         default:
151                 return -EOPNOTSUPP;
152         }
153
154         return -EOPNOTSUPP;
155 }
156
157 int sparx5_port_setup_tc(struct net_device *ndev, enum tc_setup_type type,
158                          void *type_data)
159 {
160         switch (type) {
161         case TC_SETUP_BLOCK:
162                 return sparx5_tc_setup_block(ndev, type_data);
163         case TC_SETUP_QDISC_MQPRIO:
164                 return sparx5_tc_setup_qdisc_mqprio(ndev, type_data);
165         case TC_SETUP_QDISC_TBF:
166                 return sparx5_tc_setup_qdisc_tbf(ndev, type_data);
167         case TC_SETUP_QDISC_ETS:
168                 return sparx5_tc_setup_qdisc_ets(ndev, type_data);
169         default:
170                 return -EOPNOTSUPP;
171         }
172
173         return 0;
174 }
This page took 0.041168 seconds and 4 git commands to generate.