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
lan966x_tc_setup_qdisc_mqprio(struct lan966x_port * port,struct tc_mqprio_qopt_offload * mqprio)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
lan966x_tc_setup_qdisc_taprio(struct lan966x_port * port,struct tc_taprio_qopt_offload * taprio)21 static int lan966x_tc_setup_qdisc_taprio(struct lan966x_port *port,
22 struct tc_taprio_qopt_offload *taprio)
23 {
24 return taprio->enable ? lan966x_taprio_add(port, taprio) :
25 lan966x_taprio_del(port);
26 }
27
lan966x_tc_setup_qdisc_tbf(struct lan966x_port * port,struct tc_tbf_qopt_offload * qopt)28 static int lan966x_tc_setup_qdisc_tbf(struct lan966x_port *port,
29 struct tc_tbf_qopt_offload *qopt)
30 {
31 switch (qopt->command) {
32 case TC_TBF_REPLACE:
33 return lan966x_tbf_add(port, qopt);
34 case TC_TBF_DESTROY:
35 return lan966x_tbf_del(port, qopt);
36 default:
37 return -EOPNOTSUPP;
38 }
39
40 return -EOPNOTSUPP;
41 }
42
lan966x_tc_setup_qdisc_cbs(struct lan966x_port * port,struct tc_cbs_qopt_offload * qopt)43 static int lan966x_tc_setup_qdisc_cbs(struct lan966x_port *port,
44 struct tc_cbs_qopt_offload *qopt)
45 {
46 return qopt->enable ? lan966x_cbs_add(port, qopt) :
47 lan966x_cbs_del(port, qopt);
48 }
49
lan966x_tc_setup_qdisc_ets(struct lan966x_port * port,struct tc_ets_qopt_offload * qopt)50 static int lan966x_tc_setup_qdisc_ets(struct lan966x_port *port,
51 struct tc_ets_qopt_offload *qopt)
52 {
53 switch (qopt->command) {
54 case TC_ETS_REPLACE:
55 return lan966x_ets_add(port, qopt);
56 case TC_ETS_DESTROY:
57 return lan966x_ets_del(port, qopt);
58 default:
59 return -EOPNOTSUPP;
60 };
61
62 return -EOPNOTSUPP;
63 }
64
lan966x_tc_block_cb(enum tc_setup_type type,void * type_data,void * cb_priv,bool ingress)65 static int lan966x_tc_block_cb(enum tc_setup_type type, void *type_data,
66 void *cb_priv, bool ingress)
67 {
68 struct lan966x_port *port = cb_priv;
69
70 switch (type) {
71 case TC_SETUP_CLSMATCHALL:
72 return lan966x_tc_matchall(port, type_data, ingress);
73 case TC_SETUP_CLSFLOWER:
74 return lan966x_tc_flower(port, type_data, ingress);
75 default:
76 return -EOPNOTSUPP;
77 }
78 }
79
lan966x_tc_block_cb_ingress(enum tc_setup_type type,void * type_data,void * cb_priv)80 static int lan966x_tc_block_cb_ingress(enum tc_setup_type type,
81 void *type_data, void *cb_priv)
82 {
83 return lan966x_tc_block_cb(type, type_data, cb_priv, true);
84 }
85
lan966x_tc_block_cb_egress(enum tc_setup_type type,void * type_data,void * cb_priv)86 static int lan966x_tc_block_cb_egress(enum tc_setup_type type,
87 void *type_data, void *cb_priv)
88 {
89 return lan966x_tc_block_cb(type, type_data, cb_priv, false);
90 }
91
lan966x_tc_setup_block(struct lan966x_port * port,struct flow_block_offload * f)92 static int lan966x_tc_setup_block(struct lan966x_port *port,
93 struct flow_block_offload *f)
94 {
95 flow_setup_cb_t *cb;
96 bool ingress;
97
98 if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
99 cb = lan966x_tc_block_cb_ingress;
100 port->tc.ingress_shared_block = f->block_shared;
101 ingress = true;
102 } else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
103 cb = lan966x_tc_block_cb_egress;
104 ingress = false;
105 } else {
106 return -EOPNOTSUPP;
107 }
108
109 return flow_block_cb_setup_simple(f, &lan966x_tc_block_cb_list,
110 cb, port, port, ingress);
111 }
112
lan966x_tc_setup(struct net_device * dev,enum tc_setup_type type,void * type_data)113 int lan966x_tc_setup(struct net_device *dev, enum tc_setup_type type,
114 void *type_data)
115 {
116 struct lan966x_port *port = netdev_priv(dev);
117
118 switch (type) {
119 case TC_SETUP_QDISC_MQPRIO:
120 return lan966x_tc_setup_qdisc_mqprio(port, type_data);
121 case TC_SETUP_QDISC_TAPRIO:
122 return lan966x_tc_setup_qdisc_taprio(port, type_data);
123 case TC_SETUP_QDISC_TBF:
124 return lan966x_tc_setup_qdisc_tbf(port, type_data);
125 case TC_SETUP_QDISC_CBS:
126 return lan966x_tc_setup_qdisc_cbs(port, type_data);
127 case TC_SETUP_QDISC_ETS:
128 return lan966x_tc_setup_qdisc_ets(port, type_data);
129 case TC_SETUP_BLOCK:
130 return lan966x_tc_setup_block(port, type_data);
131 default:
132 return -EOPNOTSUPP;
133 }
134
135 return 0;
136 }
137