1329159Shselasky/*
2329159Shselasky * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
3329159Shselasky * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies.
4329159Shselasky * All rights reserved.
5329159Shselasky *
6329159Shselasky * This software is available to you under a choice of one of two
7329159Shselasky * licenses.  You may choose to be licensed under the terms of the GNU
8329159Shselasky * General Public License (GPL) Version 2, available from the file
9329159Shselasky * COPYING in the main directory of this source tree, or the
10329159Shselasky * OpenIB.org BSD license below:
11329159Shselasky *
12329159Shselasky *     Redistribution and use in source and binary forms, with or
13329159Shselasky *     without modification, are permitted provided that the following
14329159Shselasky *     conditions are met:
15329159Shselasky *
16329159Shselasky *      - Redistributions of source code must retain the above
17329159Shselasky *        copyright notice, this list of conditions and the following
18329159Shselasky *        disclaimer.
19329159Shselasky *
20329159Shselasky *      - Redistributions in binary form must reproduce the above
21329159Shselasky *        copyright notice, this list of conditions and the following
22329159Shselasky *        disclaimer in the documentation and/or other materials
23329159Shselasky *        provided with the distribution.
24329159Shselasky *
25329159Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26329159Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27329159Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28329159Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29329159Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30329159Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31329159Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32329159Shselasky * SOFTWARE.
33329159Shselasky */
34329159Shselasky
35329159Shselasky#include <linux/kernel.h>
36329159Shselasky#include "fw_qos.h"
37329159Shselasky#include "fw.h"
38329159Shselasky
39329159Shselaskyenum {
40329159Shselasky	/* allocate vpp opcode modifiers */
41329159Shselasky	MLX4_ALLOCATE_VPP_ALLOCATE	= 0x0,
42329159Shselasky	MLX4_ALLOCATE_VPP_QUERY		= 0x1
43329159Shselasky};
44329159Shselasky
45329159Shselaskyenum {
46329159Shselasky	/* set vport qos opcode modifiers */
47329159Shselasky	MLX4_SET_VPORT_QOS_SET		= 0x0,
48329159Shselasky	MLX4_SET_VPORT_QOS_QUERY	= 0x1
49329159Shselasky};
50329159Shselasky
51329159Shselaskystruct mlx4_set_port_prio2tc_context {
52329159Shselasky	u8 prio2tc[4];
53329159Shselasky};
54329159Shselasky
55329159Shselaskystruct mlx4_port_scheduler_tc_cfg_be {
56329159Shselasky	__be16 pg;
57329159Shselasky	__be16 bw_precentage;
58329159Shselasky	__be16 max_bw_units; /* 3-100Mbps, 4-1Gbps, other values - reserved */
59329159Shselasky	__be16 max_bw_value;
60329159Shselasky};
61329159Shselasky
62329159Shselaskystruct mlx4_set_port_scheduler_context {
63329159Shselasky	struct mlx4_port_scheduler_tc_cfg_be tc[MLX4_NUM_TC];
64329159Shselasky};
65329159Shselasky
66329159Shselasky/* Granular Qos (per VF) section */
67329159Shselaskystruct mlx4_alloc_vpp_param {
68329159Shselasky	__be32 availible_vpp;
69329159Shselasky	__be32 vpp_p_up[MLX4_NUM_UP];
70329159Shselasky};
71329159Shselasky
72329159Shselaskystruct mlx4_prio_qos_param {
73329159Shselasky	__be32 bw_share;
74329159Shselasky	__be32 max_avg_bw;
75329159Shselasky	__be32 reserved;
76329159Shselasky	__be32 enable;
77329159Shselasky	__be32 reserved1[4];
78329159Shselasky};
79329159Shselasky
80329159Shselaskystruct mlx4_set_vport_context {
81329159Shselasky	__be32 reserved[8];
82329159Shselasky	struct mlx4_prio_qos_param qos_p_up[MLX4_NUM_UP];
83329159Shselasky};
84329159Shselasky
85329159Shselaskyint mlx4_SET_PORT_PRIO2TC(struct mlx4_dev *dev, u8 port, u8 *prio2tc)
86329159Shselasky{
87329159Shselasky	struct mlx4_cmd_mailbox *mailbox;
88329159Shselasky	struct mlx4_set_port_prio2tc_context *context;
89329159Shselasky	int err;
90329159Shselasky	u32 in_mod;
91329159Shselasky	int i;
92329159Shselasky
93329159Shselasky	mailbox = mlx4_alloc_cmd_mailbox(dev);
94329159Shselasky	if (IS_ERR(mailbox))
95329159Shselasky		return PTR_ERR(mailbox);
96329159Shselasky
97329159Shselasky	context = mailbox->buf;
98329159Shselasky
99329159Shselasky	for (i = 0; i < MLX4_NUM_UP; i += 2)
100329159Shselasky		context->prio2tc[i >> 1] = prio2tc[i] << 4 | prio2tc[i + 1];
101329159Shselasky
102329159Shselasky	in_mod = MLX4_SET_PORT_PRIO2TC << 8 | port;
103329159Shselasky	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
104329159Shselasky		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
105329159Shselasky
106329159Shselasky	mlx4_free_cmd_mailbox(dev, mailbox);
107329159Shselasky	return err;
108329159Shselasky}
109329159ShselaskyEXPORT_SYMBOL(mlx4_SET_PORT_PRIO2TC);
110329159Shselasky
111329159Shselaskyint mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw,
112329159Shselasky			    u8 *pg, u16 *ratelimit)
113329159Shselasky{
114329159Shselasky	struct mlx4_cmd_mailbox *mailbox;
115329159Shselasky	struct mlx4_set_port_scheduler_context *context;
116329159Shselasky	int err;
117329159Shselasky	u32 in_mod;
118329159Shselasky	int i;
119329159Shselasky
120329159Shselasky	mailbox = mlx4_alloc_cmd_mailbox(dev);
121329159Shselasky	if (IS_ERR(mailbox))
122329159Shselasky		return PTR_ERR(mailbox);
123329159Shselasky
124329159Shselasky	context = mailbox->buf;
125329159Shselasky
126329159Shselasky	for (i = 0; i < MLX4_NUM_TC; i++) {
127329159Shselasky		struct mlx4_port_scheduler_tc_cfg_be *tc = &context->tc[i];
128329159Shselasky		u16 r;
129329159Shselasky
130329159Shselasky		if (ratelimit && ratelimit[i]) {
131329159Shselasky			if (ratelimit[i] <= MLX4_MAX_100M_UNITS_VAL) {
132329159Shselasky				r = ratelimit[i];
133329159Shselasky				tc->max_bw_units =
134329159Shselasky					htons(MLX4_RATELIMIT_100M_UNITS);
135329159Shselasky			} else {
136329159Shselasky				r = ratelimit[i] / 10;
137329159Shselasky				tc->max_bw_units =
138329159Shselasky					htons(MLX4_RATELIMIT_1G_UNITS);
139329159Shselasky			}
140329159Shselasky			tc->max_bw_value = htons(r);
141329159Shselasky		} else {
142329159Shselasky			tc->max_bw_value = htons(MLX4_RATELIMIT_DEFAULT);
143329159Shselasky			tc->max_bw_units = htons(MLX4_RATELIMIT_1G_UNITS);
144329159Shselasky		}
145329159Shselasky
146329159Shselasky		tc->pg = htons(pg[i]);
147329159Shselasky		tc->bw_precentage = htons(tc_tx_bw[i]);
148329159Shselasky	}
149329159Shselasky
150329159Shselasky	in_mod = MLX4_SET_PORT_SCHEDULER << 8 | port;
151329159Shselasky	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
152329159Shselasky		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
153329159Shselasky
154329159Shselasky	mlx4_free_cmd_mailbox(dev, mailbox);
155329159Shselasky	return err;
156329159Shselasky}
157329159ShselaskyEXPORT_SYMBOL(mlx4_SET_PORT_SCHEDULER);
158329159Shselasky
159329159Shselaskyint mlx4_ALLOCATE_VPP_get(struct mlx4_dev *dev, u8 port,
160329159Shselasky			  u16 *availible_vpp, u8 *vpp_p_up)
161329159Shselasky{
162329159Shselasky	int i;
163329159Shselasky	int err;
164329159Shselasky	struct mlx4_cmd_mailbox *mailbox;
165329159Shselasky	struct mlx4_alloc_vpp_param *out_param;
166329159Shselasky
167329159Shselasky	mailbox = mlx4_alloc_cmd_mailbox(dev);
168329159Shselasky	if (IS_ERR(mailbox))
169329159Shselasky		return PTR_ERR(mailbox);
170329159Shselasky
171329159Shselasky	out_param = mailbox->buf;
172329159Shselasky
173329159Shselasky	err = mlx4_cmd_box(dev, 0, mailbox->dma, port,
174329159Shselasky			   MLX4_ALLOCATE_VPP_QUERY,
175329159Shselasky			   MLX4_CMD_ALLOCATE_VPP,
176329159Shselasky			   MLX4_CMD_TIME_CLASS_A,
177329159Shselasky			   MLX4_CMD_NATIVE);
178329159Shselasky	if (err)
179329159Shselasky		goto out;
180329159Shselasky
181329159Shselasky	/* Total number of supported VPPs */
182329159Shselasky	*availible_vpp = (u16)be32_to_cpu(out_param->availible_vpp);
183329159Shselasky
184329159Shselasky	for (i = 0; i < MLX4_NUM_UP; i++)
185329159Shselasky		vpp_p_up[i] = (u8)be32_to_cpu(out_param->vpp_p_up[i]);
186329159Shselasky
187329159Shselaskyout:
188329159Shselasky	mlx4_free_cmd_mailbox(dev, mailbox);
189329159Shselasky
190329159Shselasky	return err;
191329159Shselasky}
192329159ShselaskyEXPORT_SYMBOL(mlx4_ALLOCATE_VPP_get);
193329159Shselasky
194329159Shselaskyint mlx4_ALLOCATE_VPP_set(struct mlx4_dev *dev, u8 port, u8 *vpp_p_up)
195329159Shselasky{
196329159Shselasky	int i;
197329159Shselasky	int err;
198329159Shselasky	struct mlx4_cmd_mailbox *mailbox;
199329159Shselasky	struct mlx4_alloc_vpp_param *in_param;
200329159Shselasky
201329159Shselasky	mailbox = mlx4_alloc_cmd_mailbox(dev);
202329159Shselasky	if (IS_ERR(mailbox))
203329159Shselasky		return PTR_ERR(mailbox);
204329159Shselasky
205329159Shselasky	in_param = mailbox->buf;
206329159Shselasky
207329159Shselasky	for (i = 0; i < MLX4_NUM_UP; i++)
208329159Shselasky		in_param->vpp_p_up[i] = cpu_to_be32(vpp_p_up[i]);
209329159Shselasky
210329159Shselasky	err = mlx4_cmd(dev, mailbox->dma, port,
211329159Shselasky		       MLX4_ALLOCATE_VPP_ALLOCATE,
212329159Shselasky		       MLX4_CMD_ALLOCATE_VPP,
213329159Shselasky		       MLX4_CMD_TIME_CLASS_A,
214329159Shselasky		       MLX4_CMD_NATIVE);
215329159Shselasky
216329159Shselasky	mlx4_free_cmd_mailbox(dev, mailbox);
217329159Shselasky	return err;
218329159Shselasky}
219329159ShselaskyEXPORT_SYMBOL(mlx4_ALLOCATE_VPP_set);
220329159Shselasky
221329159Shselaskyint mlx4_SET_VPORT_QOS_get(struct mlx4_dev *dev, u8 port, u8 vport,
222329159Shselasky			   struct mlx4_vport_qos_param *out_param)
223329159Shselasky{
224329159Shselasky	int i;
225329159Shselasky	int err;
226329159Shselasky	struct mlx4_cmd_mailbox *mailbox;
227329159Shselasky	struct mlx4_set_vport_context *ctx;
228329159Shselasky
229329159Shselasky	mailbox = mlx4_alloc_cmd_mailbox(dev);
230329159Shselasky	if (IS_ERR(mailbox))
231329159Shselasky		return PTR_ERR(mailbox);
232329159Shselasky
233329159Shselasky	ctx = mailbox->buf;
234329159Shselasky
235329159Shselasky	err = mlx4_cmd_box(dev, 0, mailbox->dma, (vport << 8) | port,
236329159Shselasky			   MLX4_SET_VPORT_QOS_QUERY,
237329159Shselasky			   MLX4_CMD_SET_VPORT_QOS,
238329159Shselasky			   MLX4_CMD_TIME_CLASS_A,
239329159Shselasky			   MLX4_CMD_NATIVE);
240329159Shselasky	if (err)
241329159Shselasky		goto out;
242329159Shselasky
243329159Shselasky	for (i = 0; i < MLX4_NUM_UP; i++) {
244329159Shselasky		out_param[i].bw_share = be32_to_cpu(ctx->qos_p_up[i].bw_share);
245329159Shselasky		out_param[i].max_avg_bw =
246329159Shselasky			be32_to_cpu(ctx->qos_p_up[i].max_avg_bw);
247329159Shselasky		out_param[i].enable =
248329159Shselasky			!!(be32_to_cpu(ctx->qos_p_up[i].enable) & 31);
249329159Shselasky	}
250329159Shselasky
251329159Shselaskyout:
252329159Shselasky	mlx4_free_cmd_mailbox(dev, mailbox);
253329159Shselasky
254329159Shselasky	return err;
255329159Shselasky}
256329159ShselaskyEXPORT_SYMBOL(mlx4_SET_VPORT_QOS_get);
257329159Shselasky
258329159Shselaskyint mlx4_SET_VPORT_QOS_set(struct mlx4_dev *dev, u8 port, u8 vport,
259329159Shselasky			   struct mlx4_vport_qos_param *in_param)
260329159Shselasky{
261329159Shselasky	int i;
262329159Shselasky	int err;
263329159Shselasky	struct mlx4_cmd_mailbox *mailbox;
264329159Shselasky	struct mlx4_set_vport_context *ctx;
265329159Shselasky
266329159Shselasky	mailbox = mlx4_alloc_cmd_mailbox(dev);
267329159Shselasky	if (IS_ERR(mailbox))
268329159Shselasky		return PTR_ERR(mailbox);
269329159Shselasky
270329159Shselasky	ctx = mailbox->buf;
271329159Shselasky
272329159Shselasky	for (i = 0; i < MLX4_NUM_UP; i++) {
273329159Shselasky		ctx->qos_p_up[i].bw_share = cpu_to_be32(in_param[i].bw_share);
274329159Shselasky		ctx->qos_p_up[i].max_avg_bw =
275329159Shselasky				cpu_to_be32(in_param[i].max_avg_bw);
276329159Shselasky		ctx->qos_p_up[i].enable =
277329159Shselasky				cpu_to_be32(in_param[i].enable << 31);
278329159Shselasky	}
279329159Shselasky
280329159Shselasky	err = mlx4_cmd(dev, mailbox->dma, (vport << 8) | port,
281329159Shselasky		       MLX4_SET_VPORT_QOS_SET,
282329159Shselasky		       MLX4_CMD_SET_VPORT_QOS,
283329159Shselasky		       MLX4_CMD_TIME_CLASS_A,
284329159Shselasky		       MLX4_CMD_NATIVE);
285329159Shselasky
286329159Shselasky	mlx4_free_cmd_mailbox(dev, mailbox);
287329159Shselasky	return err;
288329159Shselasky}
289329159ShselaskyEXPORT_SYMBOL(mlx4_SET_VPORT_QOS_set);
290