blob: 5a48ee07688fe3dc4b7f2578286d2ee66b26c8ae [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/**
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000381 * i40evf_get_rxnfc - command to get RX flow classification rules
382 * @netdev: network interface device structure
383 * @cmd: ethtool rxnfc command
384 *
385 * Returns Success if the command is supported.
386 **/
387static int i40evf_get_rxnfc(struct net_device *netdev,
388 struct ethtool_rxnfc *cmd,
389 u32 *rule_locs)
390{
391 struct i40evf_adapter *adapter = netdev_priv(netdev);
392 int ret = -EOPNOTSUPP;
393
394 switch (cmd->cmd) {
395 case ETHTOOL_GRXRINGS:
Mitch Williamscc052922014-10-25 03:24:34 +0000396 cmd->data = adapter->num_active_queues;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000397 ret = 0;
398 break;
399 case ETHTOOL_GRXFH:
Carolyn Wybornyb29699b2016-04-13 03:08:26 -0700400 netdev_info(netdev,
401 "RSS hash info is not available to vf, use pf.\n");
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000402 break;
403 default:
404 break;
405 }
406
407 return ret;
408}
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000409/**
410 * i40evf_get_channels: get the number of channels supported by the device
411 * @netdev: network interface device structure
412 * @ch: channel information structure
413 *
414 * For the purposes of our device, we only use combined channels, i.e. a tx/rx
415 * queue pair. Report one extra channel to match our "other" MSI-X vector.
416 **/
417static void i40evf_get_channels(struct net_device *netdev,
418 struct ethtool_channels *ch)
419{
420 struct i40evf_adapter *adapter = netdev_priv(netdev);
421
422 /* Report maximum channels */
Mitch Williamscc052922014-10-25 03:24:34 +0000423 ch->max_combined = adapter->num_active_queues;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000424
425 ch->max_other = NONQ_VECS;
426 ch->other_count = NONQ_VECS;
427
Mitch Williamscc052922014-10-25 03:24:34 +0000428 ch->combined_count = adapter->num_active_queues;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000429}
430
431/**
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700432 * i40evf_get_rxfh_key_size - get the RSS hash key size
433 * @netdev: network interface device structure
434 *
435 * Returns the table size.
436 **/
437static u32 i40evf_get_rxfh_key_size(struct net_device *netdev)
438{
439 struct i40evf_adapter *adapter = netdev_priv(netdev);
440
441 return adapter->rss_key_size;
442}
443
444/**
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000445 * i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size
446 * @netdev: network interface device structure
447 *
448 * Returns the table size.
449 **/
450static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
451{
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700452 struct i40evf_adapter *adapter = netdev_priv(netdev);
453
454 return adapter->rss_lut_size;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000455}
456
457/**
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100458 * i40evf_get_rxfh - get the rx flow hash indirection table
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000459 * @netdev: network interface device structure
460 * @indir: indirection table
Mitch Williams2cda3f32014-11-11 20:02:31 +0000461 * @key: hash key
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000462 *
463 * Reads the indirection table directly from the hardware. Always returns 0.
464 **/
Eyal Perry892311f2014-12-02 18:12:10 +0200465static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
466 u8 *hfunc)
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000467{
468 struct i40evf_adapter *adapter = netdev_priv(netdev);
Helin Zhang90b02b42015-10-26 19:44:33 -0400469 u16 i;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000470
Eyal Perry892311f2014-12-02 18:12:10 +0200471 if (hfunc)
472 *hfunc = ETH_RSS_HASH_TOP;
473 if (!indir)
474 return 0;
475
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700476 memcpy(key, adapter->rss_key, adapter->rss_key_size);
Helin Zhang90b02b42015-10-26 19:44:33 -0400477
478 /* Each 32 bits pointed by 'indir' is stored with a lut entry */
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700479 for (i = 0; i < adapter->rss_lut_size; i++)
480 indir[i] = (u32)adapter->rss_lut[i];
Helin Zhang90b02b42015-10-26 19:44:33 -0400481
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700482 return 0;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000483}
484
485/**
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100486 * i40evf_set_rxfh - set the rx flow hash indirection table
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000487 * @netdev: network interface device structure
488 * @indir: indirection table
Mitch Williams2cda3f32014-11-11 20:02:31 +0000489 * @key: hash key
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000490 *
491 * Returns -EINVAL if the table specifies an inavlid queue id, otherwise
492 * returns 0 after programming the table.
493 **/
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100494static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
Eyal Perry892311f2014-12-02 18:12:10 +0200495 const u8 *key, const u8 hfunc)
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000496{
497 struct i40evf_adapter *adapter = netdev_priv(netdev);
Helin Zhang2c86ac32015-10-27 16:15:06 -0400498 u16 i;
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000499
Eyal Perry892311f2014-12-02 18:12:10 +0200500 /* We do not allow change in unsupported parameters */
501 if (key ||
502 (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
503 return -EOPNOTSUPP;
504 if (!indir)
505 return 0;
506
Helin Zhang2c86ac32015-10-27 16:15:06 -0400507 if (key) {
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700508 memcpy(adapter->rss_key, key, adapter->rss_key_size);
Helin Zhang66f9af852015-10-26 19:44:34 -0400509 }
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000510
Helin Zhang2c86ac32015-10-27 16:15:06 -0400511 /* Each 32 bits pointed by 'indir' is stored with a lut entry */
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700512 for (i = 0; i < adapter->rss_lut_size; i++)
513 adapter->rss_lut[i] = (u8)(indir[i]);
Helin Zhang2c86ac32015-10-27 16:15:06 -0400514
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700515 return i40evf_config_rss(adapter);
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000516}
517
Mitch Williams00e5ec42016-01-15 14:33:10 -0800518/**
519 * i40evf_get_priv_flags - report device private flags
520 * @dev: network interface device structure
521 *
522 * The get string set count and the string set should be matched for each
523 * flag returned. Add new strings for each flag to the i40e_priv_flags_strings
524 * array.
525 *
526 * Returns a u32 bitmap of flags.
527 **/
528static u32 i40evf_get_priv_flags(struct net_device *dev)
529{
530 struct i40evf_adapter *adapter = netdev_priv(dev);
531 u32 ret_flags = 0;
532
533 ret_flags |= adapter->flags & I40EVF_FLAG_RX_PS_ENABLED ?
534 I40EVF_PRIV_FLAGS_PS : 0;
535
536 return ret_flags;
537}
538
539/**
540 * i40evf_set_priv_flags - set private flags
541 * @dev: network interface device structure
542 * @flags: bit flags to be set
543 **/
544static int i40evf_set_priv_flags(struct net_device *dev, u32 flags)
545{
546 struct i40evf_adapter *adapter = netdev_priv(dev);
547 bool reset_required = false;
548
549 if ((flags & I40EVF_PRIV_FLAGS_PS) &&
550 !(adapter->flags & I40EVF_FLAG_RX_PS_ENABLED)) {
551 adapter->flags |= I40EVF_FLAG_RX_PS_ENABLED;
552 reset_required = true;
553 } else if (!(flags & I40EVF_PRIV_FLAGS_PS) &&
554 (adapter->flags & I40EVF_FLAG_RX_PS_ENABLED)) {
555 adapter->flags &= ~I40EVF_FLAG_RX_PS_ENABLED;
556 reset_required = true;
557 }
558
559 /* if needed, issue reset to cause things to take effect */
560 if (reset_required)
561 i40evf_schedule_reset(adapter);
562
563 return 0;
564}
565
Mitch Williamsf0c53c72014-04-04 04:43:11 +0000566static const struct ethtool_ops i40evf_ethtool_ops = {
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000567 .get_settings = i40evf_get_settings,
568 .get_drvinfo = i40evf_get_drvinfo,
569 .get_link = ethtool_op_get_link,
570 .get_ringparam = i40evf_get_ringparam,
571 .set_ringparam = i40evf_set_ringparam,
572 .get_strings = i40evf_get_strings,
573 .get_ethtool_stats = i40evf_get_ethtool_stats,
574 .get_sset_count = i40evf_get_sset_count,
Mitch Williams00e5ec42016-01-15 14:33:10 -0800575 .get_priv_flags = i40evf_get_priv_flags,
576 .set_priv_flags = i40evf_set_priv_flags,
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000577 .get_msglevel = i40evf_get_msglevel,
578 .set_msglevel = i40evf_set_msglevel,
579 .get_coalesce = i40evf_get_coalesce,
580 .set_coalesce = i40evf_set_coalesce,
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000581 .get_rxnfc = i40evf_get_rxnfc,
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000582 .get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
Ben Hutchingsfe62d002014-05-15 01:25:27 +0100583 .get_rxfh = i40evf_get_rxfh,
584 .set_rxfh = i40evf_set_rxfh,
Mitch A Williams4e9dc312014-04-01 04:43:49 +0000585 .get_channels = i40evf_get_channels,
Mitch Williams43a3d9b2016-04-12 08:30:44 -0700586 .get_rxfh_key_size = i40evf_get_rxfh_key_size,
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000587};
588
589/**
590 * i40evf_set_ethtool_ops - Initialize ethtool ops struct
591 * @netdev: network interface device structure
592 *
593 * Sets ethtool ops struct in our netdev so that ethtool can call
594 * our functions.
595 **/
596void i40evf_set_ethtool_ops(struct net_device *netdev)
597{
Wilfried Klaebe7ad24ea2014-05-11 00:12:32 +0000598 netdev->ethtool_ops = &i40evf_ethtool_ops;
Greg Rosefbb7ddf2013-12-21 06:12:56 +0000599}