1325618Ssbruno/*
2325618Ssbruno *   BSD LICENSE
3325618Ssbruno *
4325618Ssbruno *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
5325618Ssbruno *   All rights reserved.
6325618Ssbruno *
7325618Ssbruno *   Redistribution and use in source and binary forms, with or without
8325618Ssbruno *   modification, are permitted provided that the following conditions
9325618Ssbruno *   are met:
10325618Ssbruno *
11325618Ssbruno *     * Redistributions of source code must retain the above copyright
12325618Ssbruno *       notice, this list of conditions and the following disclaimer.
13325618Ssbruno *     * Redistributions in binary form must reproduce the above copyright
14325618Ssbruno *       notice, this list of conditions and the following disclaimer in
15325618Ssbruno *       the documentation and/or other materials provided with the
16325618Ssbruno *       distribution.
17325618Ssbruno *     * Neither the name of Cavium, Inc. nor the names of its
18325618Ssbruno *       contributors may be used to endorse or promote products derived
19325618Ssbruno *       from this software without specific prior written permission.
20325618Ssbruno *
21325618Ssbruno *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22325618Ssbruno *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23325618Ssbruno *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24325618Ssbruno *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25325618Ssbruno *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26325618Ssbruno *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27325618Ssbruno *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28325618Ssbruno *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29325618Ssbruno *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30325618Ssbruno *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31325618Ssbruno *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32325618Ssbruno */
33325618Ssbruno/*$FreeBSD: stable/11/sys/dev/liquidio/lio_rss.c 325618 2017-11-09 19:52:56Z sbruno $*/
34325618Ssbruno
35325618Ssbruno#ifdef RSS
36325618Ssbruno
37325618Ssbruno#include "lio_bsd.h"
38325618Ssbruno#include "lio_common.h"
39325618Ssbruno#include "lio_droq.h"
40325618Ssbruno#include "lio_iq.h"
41325618Ssbruno#include "lio_response_manager.h"
42325618Ssbruno#include "lio_device.h"
43325618Ssbruno#include "lio_ctrl.h"
44325618Ssbruno#include "lio_main.h"
45325618Ssbruno#include "lio_network.h"
46325618Ssbruno#include "lio_rss.h"
47325618Ssbruno
48325618Ssbrunoint	lio_send_rss_param(struct lio *lio);
49325618Ssbruno
50325618Ssbrunostatic void
51325618Ssbrunolio_set_rss_callback(struct octeon_device *oct, uint32_t status, void *arg)
52325618Ssbruno{
53325618Ssbruno	struct lio_soft_command	*sc = (struct lio_soft_command *)arg;
54325618Ssbruno
55325618Ssbruno	if (status)
56325618Ssbruno		lio_dev_err(oct, "Failed to SET RSS params\n");
57325618Ssbruno	else
58325618Ssbruno		lio_dev_info(oct, "SET RSS params\n");
59325618Ssbruno
60325618Ssbruno	lio_free_soft_command(oct, sc);
61325618Ssbruno}
62325618Ssbruno
63325618Ssbrunostatic void
64325618Ssbrunolio_set_rss_info(struct lio *lio)
65325618Ssbruno{
66325618Ssbruno	struct octeon_device		*oct = lio->oct_dev;
67325618Ssbruno	struct lio_rss_params_set	*rss_set = &lio->rss_set;
68325618Ssbruno	uint32_t	rss_hash_config;
69325618Ssbruno	int		i;
70325618Ssbruno	uint8_t		queue_id;
71325618Ssbruno
72325618Ssbruno	for (i = 0; i < LIO_RSS_TABLE_SZ; i++) {
73325618Ssbruno		queue_id = rss_get_indirection_to_bucket(i);
74325618Ssbruno		queue_id = queue_id % oct->num_oqs;
75325618Ssbruno		rss_set->fw_itable[i] = queue_id;
76325618Ssbruno	}
77325618Ssbruno
78325618Ssbruno	rss_hash_config = rss_gethashconfig();
79325618Ssbruno	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
80325618Ssbruno		rss_set->hashinfo |= LIO_RSS_HASH_IPV4;
81325618Ssbruno
82325618Ssbruno	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
83325618Ssbruno		rss_set->hashinfo |= LIO_RSS_HASH_TCP_IPV4;
84325618Ssbruno
85325618Ssbruno	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
86325618Ssbruno		rss_set->hashinfo |= LIO_RSS_HASH_IPV6;
87325618Ssbruno
88325618Ssbruno	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
89325618Ssbruno		rss_set->hashinfo |= LIO_RSS_HASH_TCP_IPV6;
90325618Ssbruno
91325618Ssbruno	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
92325618Ssbruno		rss_set->hashinfo |= LIO_RSS_HASH_IPV6_EX;
93325618Ssbruno
94325618Ssbruno	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
95325618Ssbruno		rss_set->hashinfo |= LIO_RSS_HASH_TCP_IPV6_EX;
96325618Ssbruno}
97325618Ssbruno
98325618Ssbrunoint
99325618Ssbrunolio_send_rss_param(struct lio *lio)
100325618Ssbruno{
101325618Ssbruno	struct octeon_device	*oct = lio->oct_dev;
102325618Ssbruno	struct lio_soft_command	*sc = NULL;
103325618Ssbruno	union	octeon_cmd *cmd = NULL;
104325618Ssbruno	struct lio_rss_params	*rss_param;
105325618Ssbruno	int	i, retval;
106325618Ssbruno
107325618Ssbruno	sc = lio_alloc_soft_command(oct,
108325618Ssbruno			OCTEON_CMD_SIZE + sizeof(struct lio_rss_params), 0, 0);
109325618Ssbruno
110325618Ssbruno	if (sc == NULL) {
111325618Ssbruno		lio_dev_err(oct, "%s: Soft command allocation failed\n",
112325618Ssbruno			    __func__);
113325618Ssbruno		return (ENOMEM);
114325618Ssbruno	}
115325618Ssbruno
116325618Ssbruno	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
117325618Ssbruno
118325618Ssbruno	lio_prepare_soft_command(oct, sc, LIO_OPCODE_NIC, LIO_OPCODE_NIC_CMD, 0,
119325618Ssbruno				 0, 0);
120325618Ssbruno
121325618Ssbruno	sc->callback = lio_set_rss_callback;
122325618Ssbruno	sc->callback_arg = sc;
123325618Ssbruno	sc->wait_time = 1000;
124325618Ssbruno
125325618Ssbruno	cmd = (union octeon_cmd *)sc->virtdptr;
126325618Ssbruno	cmd->cmd64 = 0;
127325618Ssbruno	cmd->s.cmd = LIO_CMD_SET_RSS;
128325618Ssbruno
129325618Ssbruno	rss_param = (struct lio_rss_params *)(cmd + 1);
130325618Ssbruno	rss_param->param.flags = 0;
131325618Ssbruno	rss_param->param.itablesize = LIO_RSS_TABLE_SZ;
132325618Ssbruno	rss_param->param.hashkeysize = LIO_RSS_KEY_SZ;
133325618Ssbruno
134325618Ssbruno	lio_set_rss_info(lio);
135325618Ssbruno	rss_param->param.hashinfo = lio->rss_set.hashinfo;
136325618Ssbruno	memcpy(rss_param->itable, (void *)lio->rss_set.fw_itable,
137325618Ssbruno	       (size_t)rss_param->param.itablesize);
138325618Ssbruno
139325618Ssbruno	lio_dev_info(oct, "RSS itable: Size %u\n", rss_param->param.itablesize);
140325618Ssbruno	for (i = 0; i < rss_param->param.itablesize; i += 8) {
141325618Ssbruno		lio_dev_dbg(oct, "   %03u:%2u, %03u:%2u, %03u:%2u, %03u:%2u, %03u:%2u, %03u:%2u, %03u:%2u, %03u:%2u\n",
142325618Ssbruno			    i + 0, rss_param->itable[i + 0],
143325618Ssbruno			    i + 1, rss_param->itable[i + 1],
144325618Ssbruno			    i + 2, rss_param->itable[i + 2],
145325618Ssbruno			    i + 3, rss_param->itable[i + 3],
146325618Ssbruno			    i + 4, rss_param->itable[i + 4],
147325618Ssbruno			    i + 5, rss_param->itable[i + 5],
148325618Ssbruno			    i + 6, rss_param->itable[i + 6],
149325618Ssbruno			    i + 7, rss_param->itable[i + 7]);
150325618Ssbruno	}
151325618Ssbruno
152325618Ssbruno	rss_getkey(lio->rss_set.key);
153325618Ssbruno
154325618Ssbruno	memcpy(rss_param->key, (void *)lio->rss_set.key,
155325618Ssbruno	       (size_t)rss_param->param.hashkeysize);
156325618Ssbruno
157325618Ssbruno	/* swap cmd and rss params */
158325618Ssbruno	lio_swap_8B_data((uint64_t *)cmd,
159325618Ssbruno			 ((OCTEON_CMD_SIZE + LIO_RSS_PARAM_SIZE) >> 3));
160325618Ssbruno
161325618Ssbruno	retval = lio_send_soft_command(oct, sc);
162325618Ssbruno	if (retval == LIO_IQ_SEND_FAILED) {
163325618Ssbruno		lio_dev_err(oct,
164325618Ssbruno			    "%s: Sending soft command failed, status: %x\n",
165325618Ssbruno			    __func__, retval);
166325618Ssbruno		lio_free_soft_command(oct, sc);
167325618Ssbruno		return (-1);
168325618Ssbruno	}
169325618Ssbruno
170325618Ssbruno	return (0);
171325618Ssbruno}
172325618Ssbruno
173325618Ssbruno#endif	/* RSS */
174