Skip to content

Commit 96f17e0

Browse files
Nogah Frankeldavem330
authored andcommitted
mlxsw: spectrum: Support RED qdisc offload
Add support for ndo_setup_tc with enum tc_setup_type value of TC_SETUP_RED. This call sets RED qdisc on a traffic class. This patch supports RED qdisc only as a root qdisc and set in on the default tclass. It can be set with or without ECN. Signed-off-by: Yuval Mintz <yuvalm@mellanox.com> Signed-off-by: Nogah Frankel <nogahf@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent ad53fa0 commit 96f17e0

File tree

4 files changed

+193
-1
lines changed

4 files changed

+193
-1
lines changed

drivers/net/ethernet/mellanox/mlxsw/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \
1919
spectrum_acl.o spectrum_flower.o \
2020
spectrum_cnt.o spectrum_fid.o \
2121
spectrum_ipip.o spectrum_acl_flex_actions.o \
22-
spectrum_mr.o spectrum_mr_tcam.o
22+
spectrum_mr.o spectrum_mr_tcam.o \
23+
spectrum_qdisc.o
2324
mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB) += spectrum_dcb.o
2425
mlxsw_spectrum-$(CONFIG_NET_DEVLINK) += spectrum_dpipe.o
2526
obj-$(CONFIG_MLXSW_MINIMAL) += mlxsw_minimal.o

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,6 +1797,8 @@ static int mlxsw_sp_setup_tc(struct net_device *dev, enum tc_setup_type type,
17971797
switch (type) {
17981798
case TC_SETUP_BLOCK:
17991799
return mlxsw_sp_setup_tc_block(mlxsw_sp_port, type_data);
1800+
case TC_SETUP_QDISC_RED:
1801+
return mlxsw_sp_setup_tc_red(mlxsw_sp_port, type_data);
18001802
default:
18011803
return -EOPNOTSUPP;
18021804
}

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,16 @@ struct mlxsw_sp_port_vlan {
203203
struct list_head bridge_vlan_node;
204204
};
205205

206+
enum mlxsw_sp_qdisc_type {
207+
MLXSW_SP_QDISC_NO_QDISC,
208+
MLXSW_SP_QDISC_RED,
209+
};
210+
211+
struct mlxsw_sp_qdisc {
212+
u32 handle;
213+
enum mlxsw_sp_qdisc_type type;
214+
};
215+
206216
struct mlxsw_sp_port {
207217
struct net_device *dev;
208218
struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats;
@@ -236,6 +246,7 @@ struct mlxsw_sp_port {
236246
} periodic_hw_stats;
237247
struct mlxsw_sp_port_sample *sample;
238248
struct list_head vlans_list;
249+
struct mlxsw_sp_qdisc root_qdisc;
239250
};
240251

241252
static inline bool
@@ -546,6 +557,10 @@ void mlxsw_sp_flower_destroy(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
546557
int mlxsw_sp_flower_stats(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
547558
struct tc_cls_flower_offload *f);
548559

560+
/* spectrum_qdisc.c */
561+
int mlxsw_sp_setup_tc_red(struct mlxsw_sp_port *mlxsw_sp_port,
562+
struct tc_red_qopt_offload *p);
563+
549564
/* spectrum_fid.c */
550565
int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
551566
enum mlxsw_sp_flood_type packet_type, u8 local_port,
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/*
2+
* drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
3+
* Copyright (c) 2017 Mellanox Technologies. All rights reserved.
4+
* Copyright (c) 2017 Nogah Frankel <nogahf@mellanox.com>
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
* 3. Neither the names of the copyright holders nor the names of its
15+
* contributors may be used to endorse or promote products derived from
16+
* this software without specific prior written permission.
17+
*
18+
* Alternatively, this software may be distributed under the terms of the
19+
* GNU General Public License ("GPL") version 2 as published by the Free
20+
* Software Foundation.
21+
*
22+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32+
* POSSIBILITY OF SUCH DAMAGE.
33+
*/
34+
35+
#include <linux/kernel.h>
36+
#include <linux/errno.h>
37+
#include <linux/netdevice.h>
38+
#include <net/pkt_cls.h>
39+
40+
#include "spectrum.h"
41+
#include "reg.h"
42+
43+
static int
44+
mlxsw_sp_tclass_congestion_enable(struct mlxsw_sp_port *mlxsw_sp_port,
45+
int tclass_num, u32 min, u32 max,
46+
u32 probability, bool is_ecn)
47+
{
48+
char cwtp_cmd[max_t(u8, MLXSW_REG_CWTP_LEN, MLXSW_REG_CWTPM_LEN)];
49+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
50+
int err;
51+
52+
mlxsw_reg_cwtp_pack(cwtp_cmd, mlxsw_sp_port->local_port, tclass_num);
53+
mlxsw_reg_cwtp_profile_pack(cwtp_cmd, MLXSW_REG_CWTP_DEFAULT_PROFILE,
54+
roundup(min, MLXSW_REG_CWTP_MIN_VALUE),
55+
roundup(max, MLXSW_REG_CWTP_MIN_VALUE),
56+
probability);
57+
58+
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(cwtp), cwtp_cmd);
59+
if (err)
60+
return err;
61+
62+
mlxsw_reg_cwtpm_pack(cwtp_cmd, mlxsw_sp_port->local_port, tclass_num,
63+
MLXSW_REG_CWTP_DEFAULT_PROFILE, true, is_ecn);
64+
65+
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(cwtpm), cwtp_cmd);
66+
}
67+
68+
static int
69+
mlxsw_sp_tclass_congestion_disable(struct mlxsw_sp_port *mlxsw_sp_port,
70+
int tclass_num)
71+
{
72+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
73+
char cwtpm_cmd[MLXSW_REG_CWTPM_LEN];
74+
75+
mlxsw_reg_cwtpm_pack(cwtpm_cmd, mlxsw_sp_port->local_port, tclass_num,
76+
MLXSW_REG_CWTPM_RESET_PROFILE, false, false);
77+
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(cwtpm), cwtpm_cmd);
78+
}
79+
80+
static int
81+
mlxsw_sp_qdisc_red_destroy(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle,
82+
struct mlxsw_sp_qdisc *mlxsw_sp_qdisc,
83+
int tclass_num)
84+
{
85+
int err;
86+
87+
if (mlxsw_sp_qdisc->handle != handle)
88+
return 0;
89+
90+
err = mlxsw_sp_tclass_congestion_disable(mlxsw_sp_port, tclass_num);
91+
mlxsw_sp_qdisc->handle = TC_H_UNSPEC;
92+
mlxsw_sp_qdisc->type = MLXSW_SP_QDISC_NO_QDISC;
93+
94+
return err;
95+
}
96+
97+
static int
98+
mlxsw_sp_qdisc_red_replace(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle,
99+
struct mlxsw_sp_qdisc *mlxsw_sp_qdisc,
100+
int tclass_num,
101+
struct tc_red_qopt_offload_params *p)
102+
{
103+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
104+
u32 min, max;
105+
u64 prob;
106+
int err = 0;
107+
108+
if (p->min > p->max) {
109+
dev_err(mlxsw_sp->bus_info->dev,
110+
"spectrum: RED: min %u is bigger then max %u\n", p->min,
111+
p->max);
112+
goto err_bad_param;
113+
}
114+
if (p->max > MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_BUFFER_SIZE)) {
115+
dev_err(mlxsw_sp->bus_info->dev,
116+
"spectrum: RED: max value %u is too big\n", p->max);
117+
goto err_bad_param;
118+
}
119+
if (p->min == 0 || p->max == 0) {
120+
dev_err(mlxsw_sp->bus_info->dev,
121+
"spectrum: RED: 0 value is illegal for min and max\n");
122+
goto err_bad_param;
123+
}
124+
125+
/* calculate probability in percentage */
126+
prob = p->probability;
127+
prob *= 100;
128+
prob = DIV_ROUND_UP(prob, 1 << 16);
129+
prob = DIV_ROUND_UP(prob, 1 << 16);
130+
min = mlxsw_sp_bytes_cells(mlxsw_sp, p->min);
131+
max = mlxsw_sp_bytes_cells(mlxsw_sp, p->max);
132+
err = mlxsw_sp_tclass_congestion_enable(mlxsw_sp_port, tclass_num, min,
133+
max, prob, p->is_ecn);
134+
if (err)
135+
goto err_config;
136+
137+
mlxsw_sp_qdisc->type = MLXSW_SP_QDISC_RED;
138+
mlxsw_sp_qdisc->handle = handle;
139+
return 0;
140+
141+
err_bad_param:
142+
err = -EINVAL;
143+
err_config:
144+
mlxsw_sp_qdisc_red_destroy(mlxsw_sp_port, mlxsw_sp_qdisc->handle,
145+
mlxsw_sp_qdisc, tclass_num);
146+
return err;
147+
}
148+
149+
#define MLXSW_SP_PORT_DEFAULT_TCLASS 0
150+
151+
int mlxsw_sp_setup_tc_red(struct mlxsw_sp_port *mlxsw_sp_port,
152+
struct tc_red_qopt_offload *p)
153+
{
154+
struct mlxsw_sp_qdisc *mlxsw_sp_qdisc;
155+
int tclass_num;
156+
157+
if (p->parent != TC_H_ROOT)
158+
return -EOPNOTSUPP;
159+
160+
mlxsw_sp_qdisc = &mlxsw_sp_port->root_qdisc;
161+
tclass_num = MLXSW_SP_PORT_DEFAULT_TCLASS;
162+
163+
switch (p->command) {
164+
case TC_RED_REPLACE:
165+
return mlxsw_sp_qdisc_red_replace(mlxsw_sp_port, p->handle,
166+
mlxsw_sp_qdisc, tclass_num,
167+
&p->set);
168+
case TC_RED_DESTROY:
169+
return mlxsw_sp_qdisc_red_destroy(mlxsw_sp_port, p->handle,
170+
mlxsw_sp_qdisc, tclass_num);
171+
default:
172+
return -EOPNOTSUPP;
173+
}
174+
}

0 commit comments

Comments
 (0)