blob: 9bb2cc7dd4e4afa5d98ac4f76b3794ffa359e7aa [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
Alexander Duyckc424d4a2017-03-14 10:15:26 -070066/* For now we have one and only one private flag and it is only defined
67 * when we have support for the SKIP_CPU_SYNC DMA attribute. Instead
68 * of leaving all this code sitting around empty we will strip it unless
69 * our one private flag is actually available.
70 */
71struct i40evf_priv_flags {
72 char flag_string[ETH_GSTRING_LEN];
73 u32 flag;
74 bool read_only;
75};
76
77#define I40EVF_PRIV_FLAG(_name, _flag, _read_only) { \
78 .flag_string = _name, \
79 .flag = _flag, \
80 .read_only = _read_only, \
81}
82
83static const struct i40evf_priv_flags i40evf_gstrings_priv_flags[] = {
84 I40EVF_PRIV_FLAG("legacy-rx", I40EVF_FLAG_LEGACY_RX, 0),
85};
86
87#define I40EVF_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40evf_gstrings_priv_flags)
88
Greg Rosefbb7ddf2013-12-21 06:12:56 +000089/**
Philippe Reynes48ce8802017-02-04 23:49:03 +010090 * i40evf_get_link_ksettings - Get Link Speed and Duplex settings
Greg Rosefbb7ddf2013-12-21 06:12:56 +000091 * @netdev: network interface device structure
Philippe Reynes48ce8802017-02-04 23:49:03 +010092 * @cmd: ethtool command
Greg Rosefbb7ddf2013-12-21 06:12:56 +000093 *
94 * Reports speed/duplex settings. Because this is a VF, we don't know what
95 * kind of link we really have, so we fake it.
96 **/
Philippe Reynes48ce8802017-02-04 23:49:03 +010097static int i40evf_get_link_ksettings(struct net_device *netdev,
98 struct ethtool_link_ksettings *cmd)
Greg Rosefbb7ddf2013-12-21 06:12:56 +000099{
Mitch Williamsfe458e52016-08-04 11:37:02 -0700100 struct i40evf_adapter *adapter = netdev_priv(netdev);
101
Philippe Reynes48ce8802017-02-04 23:49:03 +0100102 ethtool_link_ksettings_zero_link_mode(cmd, supported);
103 cmd->base.autoneg = AUTONEG_DISABLE;
104 cmd->base.port = PORT_NONE;
Mitch Williamsfe458e52016-08-04 11:37:02 -0700105 /* Set speed and duplex */
106 switch (adapter->link_speed) {
107 case I40E_LINK_SPEED_40GB:
Philippe Reynes48ce8802017-02-04 23:49:03 +0100108 cmd->base.speed = SPEED_40000;
Mitch Williamsfe458e52016-08-04 11:37:02 -0700109 break;
Carolyn Wyborny31232372016-11-21 13:03:48 -0800110 case I40E_LINK_SPEED_25GB:
111#ifdef SPEED_25000
Philippe Reynes48ce8802017-02-04 23:49:03 +0100112 cmd->base.speed = SPEED_25000;
Carolyn Wyborny31232372016-11-21 13:03:48 -0800113#else
114 netdev_info(netdev,
115 "Speed is 25G, display not supported by this version of ethtool.\n");
116#endif
117 break;
Mitch Williamsfe458e52016-08-04 11:37:02 -0700118 case I40E_LINK_SPEED_20GB:
Philippe Reynes48ce8802017-02-04 23:49:03 +0100119 cmd->base.speed = SPEED_20000;
Mitch Williamsfe458e52016-08-04 11:37:02 -0700120 break;
121 case I40E_LINK_SPEED_10GB:
Philippe Reynes48ce8802017-02-04 23:49:03 +0100122 cmd->base.speed = SPEED_10000;
Mitch Williamsfe458e52016-08-04 11:37:02 -0700123 break;
124 case I40E_LINK_SPEED_1GB:
Philippe Reynes48ce8802017-02-04 23:49:03 +0100125 cmd->base.speed = SPEED_1000;
Mitch Williamsfe458e52016-08-04 11:37:02 -0700126 break;
127 case I40E_LINK_SPEED_100MB:
Philippe Reynes48ce8802017-02-04 23:49:03 +0100128 cmd->base.speed = SPEED_100;
Mitch Williamsfe458e52016-08-04 11:37:02 -0700129 break;
130 default:
131 break;
132 }
Philippe Reynes48ce8802017-02-04 23:49:03 +0100133 cmd->base.duplex = DUPLEX_FULL;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000134
135 return 0;
136}
137
138/**
139 * i40evf_get_sset_count - Get length of string set
140 * @netdev: network interface device structure
141 * @sset: id of string set
142 *
143 * Reports size of string table. This driver only supports
144 * strings for statistics.
145 **/
146static int i40evf_get_sset_count(struct net_device *netdev, int sset)
147{
148 if (sset == ETH_SS_STATS)
Mitch Williamsc7b8d972014-04-04 04:43:08 +0000149 return I40EVF_STATS_LEN(netdev);
Alexander Duyckc424d4a2017-03-14 10:15:26 -0700150 else if (sset == ETH_SS_PRIV_FLAGS)
151 return I40EVF_PRIV_FLAGS_STR_LEN;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000152 else
Mitch Williamsc7b8d972014-04-04 04:43:08 +0000153 return -EINVAL;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000154}
155
156/**
157 * i40evf_get_ethtool_stats - report device statistics
158 * @netdev: network interface device structure
159 * @stats: ethtool statistics structure
160 * @data: pointer to data buffer
161 *
162 * All statistics are added to the data buffer as an array of u64.
163 **/
164static void i40evf_get_ethtool_stats(struct net_device *netdev,
165 struct ethtool_stats *stats, u64 *data)
166{
167 struct i40evf_adapter *adapter = netdev_priv(netdev);
168 int i, j;
169 char *p;
170
171 for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
172 p = (char *)adapter + i40evf_gstrings_stats[i].stat_offset;
173 data[i] = *(u64 *)p;
174 }
Mitch Williamscc052922014-10-25 03:24:34 +0000175 for (j = 0; j < adapter->num_active_queues; j++) {
Mitch Williams0dd438d2015-10-26 19:44:40 -0400176 data[i++] = adapter->tx_rings[j].stats.packets;
177 data[i++] = adapter->tx_rings[j].stats.bytes;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000178 }
Mitch Williamscc052922014-10-25 03:24:34 +0000179 for (j = 0; j < adapter->num_active_queues; j++) {
Mitch Williams0dd438d2015-10-26 19:44:40 -0400180 data[i++] = adapter->rx_rings[j].stats.packets;
181 data[i++] = adapter->rx_rings[j].stats.bytes;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000182 }
183}
184
185/**
186 * i40evf_get_strings - Get string set
187 * @netdev: network interface device structure
188 * @sset: id of string set
189 * @data: buffer for string data
190 *
191 * Builds stats string table.
192 **/
193static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
194{
195 struct i40evf_adapter *adapter = netdev_priv(netdev);
196 u8 *p = data;
197 int i;
198
199 if (sset == ETH_SS_STATS) {
200 for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
201 memcpy(p, i40evf_gstrings_stats[i].stat_string,
202 ETH_GSTRING_LEN);
203 p += ETH_GSTRING_LEN;
204 }
Mitch Williamscc052922014-10-25 03:24:34 +0000205 for (i = 0; i < adapter->num_active_queues; i++) {
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000206 snprintf(p, ETH_GSTRING_LEN, "tx-%u.packets", i);
207 p += ETH_GSTRING_LEN;
208 snprintf(p, ETH_GSTRING_LEN, "tx-%u.bytes", i);
209 p += ETH_GSTRING_LEN;
210 }
Mitch Williamscc052922014-10-25 03:24:34 +0000211 for (i = 0; i < adapter->num_active_queues; i++) {
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000212 snprintf(p, ETH_GSTRING_LEN, "rx-%u.packets", i);
213 p += ETH_GSTRING_LEN;
214 snprintf(p, ETH_GSTRING_LEN, "rx-%u.bytes", i);
215 p += ETH_GSTRING_LEN;
216 }
Alexander Duyckc424d4a2017-03-14 10:15:26 -0700217 } else if (sset == ETH_SS_PRIV_FLAGS) {
218 for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
219 snprintf(p, ETH_GSTRING_LEN, "%s",
220 i40evf_gstrings_priv_flags[i].flag_string);
221 p += ETH_GSTRING_LEN;
222 }
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000223 }
224}
225
226/**
Alexander Duyckc424d4a2017-03-14 10:15:26 -0700227 * i40evf_get_priv_flags - report device private flags
228 * @dev: network interface device structure
229 *
230 * The get string set count and the string set should be matched for each
231 * flag returned. Add new strings for each flag to the i40e_gstrings_priv_flags
232 * array.
233 *
234 * Returns a u32 bitmap of flags.
235 **/
236static u32 i40evf_get_priv_flags(struct net_device *netdev)
237{
238 struct i40evf_adapter *adapter = netdev_priv(netdev);
239 u32 i, ret_flags = 0;
240
241 for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
242 const struct i40evf_priv_flags *priv_flags;
243
244 priv_flags = &i40evf_gstrings_priv_flags[i];
245
246 if (priv_flags->flag & adapter->flags)
247 ret_flags |= BIT(i);
248 }
249
250 return ret_flags;
251}
252
253/**
254 * i40evf_set_priv_flags - set private flags
255 * @dev: network interface device structure
256 * @flags: bit flags to be set
257 **/
258static int i40evf_set_priv_flags(struct net_device *netdev, u32 flags)
259{
260 struct i40evf_adapter *adapter = netdev_priv(netdev);
261 u64 changed_flags;
262 u32 i;
263
264 changed_flags = adapter->flags;
265
266 for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
267 const struct i40evf_priv_flags *priv_flags;
268
269 priv_flags = &i40evf_gstrings_priv_flags[i];
270
271 if (priv_flags->read_only)
272 continue;
273
274 if (flags & BIT(i))
275 adapter->flags |= priv_flags->flag;
276 else
277 adapter->flags &= ~(priv_flags->flag);
278 }
279
280 /* check for flags that changed */
281 changed_flags ^= adapter->flags;
282
283 /* Process any additional changes needed as a result of flag changes. */
284
285 /* issue a reset to force legacy-rx change to take effect */
286 if (changed_flags & I40EVF_FLAG_LEGACY_RX) {
287 if (netif_running(netdev)) {
288 adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
289 schedule_work(&adapter->reset_task);
290 }
291 }
292
293 return 0;
294}
295
296/**
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000297 * i40evf_get_msglevel - Get debug message level
298 * @netdev: network interface device structure
299 *
300 * Returns current debug message level.
301 **/
302static u32 i40evf_get_msglevel(struct net_device *netdev)
303{
304 struct i40evf_adapter *adapter = netdev_priv(netdev);
Mitch Williams75a64432014-11-11 20:02:42 +0000305
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000306 return adapter->msg_enable;
307}
308
309/**
Ashish Shah0e888982015-02-06 08:52:10 +0000310 * i40evf_set_msglevel - Set debug message level
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000311 * @netdev: network interface device structure
312 * @data: message level
313 *
314 * Set current debug message level. Higher values cause the driver to
315 * be noisier.
316 **/
317static void i40evf_set_msglevel(struct net_device *netdev, u32 data)
318{
319 struct i40evf_adapter *adapter = netdev_priv(netdev);
Mitch Williams75a64432014-11-11 20:02:42 +0000320
Ashish Shah0e888982015-02-06 08:52:10 +0000321 if (I40E_DEBUG_USER & data)
322 adapter->hw.debug_mask = data;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000323 adapter->msg_enable = data;
324}
325
326/**
Jesse Brandeburgb39c1e22014-08-01 13:27:08 -0700327 * i40evf_get_drvinfo - Get driver info
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000328 * @netdev: network interface device structure
329 * @drvinfo: ethool driver info structure
330 *
331 * Returns information about the driver and device for display to the user.
332 **/
333static void i40evf_get_drvinfo(struct net_device *netdev,
334 struct ethtool_drvinfo *drvinfo)
335{
336 struct i40evf_adapter *adapter = netdev_priv(netdev);
337
338 strlcpy(drvinfo->driver, i40evf_driver_name, 32);
339 strlcpy(drvinfo->version, i40evf_driver_version, 32);
Mitch Williamscc470a82015-03-27 00:12:11 -0700340 strlcpy(drvinfo->fw_version, "N/A", 4);
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000341 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
Alexander Duyckc424d4a2017-03-14 10:15:26 -0700342 drvinfo->n_priv_flags = I40EVF_PRIV_FLAGS_STR_LEN;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000343}
344
345/**
346 * i40evf_get_ringparam - Get ring parameters
347 * @netdev: network interface device structure
348 * @ring: ethtool ringparam structure
349 *
350 * Returns current ring parameters. TX and RX rings are reported separately,
351 * but the number of rings is not reported.
352 **/
353static void i40evf_get_ringparam(struct net_device *netdev,
Mitch Williams75a64432014-11-11 20:02:42 +0000354 struct ethtool_ringparam *ring)
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000355{
356 struct i40evf_adapter *adapter = netdev_priv(netdev);
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000357
358 ring->rx_max_pending = I40EVF_MAX_RXD;
359 ring->tx_max_pending = I40EVF_MAX_TXD;
Mitch Williamsd732a182014-04-24 06:41:37 +0000360 ring->rx_pending = adapter->rx_desc_count;
361 ring->tx_pending = adapter->tx_desc_count;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000362}
363
364/**
365 * i40evf_set_ringparam - Set ring parameters
366 * @netdev: network interface device structure
367 * @ring: ethtool ringparam structure
368 *
369 * Sets ring parameters. TX and RX rings are controlled separately, but the
370 * number of rings is not specified, so all rings get the same settings.
371 **/
372static int i40evf_set_ringparam(struct net_device *netdev,
373 struct ethtool_ringparam *ring)
374{
375 struct i40evf_adapter *adapter = netdev_priv(netdev);
376 u32 new_rx_count, new_tx_count;
377
378 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
379 return -EINVAL;
380
381 new_tx_count = clamp_t(u32, ring->tx_pending,
382 I40EVF_MIN_TXD,
383 I40EVF_MAX_TXD);
384 new_tx_count = ALIGN(new_tx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
385
386 new_rx_count = clamp_t(u32, ring->rx_pending,
387 I40EVF_MIN_RXD,
388 I40EVF_MAX_RXD);
389 new_rx_count = ALIGN(new_rx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
390
391 /* if nothing to do return success */
Mitch Williamsd732a182014-04-24 06:41:37 +0000392 if ((new_tx_count == adapter->tx_desc_count) &&
393 (new_rx_count == adapter->rx_desc_count))
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000394 return 0;
395
Mitch Williamsd732a182014-04-24 06:41:37 +0000396 adapter->tx_desc_count = new_tx_count;
397 adapter->rx_desc_count = new_rx_count;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000398
Mitch Williams67c818a2015-06-19 08:56:30 -0700399 if (netif_running(netdev)) {
400 adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
401 schedule_work(&adapter->reset_task);
402 }
Mitch Williamsd732a182014-04-24 06:41:37 +0000403
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000404 return 0;
405}
406
407/**
Jacob Keller65e87c02016-09-12 14:18:44 -0700408 * __i40evf_get_coalesce - get per-queue coalesce settings
409 * @netdev: the netdev to check
410 * @ec: ethtool coalesce data structure
411 * @queue: which queue to pick
412 *
413 * Gets the per-queue settings for coalescence. Specifically Rx and Tx usecs
414 * are per queue. If queue is <0 then we default to queue 0 as the
415 * representative value.
416 **/
417static int __i40evf_get_coalesce(struct net_device *netdev,
418 struct ethtool_coalesce *ec,
419 int queue)
420{
421 struct i40evf_adapter *adapter = netdev_priv(netdev);
422 struct i40e_vsi *vsi = &adapter->vsi;
423 struct i40e_ring *rx_ring, *tx_ring;
424
425 ec->tx_max_coalesced_frames = vsi->work_limit;
426 ec->rx_max_coalesced_frames = vsi->work_limit;
427
428 /* Rx and Tx usecs per queue value. If user doesn't specify the
429 * queue, return queue 0's value to represent.
430 */
431 if (queue < 0)
432 queue = 0;
433 else if (queue >= adapter->num_active_queues)
434 return -EINVAL;
435
436 rx_ring = &adapter->rx_rings[queue];
437 tx_ring = &adapter->tx_rings[queue];
438
439 if (ITR_IS_DYNAMIC(rx_ring->rx_itr_setting))
440 ec->use_adaptive_rx_coalesce = 1;
441
442 if (ITR_IS_DYNAMIC(tx_ring->tx_itr_setting))
443 ec->use_adaptive_tx_coalesce = 1;
444
445 ec->rx_coalesce_usecs = rx_ring->rx_itr_setting & ~I40E_ITR_DYNAMIC;
446 ec->tx_coalesce_usecs = tx_ring->tx_itr_setting & ~I40E_ITR_DYNAMIC;
447
448 return 0;
449}
450
451/**
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000452 * i40evf_get_coalesce - Get interrupt coalescing settings
453 * @netdev: network interface device structure
454 * @ec: ethtool coalesce structure
455 *
456 * Returns current coalescing settings. This is referred to elsewhere in the
457 * driver as Interrupt Throttle Rate, as this is how the hardware describes
Jacob Keller65e87c02016-09-12 14:18:44 -0700458 * this functionality. Note that if per-queue settings have been modified this
459 * only represents the settings of queue 0.
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000460 **/
461static int i40evf_get_coalesce(struct net_device *netdev,
Mitch Williams75a64432014-11-11 20:02:42 +0000462 struct ethtool_coalesce *ec)
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000463{
Jacob Keller65e87c02016-09-12 14:18:44 -0700464 return __i40evf_get_coalesce(netdev, ec, -1);
465}
466
467/**
468 * i40evf_get_per_queue_coalesce - get coalesce values for specific queue
469 * @netdev: netdev to read
470 * @ec: coalesce settings from ethtool
471 * @queue: the queue to read
472 *
473 * Read specific queue's coalesce settings.
474 **/
475static int i40evf_get_per_queue_coalesce(struct net_device *netdev,
476 u32 queue,
477 struct ethtool_coalesce *ec)
478{
479 return __i40evf_get_coalesce(netdev, ec, queue);
480}
481
482/**
483 * i40evf_set_itr_per_queue - set ITR values for specific queue
484 * @vsi: the VSI to set values for
485 * @ec: coalesce settings from ethtool
486 * @queue: the queue to modify
487 *
488 * Change the ITR settings for a specific queue.
489 **/
490static void i40evf_set_itr_per_queue(struct i40evf_adapter *adapter,
491 struct ethtool_coalesce *ec,
492 int queue)
493{
494 struct i40e_vsi *vsi = &adapter->vsi;
495 struct i40e_hw *hw = &adapter->hw;
496 struct i40e_q_vector *q_vector;
497 u16 vector;
498
499 adapter->rx_rings[queue].rx_itr_setting = ec->rx_coalesce_usecs;
500 adapter->tx_rings[queue].tx_itr_setting = ec->tx_coalesce_usecs;
501
502 if (ec->use_adaptive_rx_coalesce)
503 adapter->rx_rings[queue].rx_itr_setting |= I40E_ITR_DYNAMIC;
504 else
505 adapter->rx_rings[queue].rx_itr_setting &= ~I40E_ITR_DYNAMIC;
506
507 if (ec->use_adaptive_tx_coalesce)
508 adapter->tx_rings[queue].tx_itr_setting |= I40E_ITR_DYNAMIC;
509 else
510 adapter->tx_rings[queue].tx_itr_setting &= ~I40E_ITR_DYNAMIC;
511
512 q_vector = adapter->rx_rings[queue].q_vector;
513 q_vector->rx.itr = ITR_TO_REG(adapter->rx_rings[queue].rx_itr_setting);
514 vector = vsi->base_vector + q_vector->v_idx;
515 wr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, vector - 1), q_vector->rx.itr);
516
517 q_vector = adapter->tx_rings[queue].q_vector;
518 q_vector->tx.itr = ITR_TO_REG(adapter->tx_rings[queue].tx_itr_setting);
519 vector = vsi->base_vector + q_vector->v_idx;
520 wr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, vector - 1), q_vector->tx.itr);
521
522 i40e_flush(hw);
523}
524
525/**
526 * __i40evf_set_coalesce - set coalesce settings for particular queue
527 * @netdev: the netdev to change
528 * @ec: ethtool coalesce settings
529 * @queue: the queue to change
530 *
531 * Sets the coalesce settings for a particular queue.
532 **/
533static int __i40evf_set_coalesce(struct net_device *netdev,
534 struct ethtool_coalesce *ec,
535 int queue)
536{
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000537 struct i40evf_adapter *adapter = netdev_priv(netdev);
538 struct i40e_vsi *vsi = &adapter->vsi;
Jacob Keller65e87c02016-09-12 14:18:44 -0700539 int i;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000540
Jacob Keller65e87c02016-09-12 14:18:44 -0700541 if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
542 vsi->work_limit = ec->tx_max_coalesced_frames_irq;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000543
Jacob Keller65e87c02016-09-12 14:18:44 -0700544 if (ec->rx_coalesce_usecs == 0) {
545 if (ec->use_adaptive_rx_coalesce)
546 netif_info(adapter, drv, netdev, "rx-usecs=0, need to disable adaptive-rx for a complete disable\n");
547 } else if ((ec->rx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||
548 (ec->rx_coalesce_usecs > (I40E_MAX_ITR << 1))) {
549 netif_info(adapter, drv, netdev, "Invalid value, rx-usecs range is 0-8160\n");
550 return -EINVAL;
551 }
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000552
Jacob Keller65e87c02016-09-12 14:18:44 -0700553 else
554 if (ec->tx_coalesce_usecs == 0) {
555 if (ec->use_adaptive_tx_coalesce)
556 netif_info(adapter, drv, netdev, "tx-usecs=0, need to disable adaptive-tx for a complete disable\n");
557 } else if ((ec->tx_coalesce_usecs < (I40E_MIN_ITR << 1)) ||
558 (ec->tx_coalesce_usecs > (I40E_MAX_ITR << 1))) {
559 netif_info(adapter, drv, netdev, "Invalid value, tx-usecs range is 0-8160\n");
560 return -EINVAL;
561 }
Mitch Williams32f5f542014-04-04 04:43:10 +0000562
Jacob Keller65e87c02016-09-12 14:18:44 -0700563 /* Rx and Tx usecs has per queue value. If user doesn't specify the
564 * queue, apply to all queues.
565 */
566 if (queue < 0) {
567 for (i = 0; i < adapter->num_active_queues; i++)
568 i40evf_set_itr_per_queue(adapter, ec, i);
569 } else if (queue < adapter->num_active_queues) {
570 i40evf_set_itr_per_queue(adapter, ec, queue);
571 } else {
572 netif_info(adapter, drv, netdev, "Invalid queue value, queue range is 0 - %d\n",
573 adapter->num_active_queues - 1);
574 return -EINVAL;
575 }
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000576
577 return 0;
578}
579
580/**
581 * i40evf_set_coalesce - Set interrupt coalescing settings
582 * @netdev: network interface device structure
583 * @ec: ethtool coalesce structure
584 *
Jacob Keller65e87c02016-09-12 14:18:44 -0700585 * Change current coalescing settings for every queue.
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000586 **/
587static int i40evf_set_coalesce(struct net_device *netdev,
Mitch Williams75a64432014-11-11 20:02:42 +0000588 struct ethtool_coalesce *ec)
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000589{
Jacob Keller65e87c02016-09-12 14:18:44 -0700590 return __i40evf_set_coalesce(netdev, ec, -1);
591}
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000592
Jacob Keller65e87c02016-09-12 14:18:44 -0700593/**
594 * i40evf_set_per_queue_coalesce - set specific queue's coalesce settings
595 * @netdev: the netdev to change
596 * @ec: ethtool's coalesce settings
597 * @queue: the queue to modify
598 *
599 * Modifies a specific queue's coalesce settings.
600 */
601static int i40evf_set_per_queue_coalesce(struct net_device *netdev,
602 u32 queue,
603 struct ethtool_coalesce *ec)
604{
605 return __i40evf_set_coalesce(netdev, ec, queue);
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000606}
607
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000608/**
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000609 * i40evf_get_rxnfc - command to get RX flow classification rules
610 * @netdev: network interface device structure
611 * @cmd: ethtool rxnfc command
612 *
613 * Returns Success if the command is supported.
614 **/
615static int i40evf_get_rxnfc(struct net_device *netdev,
616 struct ethtool_rxnfc *cmd,
617 u32 *rule_locs)
618{
619 struct i40evf_adapter *adapter = netdev_priv(netdev);
620 int ret = -EOPNOTSUPP;
621
622 switch (cmd->cmd) {
623 case ETHTOOL_GRXRINGS:
Mitch Williamscc052922014-10-25 03:24:34 +0000624 cmd->data = adapter->num_active_queues;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000625 ret = 0;
626 break;
627 case ETHTOOL_GRXFH:
Carolyn Wybornyb29699b2016-04-13 03:08:26 -0700628 netdev_info(netdev,
629 "RSS hash info is not available to vf, use pf.\n");
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000630 break;
631 default:
632 break;
633 }
634
635 return ret;
636}
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000637/**
638 * i40evf_get_channels: get the number of channels supported by the device
639 * @netdev: network interface device structure
640 * @ch: channel information structure
641 *
642 * For the purposes of our device, we only use combined channels, i.e. a tx/rx
643 * queue pair. Report one extra channel to match our "other" MSI-X vector.
644 **/
645static void i40evf_get_channels(struct net_device *netdev,
646 struct ethtool_channels *ch)
647{
648 struct i40evf_adapter *adapter = netdev_priv(netdev);
649
650 /* Report maximum channels */
Mitch Williamscc052922014-10-25 03:24:34 +0000651 ch->max_combined = adapter->num_active_queues;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000652
653 ch->max_other = NONQ_VECS;
654 ch->other_count = NONQ_VECS;
655
Mitch Williamscc052922014-10-25 03:24:34 +0000656 ch->combined_count = adapter->num_active_queues;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000657}
658
659/**
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700660 * i40evf_get_rxfh_key_size - get the RSS hash key size
661 * @netdev: network interface device structure
662 *
663 * Returns the table size.
664 **/
665static u32 i40evf_get_rxfh_key_size(struct net_device *netdev)
666{
667 struct i40evf_adapter *adapter = netdev_priv(netdev);
668
669 return adapter->rss_key_size;
670}
671
672/**
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000673 * i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size
674 * @netdev: network interface device structure
675 *
676 * Returns the table size.
677 **/
678static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
679{
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700680 struct i40evf_adapter *adapter = netdev_priv(netdev);
681
682 return adapter->rss_lut_size;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000683}
684
685/**
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100686 * i40evf_get_rxfh - get the rx flow hash indirection table
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000687 * @netdev: network interface device structure
688 * @indir: indirection table
Mitch Williams2cda3f32014-11-11 20:02:31 +0000689 * @key: hash key
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000690 *
691 * Reads the indirection table directly from the hardware. Always returns 0.
692 **/
Eyal Perry892311f2014-12-02 18:12:10 +0200693static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
694 u8 *hfunc)
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000695{
696 struct i40evf_adapter *adapter = netdev_priv(netdev);
Helin Zhang90b02b42015-10-26 19:44:33 -0400697 u16 i;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000698
Eyal Perry892311f2014-12-02 18:12:10 +0200699 if (hfunc)
700 *hfunc = ETH_RSS_HASH_TOP;
701 if (!indir)
702 return 0;
703
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700704 memcpy(key, adapter->rss_key, adapter->rss_key_size);
Helin Zhang90b02b42015-10-26 19:44:33 -0400705
706 /* Each 32 bits pointed by 'indir' is stored with a lut entry */
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700707 for (i = 0; i < adapter->rss_lut_size; i++)
708 indir[i] = (u32)adapter->rss_lut[i];
Helin Zhang90b02b42015-10-26 19:44:33 -0400709
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700710 return 0;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000711}
712
713/**
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100714 * i40evf_set_rxfh - set the rx flow hash indirection table
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000715 * @netdev: network interface device structure
716 * @indir: indirection table
Mitch Williams2cda3f32014-11-11 20:02:31 +0000717 * @key: hash key
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000718 *
719 * Returns -EINVAL if the table specifies an inavlid queue id, otherwise
720 * returns 0 after programming the table.
721 **/
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100722static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
Eyal Perry892311f2014-12-02 18:12:10 +0200723 const u8 *key, const u8 hfunc)
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000724{
725 struct i40evf_adapter *adapter = netdev_priv(netdev);
Helin Zhang2c86ac32015-10-27 16:15:06 -0400726 u16 i;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000727
Eyal Perry892311f2014-12-02 18:12:10 +0200728 /* We do not allow change in unsupported parameters */
729 if (key ||
730 (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
731 return -EOPNOTSUPP;
732 if (!indir)
733 return 0;
734
Helin Zhang2c86ac32015-10-27 16:15:06 -0400735 if (key) {
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700736 memcpy(adapter->rss_key, key, adapter->rss_key_size);
Helin Zhang66f9af852015-10-26 19:44:34 -0400737 }
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000738
Helin Zhang2c86ac32015-10-27 16:15:06 -0400739 /* Each 32 bits pointed by 'indir' is stored with a lut entry */
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700740 for (i = 0; i < adapter->rss_lut_size; i++)
741 adapter->rss_lut[i] = (u8)(indir[i]);
Helin Zhang2c86ac32015-10-27 16:15:06 -0400742
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700743 return i40evf_config_rss(adapter);
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000744}
745
Mitch Williamsf0c53c72014-04-04 04:43:11 +0000746static const struct ethtool_ops i40evf_ethtool_ops = {
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000747 .get_drvinfo = i40evf_get_drvinfo,
748 .get_link = ethtool_op_get_link,
749 .get_ringparam = i40evf_get_ringparam,
750 .set_ringparam = i40evf_set_ringparam,
751 .get_strings = i40evf_get_strings,
752 .get_ethtool_stats = i40evf_get_ethtool_stats,
753 .get_sset_count = i40evf_get_sset_count,
Alexander Duyckc424d4a2017-03-14 10:15:26 -0700754 .get_priv_flags = i40evf_get_priv_flags,
755 .set_priv_flags = i40evf_set_priv_flags,
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000756 .get_msglevel = i40evf_get_msglevel,
757 .set_msglevel = i40evf_set_msglevel,
758 .get_coalesce = i40evf_get_coalesce,
759 .set_coalesce = i40evf_set_coalesce,
Jacob Keller65e87c02016-09-12 14:18:44 -0700760 .get_per_queue_coalesce = i40evf_get_per_queue_coalesce,
761 .set_per_queue_coalesce = i40evf_set_per_queue_coalesce,
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000762 .get_rxnfc = i40evf_get_rxnfc,
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000763 .get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100764 .get_rxfh = i40evf_get_rxfh,
765 .set_rxfh = i40evf_set_rxfh,
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000766 .get_channels = i40evf_get_channels,
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700767 .get_rxfh_key_size = i40evf_get_rxfh_key_size,
Philippe Reynes48ce8802017-02-04 23:49:03 +0100768 .get_link_ksettings = i40evf_get_link_ksettings,
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000769};
770
771/**
772 * i40evf_set_ethtool_ops - Initialize ethtool ops struct
773 * @netdev: network interface device structure
774 *
775 * Sets ethtool ops struct in our netdev so that ethtool can call
776 * our functions.
777 **/
778void i40evf_set_ethtool_ops(struct net_device *netdev)
779{
Wilfried Klaebe7ad24ea2014-05-11 00:12:32 +0000780 netdev->ethtool_ops = &i40evf_ethtool_ops;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000781}