brintos

brintos / linux-shallow public Read only

0
0
Text · 4.1 KiB · e80f316 Raw
175 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/* Microchip Sparx5 Switch driver3 *4 * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.5 */6 7#include <net/pkt_cls.h>8#include <net/pkt_sched.h>9 10#include "sparx5_tc.h"11#include "sparx5_main.h"12#include "sparx5_qos.h"13 14/* tc block handling */15static LIST_HEAD(sparx5_block_cb_list);16 17static int sparx5_tc_block_cb(enum tc_setup_type type,18			      void *type_data,19			      void *cb_priv, bool ingress)20{21	struct net_device *ndev = cb_priv;22 23	switch (type) {24	case TC_SETUP_CLSMATCHALL:25		return sparx5_tc_matchall(ndev, type_data, ingress);26	case TC_SETUP_CLSFLOWER:27		return sparx5_tc_flower(ndev, type_data, ingress);28	default:29		return -EOPNOTSUPP;30	}31}32 33static int sparx5_tc_block_cb_ingress(enum tc_setup_type type,34				      void *type_data,35				      void *cb_priv)36{37	return sparx5_tc_block_cb(type, type_data, cb_priv, true);38}39 40static int sparx5_tc_block_cb_egress(enum tc_setup_type type,41				     void *type_data,42				     void *cb_priv)43{44	return sparx5_tc_block_cb(type, type_data, cb_priv, false);45}46 47static int sparx5_tc_setup_block(struct net_device *ndev,48				 struct flow_block_offload *fbo)49{50	flow_setup_cb_t *cb;51 52	if (fbo->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)53		cb = sparx5_tc_block_cb_ingress;54	else if (fbo->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)55		cb = sparx5_tc_block_cb_egress;56	else57		return -EOPNOTSUPP;58 59	return flow_block_cb_setup_simple(fbo, &sparx5_block_cb_list,60					  cb, ndev, ndev, false);61}62 63static void sparx5_tc_get_layer_and_idx(u32 parent, u32 portno, u32 *layer,64					u32 *idx)65{66	if (parent == TC_H_ROOT) {67		*layer = 2;68		*idx = portno;69	} else {70		u32 queue = TC_H_MIN(parent) - 1;71		*layer = 0;72		*idx = SPX5_HSCH_L0_GET_IDX(portno, queue);73	}74}75 76static int sparx5_tc_setup_qdisc_mqprio(struct net_device *ndev,77					struct tc_mqprio_qopt_offload *m)78{79	m->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS;80 81	if (m->qopt.num_tc == 0)82		return sparx5_tc_mqprio_del(ndev);83	else84		return sparx5_tc_mqprio_add(ndev, m->qopt.num_tc);85}86 87static int sparx5_tc_setup_qdisc_tbf(struct net_device *ndev,88				     struct tc_tbf_qopt_offload *qopt)89{90	struct sparx5_port *port = netdev_priv(ndev);91	u32 layer, se_idx;92 93	sparx5_tc_get_layer_and_idx(qopt->parent, port->portno, &layer,94				    &se_idx);95 96	switch (qopt->command) {97	case TC_TBF_REPLACE:98		return sparx5_tc_tbf_add(port, &qopt->replace_params, layer,99					 se_idx);100	case TC_TBF_DESTROY:101		return sparx5_tc_tbf_del(port, layer, se_idx);102	case TC_TBF_STATS:103		return -EOPNOTSUPP;104	default:105		return -EOPNOTSUPP;106	}107 108	return -EOPNOTSUPP;109}110 111static int sparx5_tc_setup_qdisc_ets(struct net_device *ndev,112				     struct tc_ets_qopt_offload *qopt)113{114	struct tc_ets_qopt_offload_replace_params *params =115		&qopt->replace_params;116	struct sparx5_port *port = netdev_priv(ndev);117	int i;118 119	/* Only allow ets on ports  */120	if (qopt->parent != TC_H_ROOT)121		return -EOPNOTSUPP;122 123	switch (qopt->command) {124	case TC_ETS_REPLACE:125 126		/* We support eight priorities */127		if (params->bands != SPX5_PRIOS)128			return -EOPNOTSUPP;129 130		/* Sanity checks */131		for (i = 0; i < SPX5_PRIOS; ++i) {132			/* Priority map is *always* reverse e.g: 7 6 5 .. 0 */133			if (params->priomap[i] != (7 - i))134				return -EOPNOTSUPP;135			/* Throw an error if we receive zero weights by tc */136			if (params->quanta[i] && params->weights[i] == 0) {137				pr_err("Invalid ets configuration; band %d has weight zero",138				       i);139				return -EINVAL;140			}141		}142 143		return sparx5_tc_ets_add(port, params);144	case TC_ETS_DESTROY:145 146		return sparx5_tc_ets_del(port);147	case TC_ETS_GRAFT:148		return -EOPNOTSUPP;149 150	default:151		return -EOPNOTSUPP;152	}153 154	return -EOPNOTSUPP;155}156 157int sparx5_port_setup_tc(struct net_device *ndev, enum tc_setup_type type,158			 void *type_data)159{160	switch (type) {161	case TC_SETUP_BLOCK:162		return sparx5_tc_setup_block(ndev, type_data);163	case TC_SETUP_QDISC_MQPRIO:164		return sparx5_tc_setup_qdisc_mqprio(ndev, type_data);165	case TC_SETUP_QDISC_TBF:166		return sparx5_tc_setup_qdisc_tbf(ndev, type_data);167	case TC_SETUP_QDISC_ETS:168		return sparx5_tc_setup_qdisc_ets(ndev, type_data);169	default:170		return -EOPNOTSUPP;171	}172 173	return 0;174}175