blob: 9f7657c68688ac4eac86a4444d1b5dfc8b5a4444 [file] [log] [blame]
Greg Rosefbb7ddf2013-12-21 06:12:56 +00001/*******************************************************************************
2 *
3 * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
Mitch Williams00e5ec42016-01-15 14:33:10 -08004 * Copyright(c) 2013 - 2016 Intel Corporation.
Greg Rosefbb7ddf2013-12-21 06:12:56 +00005 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
Jesse Brandeburgb8316072014-04-05 07:46:11 +000015 * You should have received a copy of the GNU General Public License along
16 * with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
Greg Rosefbb7ddf2013-12-21 06:12:56 +000018 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
20 *
21 * Contact Information:
22 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
23 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24 *
25 ******************************************************************************/
26
27/* ethtool support for i40evf */
28#include "i40evf.h"
29
30#include <linux/uaccess.h>
31
Greg Rosefbb7ddf2013-12-21 06:12:56 +000032struct i40evf_stats {
33 char stat_string[ETH_GSTRING_LEN];
34 int stat_offset;
35};
36
37#define I40EVF_STAT(_name, _stat) { \
38 .stat_string = _name, \
39 .stat_offset = offsetof(struct i40evf_adapter, _stat) \
40}
41
42/* All stats are u64, so we don't need to track the size of the field. */
43static const struct i40evf_stats i40evf_gstrings_stats[] = {
44 I40EVF_STAT("rx_bytes", current_stats.rx_bytes),
45 I40EVF_STAT("rx_unicast", current_stats.rx_unicast),
46 I40EVF_STAT("rx_multicast", current_stats.rx_multicast),
47 I40EVF_STAT("rx_broadcast", current_stats.rx_broadcast),
48 I40EVF_STAT("rx_discards", current_stats.rx_discards),
Greg Rosefbb7ddf2013-12-21 06:12:56 +000049 I40EVF_STAT("rx_unknown_protocol", current_stats.rx_unknown_protocol),
50 I40EVF_STAT("tx_bytes", current_stats.tx_bytes),
51 I40EVF_STAT("tx_unicast", current_stats.tx_unicast),
52 I40EVF_STAT("tx_multicast", current_stats.tx_multicast),
53 I40EVF_STAT("tx_broadcast", current_stats.tx_broadcast),
54 I40EVF_STAT("tx_discards", current_stats.tx_discards),
55 I40EVF_STAT("tx_errors", current_stats.tx_errors),
56};
57
58#define I40EVF_GLOBAL_STATS_LEN ARRAY_SIZE(i40evf_gstrings_stats)
Mitch Williamsc7b8d972014-04-04 04:43:08 +000059#define I40EVF_QUEUE_STATS_LEN(_dev) \
Mitch Williams75a64432014-11-11 20:02:42 +000060 (((struct i40evf_adapter *)\
Mitch Williamscc052922014-10-25 03:24:34 +000061 netdev_priv(_dev))->num_active_queues \
Mitch Williamsc7b8d972014-04-04 04:43:08 +000062 * 2 * (sizeof(struct i40e_queue_stats) / sizeof(u64)))
63#define I40EVF_STATS_LEN(_dev) \
64 (I40EVF_GLOBAL_STATS_LEN + I40EVF_QUEUE_STATS_LEN(_dev))
Greg Rosefbb7ddf2013-12-21 06:12:56 +000065
Mitch Williams00e5ec42016-01-15 14:33:10 -080066static const char i40evf_priv_flags_strings[][ETH_GSTRING_LEN] = {
67 "packet-split",
68};
69
70#define I40EVF_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40evf_priv_flags_strings)
71
Greg Rosefbb7ddf2013-12-21 06:12:56 +000072/**
73 * i40evf_get_settings - Get Link Speed and Duplex settings
74 * @netdev: network interface device structure
75 * @ecmd: ethtool command
76 *
77 * Reports speed/duplex settings. Because this is a VF, we don't know what
78 * kind of link we really have, so we fake it.
79 **/
80static int i40evf_get_settings(struct net_device *netdev,
81 struct ethtool_cmd *ecmd)
82{
83 /* In the future the VF will be able to query the PF for
84 * some information - for now use a dummy value
85 */
Mitch Williams107f3012014-04-04 04:43:09 +000086 ecmd->supported = 0;
Greg Rosefbb7ddf2013-12-21 06:12:56 +000087 ecmd->autoneg = AUTONEG_DISABLE;
88 ecmd->transceiver = XCVR_DUMMY1;
89 ecmd->port = PORT_NONE;
90
91 return 0;
92}
93
94/**
95 * i40evf_get_sset_count - Get length of string set
96 * @netdev: network interface device structure
97 * @sset: id of string set
98 *
99 * Reports size of string table. This driver only supports
100 * strings for statistics.
101 **/
102static int i40evf_get_sset_count(struct net_device *netdev, int sset)
103{
104 if (sset == ETH_SS_STATS)
Mitch Williamsc7b8d972014-04-04 04:43:08 +0000105 return I40EVF_STATS_LEN(netdev);
Mitch Williams00e5ec42016-01-15 14:33:10 -0800106 else if (sset == ETH_SS_PRIV_FLAGS)
107 return I40EVF_PRIV_FLAGS_STR_LEN;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000108 else
Mitch Williamsc7b8d972014-04-04 04:43:08 +0000109 return -EINVAL;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000110}
111
112/**
113 * i40evf_get_ethtool_stats - report device statistics
114 * @netdev: network interface device structure
115 * @stats: ethtool statistics structure
116 * @data: pointer to data buffer
117 *
118 * All statistics are added to the data buffer as an array of u64.
119 **/
120static void i40evf_get_ethtool_stats(struct net_device *netdev,
121 struct ethtool_stats *stats, u64 *data)
122{
123 struct i40evf_adapter *adapter = netdev_priv(netdev);
124 int i, j;
125 char *p;
126
127 for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
128 p = (char *)adapter + i40evf_gstrings_stats[i].stat_offset;
129 data[i] = *(u64 *)p;
130 }
Mitch Williamscc052922014-10-25 03:24:34 +0000131 for (j = 0; j < adapter->num_active_queues; j++) {
Mitch Williams0dd438d2015-10-26 19:44:40 -0400132 data[i++] = adapter->tx_rings[j].stats.packets;
133 data[i++] = adapter->tx_rings[j].stats.bytes;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000134 }
Mitch Williamscc052922014-10-25 03:24:34 +0000135 for (j = 0; j < adapter->num_active_queues; j++) {
Mitch Williams0dd438d2015-10-26 19:44:40 -0400136 data[i++] = adapter->rx_rings[j].stats.packets;
137 data[i++] = adapter->rx_rings[j].stats.bytes;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000138 }
139}
140
141/**
142 * i40evf_get_strings - Get string set
143 * @netdev: network interface device structure
144 * @sset: id of string set
145 * @data: buffer for string data
146 *
147 * Builds stats string table.
148 **/
149static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
150{
151 struct i40evf_adapter *adapter = netdev_priv(netdev);
152 u8 *p = data;
153 int i;
154
155 if (sset == ETH_SS_STATS) {
156 for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
157 memcpy(p, i40evf_gstrings_stats[i].stat_string,
158 ETH_GSTRING_LEN);
159 p += ETH_GSTRING_LEN;
160 }
Mitch Williamscc052922014-10-25 03:24:34 +0000161 for (i = 0; i < adapter->num_active_queues; i++) {
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000162 snprintf(p, ETH_GSTRING_LEN, "tx-%u.packets", i);
163 p += ETH_GSTRING_LEN;
164 snprintf(p, ETH_GSTRING_LEN, "tx-%u.bytes", i);
165 p += ETH_GSTRING_LEN;
166 }
Mitch Williamscc052922014-10-25 03:24:34 +0000167 for (i = 0; i < adapter->num_active_queues; i++) {
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000168 snprintf(p, ETH_GSTRING_LEN, "rx-%u.packets", i);
169 p += ETH_GSTRING_LEN;
170 snprintf(p, ETH_GSTRING_LEN, "rx-%u.bytes", i);
171 p += ETH_GSTRING_LEN;
172 }
Mitch Williams00e5ec42016-01-15 14:33:10 -0800173 } else if (sset == ETH_SS_PRIV_FLAGS) {
174 for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
175 memcpy(data, i40evf_priv_flags_strings[i],
176 ETH_GSTRING_LEN);
177 data += ETH_GSTRING_LEN;
178 }
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000179 }
180}
181
182/**
183 * i40evf_get_msglevel - Get debug message level
184 * @netdev: network interface device structure
185 *
186 * Returns current debug message level.
187 **/
188static u32 i40evf_get_msglevel(struct net_device *netdev)
189{
190 struct i40evf_adapter *adapter = netdev_priv(netdev);
Mitch Williams75a64432014-11-11 20:02:42 +0000191
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000192 return adapter->msg_enable;
193}
194
195/**
Ashish Shah0e888982015-02-06 08:52:10 +0000196 * i40evf_set_msglevel - Set debug message level
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000197 * @netdev: network interface device structure
198 * @data: message level
199 *
200 * Set current debug message level. Higher values cause the driver to
201 * be noisier.
202 **/
203static void i40evf_set_msglevel(struct net_device *netdev, u32 data)
204{
205 struct i40evf_adapter *adapter = netdev_priv(netdev);
Mitch Williams75a64432014-11-11 20:02:42 +0000206
Ashish Shah0e888982015-02-06 08:52:10 +0000207 if (I40E_DEBUG_USER & data)
208 adapter->hw.debug_mask = data;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000209 adapter->msg_enable = data;
210}
211
212/**
Jesse Brandeburgb39c1e22014-08-01 13:27:08 -0700213 * i40evf_get_drvinfo - Get driver info
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000214 * @netdev: network interface device structure
215 * @drvinfo: ethool driver info structure
216 *
217 * Returns information about the driver and device for display to the user.
218 **/
219static void i40evf_get_drvinfo(struct net_device *netdev,
220 struct ethtool_drvinfo *drvinfo)
221{
222 struct i40evf_adapter *adapter = netdev_priv(netdev);
223
224 strlcpy(drvinfo->driver, i40evf_driver_name, 32);
225 strlcpy(drvinfo->version, i40evf_driver_version, 32);
Mitch Williamscc470a82015-03-27 00:12:11 -0700226 strlcpy(drvinfo->fw_version, "N/A", 4);
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000227 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
Mitch Williams00e5ec42016-01-15 14:33:10 -0800228 drvinfo->n_priv_flags = I40EVF_PRIV_FLAGS_STR_LEN;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000229}
230
231/**
232 * i40evf_get_ringparam - Get ring parameters
233 * @netdev: network interface device structure
234 * @ring: ethtool ringparam structure
235 *
236 * Returns current ring parameters. TX and RX rings are reported separately,
237 * but the number of rings is not reported.
238 **/
239static void i40evf_get_ringparam(struct net_device *netdev,
Mitch Williams75a64432014-11-11 20:02:42 +0000240 struct ethtool_ringparam *ring)
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000241{
242 struct i40evf_adapter *adapter = netdev_priv(netdev);
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000243
244 ring->rx_max_pending = I40EVF_MAX_RXD;
245 ring->tx_max_pending = I40EVF_MAX_TXD;
Mitch Williamsd732a182014-04-24 06:41:37 +0000246 ring->rx_pending = adapter->rx_desc_count;
247 ring->tx_pending = adapter->tx_desc_count;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000248}
249
250/**
251 * i40evf_set_ringparam - Set ring parameters
252 * @netdev: network interface device structure
253 * @ring: ethtool ringparam structure
254 *
255 * Sets ring parameters. TX and RX rings are controlled separately, but the
256 * number of rings is not specified, so all rings get the same settings.
257 **/
258static int i40evf_set_ringparam(struct net_device *netdev,
259 struct ethtool_ringparam *ring)
260{
261 struct i40evf_adapter *adapter = netdev_priv(netdev);
262 u32 new_rx_count, new_tx_count;
263
264 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
265 return -EINVAL;
266
267 new_tx_count = clamp_t(u32, ring->tx_pending,
268 I40EVF_MIN_TXD,
269 I40EVF_MAX_TXD);
270 new_tx_count = ALIGN(new_tx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
271
272 new_rx_count = clamp_t(u32, ring->rx_pending,
273 I40EVF_MIN_RXD,
274 I40EVF_MAX_RXD);
275 new_rx_count = ALIGN(new_rx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
276
277 /* if nothing to do return success */
Mitch Williamsd732a182014-04-24 06:41:37 +0000278 if ((new_tx_count == adapter->tx_desc_count) &&
279 (new_rx_count == adapter->rx_desc_count))
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000280 return 0;
281
Mitch Williamsd732a182014-04-24 06:41:37 +0000282 adapter->tx_desc_count = new_tx_count;
283 adapter->rx_desc_count = new_rx_count;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000284
Mitch Williams67c818a2015-06-19 08:56:30 -0700285 if (netif_running(netdev)) {
286 adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
287 schedule_work(&adapter->reset_task);
288 }
Mitch Williamsd732a182014-04-24 06:41:37 +0000289
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000290 return 0;
291}
292
293/**
294 * i40evf_get_coalesce - Get interrupt coalescing settings
295 * @netdev: network interface device structure
296 * @ec: ethtool coalesce structure
297 *
298 * Returns current coalescing settings. This is referred to elsewhere in the
299 * driver as Interrupt Throttle Rate, as this is how the hardware describes
300 * this functionality.
301 **/
302static int i40evf_get_coalesce(struct net_device *netdev,
Mitch Williams75a64432014-11-11 20:02:42 +0000303 struct ethtool_coalesce *ec)
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000304{
305 struct i40evf_adapter *adapter = netdev_priv(netdev);
306 struct i40e_vsi *vsi = &adapter->vsi;
307
308 ec->tx_max_coalesced_frames = vsi->work_limit;
309 ec->rx_max_coalesced_frames = vsi->work_limit;
310
311 if (ITR_IS_DYNAMIC(vsi->rx_itr_setting))
Mitch Williams32f5f542014-04-04 04:43:10 +0000312 ec->use_adaptive_rx_coalesce = 1;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000313
314 if (ITR_IS_DYNAMIC(vsi->tx_itr_setting))
Mitch Williams32f5f542014-04-04 04:43:10 +0000315 ec->use_adaptive_tx_coalesce = 1;
316
317 ec->rx_coalesce_usecs = vsi->rx_itr_setting & ~I40E_ITR_DYNAMIC;
318 ec->tx_coalesce_usecs = vsi->tx_itr_setting & ~I40E_ITR_DYNAMIC;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000319
320 return 0;
321}
322
323/**
324 * i40evf_set_coalesce - Set interrupt coalescing settings
325 * @netdev: network interface device structure
326 * @ec: ethtool coalesce structure
327 *
328 * Change current coalescing settings.
329 **/
330static int i40evf_set_coalesce(struct net_device *netdev,
Mitch Williams75a64432014-11-11 20:02:42 +0000331 struct ethtool_coalesce *ec)
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000332{
333 struct i40evf_adapter *adapter = netdev_priv(netdev);
334 struct i40e_hw *hw = &adapter->hw;
335 struct i40e_vsi *vsi = &adapter->vsi;
336 struct i40e_q_vector *q_vector;
337 int i;
338
Mitch Williams32f5f542014-04-04 04:43:10 +0000339 if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
340 vsi->work_limit = ec->tx_max_coalesced_frames_irq;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000341
Mitch Williams32f5f542014-04-04 04:43:10 +0000342 if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
343 (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000344 vsi->rx_itr_setting = ec->rx_coalesce_usecs;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000345
Mitch Williams32f5f542014-04-04 04:43:10 +0000346 else
347 return -EINVAL;
348
349 if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
350 (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000351 vsi->tx_itr_setting = ec->tx_coalesce_usecs;
Mitch Williams32f5f542014-04-04 04:43:10 +0000352 else if (ec->use_adaptive_tx_coalesce)
353 vsi->tx_itr_setting = (I40E_ITR_DYNAMIC |
354 ITR_REG_TO_USEC(I40E_ITR_RX_DEF));
355 else
356 return -EINVAL;
357
358 if (ec->use_adaptive_rx_coalesce)
359 vsi->rx_itr_setting |= I40E_ITR_DYNAMIC;
360 else
361 vsi->rx_itr_setting &= ~I40E_ITR_DYNAMIC;
362
363 if (ec->use_adaptive_tx_coalesce)
364 vsi->tx_itr_setting |= I40E_ITR_DYNAMIC;
365 else
366 vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000367
368 for (i = 0; i < adapter->num_msix_vectors - NONQ_VECS; i++) {
Mitch Williams7d96ba12015-10-26 19:44:39 -0400369 q_vector = &adapter->q_vectors[i];
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000370 q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
371 wr32(hw, I40E_VFINT_ITRN1(0, i), q_vector->rx.itr);
372 q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting);
373 wr32(hw, I40E_VFINT_ITRN1(1, i), q_vector->tx.itr);
374 i40e_flush(hw);
375 }
376
377 return 0;
378}
379
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000380/**
381 * i40e_get_rss_hash_opts - Get RSS hash Input Set for each flow type
382 * @adapter: board private structure
383 * @cmd: ethtool rxnfc command
384 *
385 * Returns Success if the flow is supported, else Invalid Input.
386 **/
387static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter,
388 struct ethtool_rxnfc *cmd)
389{
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000390 /* We always hash on IP src and dest addresses */
391 cmd->data = RXH_IP_SRC | RXH_IP_DST;
392
393 switch (cmd->flow_type) {
394 case TCP_V4_FLOW:
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700395 if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP))
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000396 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
397 break;
398 case UDP_V4_FLOW:
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700399 if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP))
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000400 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
401 break;
402
403 case SCTP_V4_FLOW:
404 case AH_ESP_V4_FLOW:
405 case AH_V4_FLOW:
406 case ESP_V4_FLOW:
407 case IPV4_FLOW:
408 break;
409
410 case TCP_V6_FLOW:
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700411 if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP))
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000412 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
413 break;
414 case UDP_V6_FLOW:
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700415 if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP))
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000416 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
417 break;
418
419 case SCTP_V6_FLOW:
420 case AH_ESP_V6_FLOW:
421 case AH_V6_FLOW:
422 case ESP_V6_FLOW:
423 case IPV6_FLOW:
424 break;
425 default:
426 cmd->data = 0;
427 return -EINVAL;
428 }
429
430 return 0;
431}
432
433/**
434 * i40evf_get_rxnfc - command to get RX flow classification rules
435 * @netdev: network interface device structure
436 * @cmd: ethtool rxnfc command
437 *
438 * Returns Success if the command is supported.
439 **/
440static int i40evf_get_rxnfc(struct net_device *netdev,
441 struct ethtool_rxnfc *cmd,
442 u32 *rule_locs)
443{
444 struct i40evf_adapter *adapter = netdev_priv(netdev);
445 int ret = -EOPNOTSUPP;
446
447 switch (cmd->cmd) {
448 case ETHTOOL_GRXRINGS:
Mitch Williamscc052922014-10-25 03:24:34 +0000449 cmd->data = adapter->num_active_queues;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000450 ret = 0;
451 break;
452 case ETHTOOL_GRXFH:
453 ret = i40evf_get_rss_hash_opts(adapter, cmd);
454 break;
455 default:
456 break;
457 }
458
459 return ret;
460}
461
462/**
463 * i40evf_set_rss_hash_opt - Enable/Disable flow types for RSS hash
464 * @adapter: board private structure
465 * @cmd: ethtool rxnfc command
466 *
467 * Returns Success if the flow input set is supported.
468 **/
469static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter,
470 struct ethtool_rxnfc *nfc)
471{
472 struct i40e_hw *hw = &adapter->hw;
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800473 u32 flags = adapter->vf_res->vf_offload_flags;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000474
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000475 /* RSS does not support anything other than hashing
476 * to queues on src and dst IPs and ports
477 */
478 if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
479 RXH_L4_B_0_1 | RXH_L4_B_2_3))
480 return -EINVAL;
481
482 /* We need at least the IP SRC and DEST fields for hashing */
483 if (!(nfc->data & RXH_IP_SRC) ||
484 !(nfc->data & RXH_IP_DST))
485 return -EINVAL;
486
487 switch (nfc->flow_type) {
488 case TCP_V4_FLOW:
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800489 if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
490 if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700491 adapter->hena |=
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800492 BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
493
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700494 adapter->hena |=
495 BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800496 } else {
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000497 return -EINVAL;
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800498 }
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000499 break;
500 case TCP_V6_FLOW:
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800501 if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
502 if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700503 adapter->hena |=
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800504 BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
505
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700506 adapter->hena |=
507 BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800508 } else {
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000509 return -EINVAL;
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800510 }
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000511 break;
512 case UDP_V4_FLOW:
Anjali Singhai Jain6e35c042015-12-09 15:50:24 -0800513 if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800514 if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700515 adapter->hena |=
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800516 BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
517 BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);
518
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700519 adapter->hena |=
520 (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
Jesse Brandeburg41a1d042015-06-04 16:24:02 -0400521 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
Anjali Singhai Jain6e35c042015-12-09 15:50:24 -0800522 } else {
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000523 return -EINVAL;
524 }
525 break;
526 case UDP_V6_FLOW:
Anjali Singhai Jain6e35c042015-12-09 15:50:24 -0800527 if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800528 if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700529 adapter->hena |=
Anjali Singhai Jain3d0da5b2015-12-22 14:25:05 -0800530 BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
531 BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);
532
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700533 adapter->hena |=
534 (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
Jesse Brandeburg41a1d042015-06-04 16:24:02 -0400535 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
Anjali Singhai Jain6e35c042015-12-09 15:50:24 -0800536 } else {
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000537 return -EINVAL;
538 }
539 break;
540 case AH_ESP_V4_FLOW:
541 case AH_V4_FLOW:
542 case ESP_V4_FLOW:
543 case SCTP_V4_FLOW:
544 if ((nfc->data & RXH_L4_B_0_1) ||
545 (nfc->data & RXH_L4_B_2_3))
546 return -EINVAL;
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700547 adapter->hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER);
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000548 break;
549 case AH_ESP_V6_FLOW:
550 case AH_V6_FLOW:
551 case ESP_V6_FLOW:
552 case SCTP_V6_FLOW:
553 if ((nfc->data & RXH_L4_B_0_1) ||
554 (nfc->data & RXH_L4_B_2_3))
555 return -EINVAL;
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700556 adapter->hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER);
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000557 break;
558 case IPV4_FLOW:
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700559 adapter->hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) |
560 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000561 break;
562 case IPV6_FLOW:
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700563 adapter->hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) |
564 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000565 break;
566 default:
567 return -EINVAL;
568 }
569
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700570 if (RSS_PF(adapter)) {
571 adapter->aq_required = I40EVF_FLAG_AQ_SET_HENA;
572 } else {
573 wr32(hw, I40E_VFQF_HENA(0), (u32)adapter->hena);
574 wr32(hw, I40E_VFQF_HENA(1), (u32)(adapter->hena >> 32));
575 i40e_flush(hw);
576 }
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000577
578 return 0;
579}
580
581/**
582 * i40evf_set_rxnfc - command to set RX flow classification rules
583 * @netdev: network interface device structure
584 * @cmd: ethtool rxnfc command
585 *
586 * Returns Success if the command is supported.
587 **/
588static int i40evf_set_rxnfc(struct net_device *netdev,
589 struct ethtool_rxnfc *cmd)
590{
591 struct i40evf_adapter *adapter = netdev_priv(netdev);
592 int ret = -EOPNOTSUPP;
593
594 switch (cmd->cmd) {
595 case ETHTOOL_SRXFH:
596 ret = i40evf_set_rss_hash_opt(adapter, cmd);
597 break;
598 default:
599 break;
600 }
601
602 return ret;
603}
604
605/**
606 * i40evf_get_channels: get the number of channels supported by the device
607 * @netdev: network interface device structure
608 * @ch: channel information structure
609 *
610 * For the purposes of our device, we only use combined channels, i.e. a tx/rx
611 * queue pair. Report one extra channel to match our "other" MSI-X vector.
612 **/
613static void i40evf_get_channels(struct net_device *netdev,
614 struct ethtool_channels *ch)
615{
616 struct i40evf_adapter *adapter = netdev_priv(netdev);
617
618 /* Report maximum channels */
Mitch Williamscc052922014-10-25 03:24:34 +0000619 ch->max_combined = adapter->num_active_queues;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000620
621 ch->max_other = NONQ_VECS;
622 ch->other_count = NONQ_VECS;
623
Mitch Williamscc052922014-10-25 03:24:34 +0000624 ch->combined_count = adapter->num_active_queues;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000625}
626
627/**
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700628 * i40evf_get_rxfh_key_size - get the RSS hash key size
629 * @netdev: network interface device structure
630 *
631 * Returns the table size.
632 **/
633static u32 i40evf_get_rxfh_key_size(struct net_device *netdev)
634{
635 struct i40evf_adapter *adapter = netdev_priv(netdev);
636
637 return adapter->rss_key_size;
638}
639
640/**
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000641 * i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size
642 * @netdev: network interface device structure
643 *
644 * Returns the table size.
645 **/
646static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
647{
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700648 struct i40evf_adapter *adapter = netdev_priv(netdev);
649
650 return adapter->rss_lut_size;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000651}
652
653/**
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100654 * i40evf_get_rxfh - get the rx flow hash indirection table
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000655 * @netdev: network interface device structure
656 * @indir: indirection table
Mitch Williams2cda3f32014-11-11 20:02:31 +0000657 * @key: hash key
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000658 *
659 * Reads the indirection table directly from the hardware. Always returns 0.
660 **/
Eyal Perry892311f2014-12-02 18:12:10 +0200661static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
662 u8 *hfunc)
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000663{
664 struct i40evf_adapter *adapter = netdev_priv(netdev);
Helin Zhang90b02b42015-10-26 19:44:33 -0400665 u16 i;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000666
Eyal Perry892311f2014-12-02 18:12:10 +0200667 if (hfunc)
668 *hfunc = ETH_RSS_HASH_TOP;
669 if (!indir)
670 return 0;
671
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700672 memcpy(key, adapter->rss_key, adapter->rss_key_size);
Helin Zhang90b02b42015-10-26 19:44:33 -0400673
674 /* Each 32 bits pointed by 'indir' is stored with a lut entry */
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700675 for (i = 0; i < adapter->rss_lut_size; i++)
676 indir[i] = (u32)adapter->rss_lut[i];
Helin Zhang90b02b42015-10-26 19:44:33 -0400677
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700678 return 0;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000679}
680
681/**
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100682 * i40evf_set_rxfh - set the rx flow hash indirection table
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000683 * @netdev: network interface device structure
684 * @indir: indirection table
Mitch Williams2cda3f32014-11-11 20:02:31 +0000685 * @key: hash key
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000686 *
687 * Returns -EINVAL if the table specifies an inavlid queue id, otherwise
688 * returns 0 after programming the table.
689 **/
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100690static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
Eyal Perry892311f2014-12-02 18:12:10 +0200691 const u8 *key, const u8 hfunc)
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000692{
693 struct i40evf_adapter *adapter = netdev_priv(netdev);
Helin Zhang2c86ac32015-10-27 16:15:06 -0400694 u16 i;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000695
Eyal Perry892311f2014-12-02 18:12:10 +0200696 /* We do not allow change in unsupported parameters */
697 if (key ||
698 (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
699 return -EOPNOTSUPP;
700 if (!indir)
701 return 0;
702
Helin Zhang2c86ac32015-10-27 16:15:06 -0400703 if (key) {
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700704 memcpy(adapter->rss_key, key, adapter->rss_key_size);
Helin Zhang66f9af852015-10-26 19:44:34 -0400705 }
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000706
Helin Zhang2c86ac32015-10-27 16:15:06 -0400707 /* Each 32 bits pointed by 'indir' is stored with a lut entry */
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700708 for (i = 0; i < adapter->rss_lut_size; i++)
709 adapter->rss_lut[i] = (u8)(indir[i]);
Helin Zhang2c86ac32015-10-27 16:15:06 -0400710
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700711 return i40evf_config_rss(adapter);
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000712}
713
Mitch Williams00e5ec42016-01-15 14:33:10 -0800714/**
715 * i40evf_get_priv_flags - report device private flags
716 * @dev: network interface device structure
717 *
718 * The get string set count and the string set should be matched for each
719 * flag returned. Add new strings for each flag to the i40e_priv_flags_strings
720 * array.
721 *
722 * Returns a u32 bitmap of flags.
723 **/
724static u32 i40evf_get_priv_flags(struct net_device *dev)
725{
726 struct i40evf_adapter *adapter = netdev_priv(dev);
727 u32 ret_flags = 0;
728
729 ret_flags |= adapter->flags & I40EVF_FLAG_RX_PS_ENABLED ?
730 I40EVF_PRIV_FLAGS_PS : 0;
731
732 return ret_flags;
733}
734
735/**
736 * i40evf_set_priv_flags - set private flags
737 * @dev: network interface device structure
738 * @flags: bit flags to be set
739 **/
740static int i40evf_set_priv_flags(struct net_device *dev, u32 flags)
741{
742 struct i40evf_adapter *adapter = netdev_priv(dev);
743 bool reset_required = false;
744
745 if ((flags & I40EVF_PRIV_FLAGS_PS) &&
746 !(adapter->flags & I40EVF_FLAG_RX_PS_ENABLED)) {
747 adapter->flags |= I40EVF_FLAG_RX_PS_ENABLED;
748 reset_required = true;
749 } else if (!(flags & I40EVF_PRIV_FLAGS_PS) &&
750 (adapter->flags & I40EVF_FLAG_RX_PS_ENABLED)) {
751 adapter->flags &= ~I40EVF_FLAG_RX_PS_ENABLED;
752 reset_required = true;
753 }
754
755 /* if needed, issue reset to cause things to take effect */
756 if (reset_required)
757 i40evf_schedule_reset(adapter);
758
759 return 0;
760}
761
Mitch Williamsf0c53c72014-04-04 04:43:11 +0000762static const struct ethtool_ops i40evf_ethtool_ops = {
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000763 .get_settings = i40evf_get_settings,
764 .get_drvinfo = i40evf_get_drvinfo,
765 .get_link = ethtool_op_get_link,
766 .get_ringparam = i40evf_get_ringparam,
767 .set_ringparam = i40evf_set_ringparam,
768 .get_strings = i40evf_get_strings,
769 .get_ethtool_stats = i40evf_get_ethtool_stats,
770 .get_sset_count = i40evf_get_sset_count,
Mitch Williams00e5ec42016-01-15 14:33:10 -0800771 .get_priv_flags = i40evf_get_priv_flags,
772 .set_priv_flags = i40evf_set_priv_flags,
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000773 .get_msglevel = i40evf_get_msglevel,
774 .set_msglevel = i40evf_set_msglevel,
775 .get_coalesce = i40evf_get_coalesce,
776 .set_coalesce = i40evf_set_coalesce,
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000777 .get_rxnfc = i40evf_get_rxnfc,
778 .set_rxnfc = i40evf_set_rxnfc,
779 .get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100780 .get_rxfh = i40evf_get_rxfh,
781 .set_rxfh = i40evf_set_rxfh,
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000782 .get_channels = i40evf_get_channels,
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700783 .get_rxfh_key_size = i40evf_get_rxfh_key_size,
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000784};
785
786/**
787 * i40evf_set_ethtool_ops - Initialize ethtool ops struct
788 * @netdev: network interface device structure
789 *
790 * Sets ethtool ops struct in our netdev so that ethtool can call
791 * our functions.
792 **/
793void i40evf_set_ethtool_ops(struct net_device *netdev)
794{
Wilfried Klaebe7ad24ea2014-05-11 00:12:32 +0000795 netdev->ethtool_ops = &i40evf_ethtool_ops;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000796}