]> Git Repo - linux.git/blob - drivers/net/ethernet/microchip/lan966x/lan966x_tc.c
Linux 6.14-rc3
[linux.git] / drivers / net / ethernet / microchip / lan966x / lan966x_tc.c
1 // SPDX-License-Identifier: GPL-2.0+
2
3 #include <net/pkt_cls.h>
4 #include <net/pkt_sched.h>
5
6 #include "lan966x_main.h"
7
8 static LIST_HEAD(lan966x_tc_block_cb_list);
9
10 static int lan966x_tc_setup_qdisc_mqprio(struct lan966x_port *port,
11                                          struct tc_mqprio_qopt_offload *mqprio)
12 {
13         u8 num_tc = mqprio->qopt.num_tc;
14
15         mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS;
16
17         return num_tc ? lan966x_mqprio_add(port, num_tc) :
18                         lan966x_mqprio_del(port);
19 }
20
21 static int lan966x_tc_setup_qdisc_taprio(struct lan966x_port *port,
22                                          struct tc_taprio_qopt_offload *taprio)
23 {
24         switch (taprio->cmd) {
25         case TAPRIO_CMD_REPLACE:
26                 return lan966x_taprio_add(port, taprio);
27         case TAPRIO_CMD_DESTROY:
28                 return lan966x_taprio_del(port);
29         default:
30                 return -EOPNOTSUPP;
31         }
32 }
33
34 static int lan966x_tc_setup_qdisc_tbf(struct lan966x_port *port,
35                                       struct tc_tbf_qopt_offload *qopt)
36 {
37         switch (qopt->command) {
38         case TC_TBF_REPLACE:
39                 return lan966x_tbf_add(port, qopt);
40         case TC_TBF_DESTROY:
41                 return lan966x_tbf_del(port, qopt);
42         default:
43                 return -EOPNOTSUPP;
44         }
45
46         return -EOPNOTSUPP;
47 }
48
49 static int lan966x_tc_setup_qdisc_cbs(struct lan966x_port *port,
50                                       struct tc_cbs_qopt_offload *qopt)
51 {
52         return qopt->enable ? lan966x_cbs_add(port, qopt) :
53                               lan966x_cbs_del(port, qopt);
54 }
55
56 static int lan966x_tc_setup_qdisc_ets(struct lan966x_port *port,
57                                       struct tc_ets_qopt_offload *qopt)
58 {
59         switch (qopt->command) {
60         case TC_ETS_REPLACE:
61                 return lan966x_ets_add(port, qopt);
62         case TC_ETS_DESTROY:
63                 return lan966x_ets_del(port, qopt);
64         default:
65                 return -EOPNOTSUPP;
66         };
67
68         return -EOPNOTSUPP;
69 }
70
71 static int lan966x_tc_block_cb(enum tc_setup_type type, void *type_data,
72                                void *cb_priv, bool ingress)
73 {
74         struct lan966x_port *port = cb_priv;
75
76         switch (type) {
77         case TC_SETUP_CLSMATCHALL:
78                 return lan966x_tc_matchall(port, type_data, ingress);
79         case TC_SETUP_CLSFLOWER:
80                 return lan966x_tc_flower(port, type_data, ingress);
81         default:
82                 return -EOPNOTSUPP;
83         }
84 }
85
86 static int lan966x_tc_block_cb_ingress(enum tc_setup_type type,
87                                        void *type_data, void *cb_priv)
88 {
89         return lan966x_tc_block_cb(type, type_data, cb_priv, true);
90 }
91
92 static int lan966x_tc_block_cb_egress(enum tc_setup_type type,
93                                       void *type_data, void *cb_priv)
94 {
95         return lan966x_tc_block_cb(type, type_data, cb_priv, false);
96 }
97
98 static int lan966x_tc_setup_block(struct lan966x_port *port,
99                                   struct flow_block_offload *f)
100 {
101         flow_setup_cb_t *cb;
102         bool ingress;
103
104         if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
105                 cb = lan966x_tc_block_cb_ingress;
106                 port->tc.ingress_shared_block = f->block_shared;
107                 ingress = true;
108         } else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
109                 cb = lan966x_tc_block_cb_egress;
110                 ingress = false;
111         } else {
112                 return -EOPNOTSUPP;
113         }
114
115         return flow_block_cb_setup_simple(f, &lan966x_tc_block_cb_list,
116                                           cb, port, port, ingress);
117 }
118
119 int lan966x_tc_setup(struct net_device *dev, enum tc_setup_type type,
120                      void *type_data)
121 {
122         struct lan966x_port *port = netdev_priv(dev);
123
124         switch (type) {
125         case TC_SETUP_QDISC_MQPRIO:
126                 return lan966x_tc_setup_qdisc_mqprio(port, type_data);
127         case TC_SETUP_QDISC_TAPRIO:
128                 return lan966x_tc_setup_qdisc_taprio(port, type_data);
129         case TC_SETUP_QDISC_TBF:
130                 return lan966x_tc_setup_qdisc_tbf(port, type_data);
131         case TC_SETUP_QDISC_CBS:
132                 return lan966x_tc_setup_qdisc_cbs(port, type_data);
133         case TC_SETUP_QDISC_ETS:
134                 return lan966x_tc_setup_qdisc_ets(port, type_data);
135         case TC_SETUP_BLOCK:
136                 return lan966x_tc_setup_block(port, type_data);
137         default:
138                 return -EOPNOTSUPP;
139         }
140
141         return 0;
142 }
This page took 0.038307 seconds and 4 git commands to generate.