Merge branch 'cec-defines' into for-linus
[deliverable/linux.git] / drivers / net / ethernet / intel / i40evf / i40evf_ethtool.c
1 /*******************************************************************************
2 *
3 * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
4 * Copyright(c) 2013 - 2016 Intel Corporation.
5 *
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 *
15 * 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 *
18 * 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
32 struct 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. */
43 static 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),
49 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)
59 #define I40EVF_QUEUE_STATS_LEN(_dev) \
60 (((struct i40evf_adapter *)\
61 netdev_priv(_dev))->num_active_queues \
62 * 2 * (sizeof(struct i40e_queue_stats) / sizeof(u64)))
63 #define I40EVF_STATS_LEN(_dev) \
64 (I40EVF_GLOBAL_STATS_LEN + I40EVF_QUEUE_STATS_LEN(_dev))
65
66 static 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
72 /**
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 **/
80 static 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 */
86 ecmd->supported = 0;
87 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 **/
102 static int i40evf_get_sset_count(struct net_device *netdev, int sset)
103 {
104 if (sset == ETH_SS_STATS)
105 return I40EVF_STATS_LEN(netdev);
106 else if (sset == ETH_SS_PRIV_FLAGS)
107 return I40EVF_PRIV_FLAGS_STR_LEN;
108 else
109 return -EINVAL;
110 }
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 **/
120 static 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 }
131 for (j = 0; j < adapter->num_active_queues; j++) {
132 data[i++] = adapter->tx_rings[j].stats.packets;
133 data[i++] = adapter->tx_rings[j].stats.bytes;
134 }
135 for (j = 0; j < adapter->num_active_queues; j++) {
136 data[i++] = adapter->rx_rings[j].stats.packets;
137 data[i++] = adapter->rx_rings[j].stats.bytes;
138 }
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 **/
149 static 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 }
161 for (i = 0; i < adapter->num_active_queues; i++) {
162 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 }
167 for (i = 0; i < adapter->num_active_queues; i++) {
168 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 }
173 } 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 }
179 }
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 **/
188 static u32 i40evf_get_msglevel(struct net_device *netdev)
189 {
190 struct i40evf_adapter *adapter = netdev_priv(netdev);
191
192 return adapter->msg_enable;
193 }
194
195 /**
196 * i40evf_set_msglevel - Set debug message level
197 * @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 **/
203 static void i40evf_set_msglevel(struct net_device *netdev, u32 data)
204 {
205 struct i40evf_adapter *adapter = netdev_priv(netdev);
206
207 if (I40E_DEBUG_USER & data)
208 adapter->hw.debug_mask = data;
209 adapter->msg_enable = data;
210 }
211
212 /**
213 * i40evf_get_drvinfo - Get driver info
214 * @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 **/
219 static 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);
226 strlcpy(drvinfo->fw_version, "N/A", 4);
227 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
228 drvinfo->n_priv_flags = I40EVF_PRIV_FLAGS_STR_LEN;
229 }
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 **/
239 static void i40evf_get_ringparam(struct net_device *netdev,
240 struct ethtool_ringparam *ring)
241 {
242 struct i40evf_adapter *adapter = netdev_priv(netdev);
243
244 ring->rx_max_pending = I40EVF_MAX_RXD;
245 ring->tx_max_pending = I40EVF_MAX_TXD;
246 ring->rx_pending = adapter->rx_desc_count;
247 ring->tx_pending = adapter->tx_desc_count;
248 }
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 **/
258 static 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 */
278 if ((new_tx_count == adapter->tx_desc_count) &&
279 (new_rx_count == adapter->rx_desc_count))
280 return 0;
281
282 adapter->tx_desc_count = new_tx_count;
283 adapter->rx_desc_count = new_rx_count;
284
285 if (netif_running(netdev)) {
286 adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
287 schedule_work(&adapter->reset_task);
288 }
289
290 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 **/
302 static int i40evf_get_coalesce(struct net_device *netdev,
303 struct ethtool_coalesce *ec)
304 {
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))
312 ec->use_adaptive_rx_coalesce = 1;
313
314 if (ITR_IS_DYNAMIC(vsi->tx_itr_setting))
315 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;
319
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 **/
330 static int i40evf_set_coalesce(struct net_device *netdev,
331 struct ethtool_coalesce *ec)
332 {
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
339 if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
340 vsi->work_limit = ec->tx_max_coalesced_frames_irq;
341
342 if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
343 (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
344 vsi->rx_itr_setting = ec->rx_coalesce_usecs;
345
346 else
347 return -EINVAL;
348
349 if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
350 (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
351 vsi->tx_itr_setting = ec->tx_coalesce_usecs;
352 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;
367
368 for (i = 0; i < adapter->num_msix_vectors - NONQ_VECS; i++) {
369 q_vector = &adapter->q_vectors[i];
370 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
380 /**
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 **/
387 static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter,
388 struct ethtool_rxnfc *cmd)
389 {
390 struct i40e_hw *hw = &adapter->hw;
391 u64 hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) |
392 ((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32);
393
394 /* We always hash on IP src and dest addresses */
395 cmd->data = RXH_IP_SRC | RXH_IP_DST;
396
397 switch (cmd->flow_type) {
398 case TCP_V4_FLOW:
399 if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP))
400 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
401 break;
402 case UDP_V4_FLOW:
403 if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP))
404 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
405 break;
406
407 case SCTP_V4_FLOW:
408 case AH_ESP_V4_FLOW:
409 case AH_V4_FLOW:
410 case ESP_V4_FLOW:
411 case IPV4_FLOW:
412 break;
413
414 case TCP_V6_FLOW:
415 if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP))
416 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
417 break;
418 case UDP_V6_FLOW:
419 if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP))
420 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
421 break;
422
423 case SCTP_V6_FLOW:
424 case AH_ESP_V6_FLOW:
425 case AH_V6_FLOW:
426 case ESP_V6_FLOW:
427 case IPV6_FLOW:
428 break;
429 default:
430 cmd->data = 0;
431 return -EINVAL;
432 }
433
434 return 0;
435 }
436
437 /**
438 * i40evf_get_rxnfc - command to get RX flow classification rules
439 * @netdev: network interface device structure
440 * @cmd: ethtool rxnfc command
441 *
442 * Returns Success if the command is supported.
443 **/
444 static int i40evf_get_rxnfc(struct net_device *netdev,
445 struct ethtool_rxnfc *cmd,
446 u32 *rule_locs)
447 {
448 struct i40evf_adapter *adapter = netdev_priv(netdev);
449 int ret = -EOPNOTSUPP;
450
451 switch (cmd->cmd) {
452 case ETHTOOL_GRXRINGS:
453 cmd->data = adapter->num_active_queues;
454 ret = 0;
455 break;
456 case ETHTOOL_GRXFH:
457 ret = i40evf_get_rss_hash_opts(adapter, cmd);
458 break;
459 default:
460 break;
461 }
462
463 return ret;
464 }
465
466 /**
467 * i40evf_set_rss_hash_opt - Enable/Disable flow types for RSS hash
468 * @adapter: board private structure
469 * @cmd: ethtool rxnfc command
470 *
471 * Returns Success if the flow input set is supported.
472 **/
473 static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter,
474 struct ethtool_rxnfc *nfc)
475 {
476 struct i40e_hw *hw = &adapter->hw;
477 u32 flags = adapter->vf_res->vf_offload_flags;
478
479 u64 hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) |
480 ((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32);
481
482 /* RSS does not support anything other than hashing
483 * to queues on src and dst IPs and ports
484 */
485 if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
486 RXH_L4_B_0_1 | RXH_L4_B_2_3))
487 return -EINVAL;
488
489 /* We need at least the IP SRC and DEST fields for hashing */
490 if (!(nfc->data & RXH_IP_SRC) ||
491 !(nfc->data & RXH_IP_DST))
492 return -EINVAL;
493
494 switch (nfc->flow_type) {
495 case TCP_V4_FLOW:
496 if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
497 if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
498 hena |=
499 BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
500
501 hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
502 } else {
503 return -EINVAL;
504 }
505 break;
506 case TCP_V6_FLOW:
507 if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
508 if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
509 hena |=
510 BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
511
512 hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
513 } else {
514 return -EINVAL;
515 }
516 break;
517 case UDP_V4_FLOW:
518 if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
519 if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
520 hena |=
521 BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
522 BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);
523
524 hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
525 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
526 } else {
527 return -EINVAL;
528 }
529 break;
530 case UDP_V6_FLOW:
531 if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
532 if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
533 hena |=
534 BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
535 BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);
536
537 hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
538 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
539 } else {
540 return -EINVAL;
541 }
542 break;
543 case AH_ESP_V4_FLOW:
544 case AH_V4_FLOW:
545 case ESP_V4_FLOW:
546 case SCTP_V4_FLOW:
547 if ((nfc->data & RXH_L4_B_0_1) ||
548 (nfc->data & RXH_L4_B_2_3))
549 return -EINVAL;
550 hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER);
551 break;
552 case AH_ESP_V6_FLOW:
553 case AH_V6_FLOW:
554 case ESP_V6_FLOW:
555 case SCTP_V6_FLOW:
556 if ((nfc->data & RXH_L4_B_0_1) ||
557 (nfc->data & RXH_L4_B_2_3))
558 return -EINVAL;
559 hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER);
560 break;
561 case IPV4_FLOW:
562 hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) |
563 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
564 break;
565 case IPV6_FLOW:
566 hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) |
567 BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
568 break;
569 default:
570 return -EINVAL;
571 }
572
573 wr32(hw, I40E_VFQF_HENA(0), (u32)hena);
574 wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32));
575 i40e_flush(hw);
576
577 return 0;
578 }
579
580 /**
581 * i40evf_set_rxnfc - command to set RX flow classification rules
582 * @netdev: network interface device structure
583 * @cmd: ethtool rxnfc command
584 *
585 * Returns Success if the command is supported.
586 **/
587 static int i40evf_set_rxnfc(struct net_device *netdev,
588 struct ethtool_rxnfc *cmd)
589 {
590 struct i40evf_adapter *adapter = netdev_priv(netdev);
591 int ret = -EOPNOTSUPP;
592
593 switch (cmd->cmd) {
594 case ETHTOOL_SRXFH:
595 ret = i40evf_set_rss_hash_opt(adapter, cmd);
596 break;
597 default:
598 break;
599 }
600
601 return ret;
602 }
603
604 /**
605 * i40evf_get_channels: get the number of channels supported by the device
606 * @netdev: network interface device structure
607 * @ch: channel information structure
608 *
609 * For the purposes of our device, we only use combined channels, i.e. a tx/rx
610 * queue pair. Report one extra channel to match our "other" MSI-X vector.
611 **/
612 static void i40evf_get_channels(struct net_device *netdev,
613 struct ethtool_channels *ch)
614 {
615 struct i40evf_adapter *adapter = netdev_priv(netdev);
616
617 /* Report maximum channels */
618 ch->max_combined = adapter->num_active_queues;
619
620 ch->max_other = NONQ_VECS;
621 ch->other_count = NONQ_VECS;
622
623 ch->combined_count = adapter->num_active_queues;
624 }
625
626 /**
627 * i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size
628 * @netdev: network interface device structure
629 *
630 * Returns the table size.
631 **/
632 static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
633 {
634 return (I40E_VFQF_HLUT_MAX_INDEX + 1) * 4;
635 }
636
637 /**
638 * i40evf_get_rxfh - get the rx flow hash indirection table
639 * @netdev: network interface device structure
640 * @indir: indirection table
641 * @key: hash key
642 *
643 * Reads the indirection table directly from the hardware. Always returns 0.
644 **/
645 static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
646 u8 *hfunc)
647 {
648 struct i40evf_adapter *adapter = netdev_priv(netdev);
649 struct i40e_vsi *vsi = &adapter->vsi;
650 u8 *seed = NULL, *lut;
651 int ret;
652 u16 i;
653
654 if (hfunc)
655 *hfunc = ETH_RSS_HASH_TOP;
656 if (!indir)
657 return 0;
658
659 seed = key;
660
661 lut = kzalloc(I40EVF_HLUT_ARRAY_SIZE, GFP_KERNEL);
662 if (!lut)
663 return -ENOMEM;
664
665 ret = i40evf_get_rss(vsi, seed, lut, I40EVF_HLUT_ARRAY_SIZE);
666 if (ret)
667 goto out;
668
669 /* Each 32 bits pointed by 'indir' is stored with a lut entry */
670 for (i = 0; i < I40EVF_HLUT_ARRAY_SIZE; i++)
671 indir[i] = (u32)lut[i];
672
673 out:
674 kfree(lut);
675
676 return ret;
677 }
678
679 /**
680 * i40evf_set_rxfh - set the rx flow hash indirection table
681 * @netdev: network interface device structure
682 * @indir: indirection table
683 * @key: hash key
684 *
685 * Returns -EINVAL if the table specifies an inavlid queue id, otherwise
686 * returns 0 after programming the table.
687 **/
688 static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
689 const u8 *key, const u8 hfunc)
690 {
691 struct i40evf_adapter *adapter = netdev_priv(netdev);
692 struct i40e_vsi *vsi = &adapter->vsi;
693 u8 *seed = NULL;
694 u16 i;
695
696 /* 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
703 if (key) {
704 if (!vsi->rss_hkey_user) {
705 vsi->rss_hkey_user = kzalloc(I40EVF_HKEY_ARRAY_SIZE,
706 GFP_KERNEL);
707 if (!vsi->rss_hkey_user)
708 return -ENOMEM;
709 }
710 memcpy(vsi->rss_hkey_user, key, I40EVF_HKEY_ARRAY_SIZE);
711 seed = vsi->rss_hkey_user;
712 }
713 if (!vsi->rss_lut_user) {
714 vsi->rss_lut_user = kzalloc(I40EVF_HLUT_ARRAY_SIZE,
715 GFP_KERNEL);
716 if (!vsi->rss_lut_user)
717 return -ENOMEM;
718 }
719
720 /* Each 32 bits pointed by 'indir' is stored with a lut entry */
721 for (i = 0; i < I40EVF_HLUT_ARRAY_SIZE; i++)
722 vsi->rss_lut_user[i] = (u8)(indir[i]);
723
724 return i40evf_config_rss(vsi, seed, vsi->rss_lut_user,
725 I40EVF_HLUT_ARRAY_SIZE);
726 }
727
728 /**
729 * i40evf_get_priv_flags - report device private flags
730 * @dev: network interface device structure
731 *
732 * The get string set count and the string set should be matched for each
733 * flag returned. Add new strings for each flag to the i40e_priv_flags_strings
734 * array.
735 *
736 * Returns a u32 bitmap of flags.
737 **/
738 static u32 i40evf_get_priv_flags(struct net_device *dev)
739 {
740 struct i40evf_adapter *adapter = netdev_priv(dev);
741 u32 ret_flags = 0;
742
743 ret_flags |= adapter->flags & I40EVF_FLAG_RX_PS_ENABLED ?
744 I40EVF_PRIV_FLAGS_PS : 0;
745
746 return ret_flags;
747 }
748
749 /**
750 * i40evf_set_priv_flags - set private flags
751 * @dev: network interface device structure
752 * @flags: bit flags to be set
753 **/
754 static int i40evf_set_priv_flags(struct net_device *dev, u32 flags)
755 {
756 struct i40evf_adapter *adapter = netdev_priv(dev);
757 bool reset_required = false;
758
759 if ((flags & I40EVF_PRIV_FLAGS_PS) &&
760 !(adapter->flags & I40EVF_FLAG_RX_PS_ENABLED)) {
761 adapter->flags |= I40EVF_FLAG_RX_PS_ENABLED;
762 reset_required = true;
763 } else if (!(flags & I40EVF_PRIV_FLAGS_PS) &&
764 (adapter->flags & I40EVF_FLAG_RX_PS_ENABLED)) {
765 adapter->flags &= ~I40EVF_FLAG_RX_PS_ENABLED;
766 reset_required = true;
767 }
768
769 /* if needed, issue reset to cause things to take effect */
770 if (reset_required)
771 i40evf_schedule_reset(adapter);
772
773 return 0;
774 }
775
776 static const struct ethtool_ops i40evf_ethtool_ops = {
777 .get_settings = i40evf_get_settings,
778 .get_drvinfo = i40evf_get_drvinfo,
779 .get_link = ethtool_op_get_link,
780 .get_ringparam = i40evf_get_ringparam,
781 .set_ringparam = i40evf_set_ringparam,
782 .get_strings = i40evf_get_strings,
783 .get_ethtool_stats = i40evf_get_ethtool_stats,
784 .get_sset_count = i40evf_get_sset_count,
785 .get_priv_flags = i40evf_get_priv_flags,
786 .set_priv_flags = i40evf_set_priv_flags,
787 .get_msglevel = i40evf_get_msglevel,
788 .set_msglevel = i40evf_set_msglevel,
789 .get_coalesce = i40evf_get_coalesce,
790 .set_coalesce = i40evf_set_coalesce,
791 .get_rxnfc = i40evf_get_rxnfc,
792 .set_rxnfc = i40evf_set_rxnfc,
793 .get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
794 .get_rxfh = i40evf_get_rxfh,
795 .set_rxfh = i40evf_set_rxfh,
796 .get_channels = i40evf_get_channels,
797 };
798
799 /**
800 * i40evf_set_ethtool_ops - Initialize ethtool ops struct
801 * @netdev: network interface device structure
802 *
803 * Sets ethtool ops struct in our netdev so that ethtool can call
804 * our functions.
805 **/
806 void i40evf_set_ethtool_ops(struct net_device *netdev)
807 {
808 netdev->ethtool_ops = &i40evf_ethtool_ops;
809 }
This page took 0.077417 seconds and 6 git commands to generate.