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 } 143