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
8static LIST_HEAD(lan966x_tc_block_cb_list);
9
10static 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
21static 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, qopt: taprio);
27 case TAPRIO_CMD_DESTROY:
28 return lan966x_taprio_del(port);
29 default:
30 return -EOPNOTSUPP;
31 }
32}
33
34static 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
49static 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
56static 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
71static 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, f: type_data, ingress);
79 case TC_SETUP_CLSFLOWER:
80 return lan966x_tc_flower(port, f: type_data, ingress);
81 default:
82 return -EOPNOTSUPP;
83 }
84}
85
86static 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, ingress: true);
90}
91
92static 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, ingress: false);
96}
97
98static 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, driver_list: &lan966x_tc_block_cb_list,
116 cb, cb_ident: port, cb_priv: port, ingress_only: ingress);
117}
118
119int 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, mqprio: type_data);
127 case TC_SETUP_QDISC_TAPRIO:
128 return lan966x_tc_setup_qdisc_taprio(port, taprio: type_data);
129 case TC_SETUP_QDISC_TBF:
130 return lan966x_tc_setup_qdisc_tbf(port, qopt: type_data);
131 case TC_SETUP_QDISC_CBS:
132 return lan966x_tc_setup_qdisc_cbs(port, qopt: type_data);
133 case TC_SETUP_QDISC_ETS:
134 return lan966x_tc_setup_qdisc_ets(port, qopt: type_data);
135 case TC_SETUP_BLOCK:
136 return lan966x_tc_setup_block(port, f: type_data);
137 default:
138 return -EOPNOTSUPP;
139 }
140
141 return 0;
142}
143

source code of linux/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c