1/*
2 *   BSD LICENSE
3 *
4 *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
5 *   All rights reserved.
6 *
7 *   Redistribution and use in source and binary forms, with or without
8 *   modification, are permitted provided that the following conditions
9 *   are met:
10 *
11 *     * Redistributions of source code must retain the above copyright
12 *       notice, this list of conditions and the following disclaimer.
13 *     * Redistributions in binary form must reproduce the above copyright
14 *       notice, this list of conditions and the following disclaimer in
15 *       the documentation and/or other materials provided with the
16 *       distribution.
17 *     * Neither the name of Cavium, Inc. nor the names of its
18 *       contributors may be used to endorse or promote products derived
19 *       from this software without specific prior written permission.
20 *
21 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33/*$FreeBSD: stable/11/sys/dev/liquidio/lio_rss.c 325618 2017-11-09 19:52:56Z sbruno $*/
34
35#ifdef RSS
36
37#include "lio_bsd.h"
38#include "lio_common.h"
39#include "lio_droq.h"
40#include "lio_iq.h"
41#include "lio_response_manager.h"
42#include "lio_device.h"
43#include "lio_ctrl.h"
44#include "lio_main.h"
45#include "lio_network.h"
46#include "lio_rss.h"
47
48int	lio_send_rss_param(struct lio *lio);
49
50static void
51lio_set_rss_callback(struct octeon_device *oct, uint32_t status, void *arg)
52{
53	struct lio_soft_command	*sc = (struct lio_soft_command *)arg;
54
55	if (status)
56		lio_dev_err(oct, "Failed to SET RSS params\n");
57	else
58		lio_dev_info(oct, "SET RSS params\n");
59
60	lio_free_soft_command(oct, sc);
61}
62
63static void
64lio_set_rss_info(struct lio *lio)
65{
66	struct octeon_device		*oct = lio->oct_dev;
67	struct lio_rss_params_set	*rss_set = &lio->rss_set;
68	uint32_t	rss_hash_config;
69	int		i;
70	uint8_t		queue_id;
71
72	for (i = 0; i < LIO_RSS_TABLE_SZ; i++) {
73		queue_id = rss_get_indirection_to_bucket(i);
74		queue_id = queue_id % oct->num_oqs;
75		rss_set->fw_itable[i] = queue_id;
76	}
77
78	rss_hash_config = rss_gethashconfig();
79	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
80		rss_set->hashinfo |= LIO_RSS_HASH_IPV4;
81
82	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
83		rss_set->hashinfo |= LIO_RSS_HASH_TCP_IPV4;
84
85	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
86		rss_set->hashinfo |= LIO_RSS_HASH_IPV6;
87
88	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
89		rss_set->hashinfo |= LIO_RSS_HASH_TCP_IPV6;
90
91	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
92		rss_set->hashinfo |= LIO_RSS_HASH_IPV6_EX;
93
94	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
95		rss_set->hashinfo |= LIO_RSS_HASH_TCP_IPV6_EX;
96}
97
98int
99lio_send_rss_param(struct lio *lio)
100{
101	struct octeon_device	*oct = lio->oct_dev;
102	struct lio_soft_command	*sc = NULL;
103	union	octeon_cmd *cmd = NULL;
104	struct lio_rss_params	*rss_param;
105	int	i, retval;
106
107	sc = lio_alloc_soft_command(oct,
108			OCTEON_CMD_SIZE + sizeof(struct lio_rss_params), 0, 0);
109
110	if (sc == NULL) {
111		lio_dev_err(oct, "%s: Soft command allocation failed\n",
112			    __func__);
113		return (ENOMEM);
114	}
115
116	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
117
118	lio_prepare_soft_command(oct, sc, LIO_OPCODE_NIC, LIO_OPCODE_NIC_CMD, 0,
119				 0, 0);
120
121	sc->callback = lio_set_rss_callback;
122	sc->callback_arg = sc;
123	sc->wait_time = 1000;
124
125	cmd = (union octeon_cmd *)sc->virtdptr;
126	cmd->cmd64 = 0;
127	cmd->s.cmd = LIO_CMD_SET_RSS;
128
129	rss_param = (struct lio_rss_params *)(cmd + 1);
130	rss_param->param.flags = 0;
131	rss_param->param.itablesize = LIO_RSS_TABLE_SZ;
132	rss_param->param.hashkeysize = LIO_RSS_KEY_SZ;
133
134	lio_set_rss_info(lio);
135	rss_param->param.hashinfo = lio->rss_set.hashinfo;
136	memcpy(rss_param->itable, (void *)lio->rss_set.fw_itable,
137	       (size_t)rss_param->param.itablesize);
138
139	lio_dev_info(oct, "RSS itable: Size %u\n", rss_param->param.itablesize);
140	for (i = 0; i < rss_param->param.itablesize; i += 8) {
141		lio_dev_dbg(oct, "   %03u:%2u, %03u:%2u, %03u:%2u, %03u:%2u, %03u:%2u, %03u:%2u, %03u:%2u, %03u:%2u\n",
142			    i + 0, rss_param->itable[i + 0],
143			    i + 1, rss_param->itable[i + 1],
144			    i + 2, rss_param->itable[i + 2],
145			    i + 3, rss_param->itable[i + 3],
146			    i + 4, rss_param->itable[i + 4],
147			    i + 5, rss_param->itable[i + 5],
148			    i + 6, rss_param->itable[i + 6],
149			    i + 7, rss_param->itable[i + 7]);
150	}
151
152	rss_getkey(lio->rss_set.key);
153
154	memcpy(rss_param->key, (void *)lio->rss_set.key,
155	       (size_t)rss_param->param.hashkeysize);
156
157	/* swap cmd and rss params */
158	lio_swap_8B_data((uint64_t *)cmd,
159			 ((OCTEON_CMD_SIZE + LIO_RSS_PARAM_SIZE) >> 3));
160
161	retval = lio_send_soft_command(oct, sc);
162	if (retval == LIO_IQ_SEND_FAILED) {
163		lio_dev_err(oct,
164			    "%s: Sending soft command failed, status: %x\n",
165			    __func__, retval);
166		lio_free_soft_command(oct, sc);
167		return (-1);
168	}
169
170	return (0);
171}
172
173#endif	/* RSS */
174