143 lines · 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 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, 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, 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 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, 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, 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, &lan966x_tc_block_cb_list,116 cb, port, port, 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, 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}143