1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3 * Driver for Solarflare network controllers and boards
4 * Copyright 2005-2006 Fen Systems Ltd.
5 * Copyright 2006-2013 Solarflare Communications Inc.
8 #include <linux/netdevice.h>
9 #include <linux/ethtool.h>
10 #include <linux/rtnetlink.h>
12 #include "net_driver.h"
13 #include "workarounds.h"
16 #include "efx_channels.h"
17 #include "rx_common.h"
18 #include "tx_common.h"
19 #include "ethtool_common.h"
23 #define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB
25 /**************************************************************************
29 **************************************************************************
32 /* Identify device by flashing LEDs */
33 static int efx_ethtool_phys_id(struct net_device
*net_dev
,
34 enum ethtool_phys_id_state state
)
36 struct efx_nic
*efx
= netdev_priv(net_dev
);
37 enum efx_led_mode mode
= EFX_LED_DEFAULT
;
46 case ETHTOOL_ID_INACTIVE
:
47 mode
= EFX_LED_DEFAULT
;
49 case ETHTOOL_ID_ACTIVE
:
50 return 1; /* cycle on/off once per second */
53 return efx_siena_mcdi_set_id_led(efx
, mode
);
56 static int efx_ethtool_get_regs_len(struct net_device
*net_dev
)
58 return efx_siena_get_regs_len(netdev_priv(net_dev
));
61 static void efx_ethtool_get_regs(struct net_device
*net_dev
,
62 struct ethtool_regs
*regs
, void *buf
)
64 struct efx_nic
*efx
= netdev_priv(net_dev
);
66 regs
->version
= efx
->type
->revision
;
67 efx_siena_get_regs(efx
, buf
);
71 * Each channel has a single IRQ and moderation timer, started by any
72 * completion (or other event). Unless the module parameter
73 * separate_tx_channels is set, IRQs and moderation are therefore
74 * shared between RX and TX completions. In this case, when RX IRQ
75 * moderation is explicitly changed then TX IRQ moderation is
76 * automatically changed too, but otherwise we fail if the two values
77 * are requested to be different.
79 * The hardware does not support a limit on the number of completions
80 * before an IRQ, so we do not use the max_frames fields. We should
81 * report and require that max_frames == (usecs != 0), but this would
82 * invalidate existing user documentation.
84 * The hardware does not have distinct settings for interrupt
85 * moderation while the previous IRQ is being handled, so we should
86 * not use the 'irq' fields. However, an earlier developer
87 * misunderstood the meaning of the 'irq' fields and the driver did
88 * not support the standard fields. To avoid invalidating existing
89 * user documentation, we report and accept changes through either the
90 * standard or 'irq' fields. If both are changed at the same time, we
91 * prefer the standard field.
93 * We implement adaptive IRQ moderation, but use a different algorithm
94 * from that assumed in the definition of struct ethtool_coalesce.
95 * Therefore we do not use any of the adaptive moderation parameters
99 static int efx_ethtool_get_coalesce(struct net_device
*net_dev
,
100 struct ethtool_coalesce
*coalesce
,
101 struct kernel_ethtool_coalesce
*kernel_coal
,
102 struct netlink_ext_ack
*extack
)
104 struct efx_nic
*efx
= netdev_priv(net_dev
);
105 unsigned int tx_usecs
, rx_usecs
;
108 efx_siena_get_irq_moderation(efx
, &tx_usecs
, &rx_usecs
, &rx_adaptive
);
110 coalesce
->tx_coalesce_usecs
= tx_usecs
;
111 coalesce
->tx_coalesce_usecs_irq
= tx_usecs
;
112 coalesce
->rx_coalesce_usecs
= rx_usecs
;
113 coalesce
->rx_coalesce_usecs_irq
= rx_usecs
;
114 coalesce
->use_adaptive_rx_coalesce
= rx_adaptive
;
119 static int efx_ethtool_set_coalesce(struct net_device
*net_dev
,
120 struct ethtool_coalesce
*coalesce
,
121 struct kernel_ethtool_coalesce
*kernel_coal
,
122 struct netlink_ext_ack
*extack
)
124 struct efx_nic
*efx
= netdev_priv(net_dev
);
125 struct efx_channel
*channel
;
126 unsigned int tx_usecs
, rx_usecs
;
127 bool adaptive
, rx_may_override_tx
;
130 efx_siena_get_irq_moderation(efx
, &tx_usecs
, &rx_usecs
, &adaptive
);
132 if (coalesce
->rx_coalesce_usecs
!= rx_usecs
)
133 rx_usecs
= coalesce
->rx_coalesce_usecs
;
135 rx_usecs
= coalesce
->rx_coalesce_usecs_irq
;
137 adaptive
= coalesce
->use_adaptive_rx_coalesce
;
139 /* If channels are shared, TX IRQ moderation can be quietly
140 * overridden unless it is changed from its old value.
142 rx_may_override_tx
= (coalesce
->tx_coalesce_usecs
== tx_usecs
&&
143 coalesce
->tx_coalesce_usecs_irq
== tx_usecs
);
144 if (coalesce
->tx_coalesce_usecs
!= tx_usecs
)
145 tx_usecs
= coalesce
->tx_coalesce_usecs
;
147 tx_usecs
= coalesce
->tx_coalesce_usecs_irq
;
149 rc
= efx_siena_init_irq_moderation(efx
, tx_usecs
, rx_usecs
, adaptive
,
154 efx_for_each_channel(channel
, efx
)
155 efx
->type
->push_irq_moderation(channel
);
161 efx_ethtool_get_ringparam(struct net_device
*net_dev
,
162 struct ethtool_ringparam
*ring
,
163 struct kernel_ethtool_ringparam
*kernel_ring
,
164 struct netlink_ext_ack
*extack
)
166 struct efx_nic
*efx
= netdev_priv(net_dev
);
168 ring
->rx_max_pending
= EFX_MAX_DMAQ_SIZE
;
169 ring
->tx_max_pending
= EFX_TXQ_MAX_ENT(efx
);
170 ring
->rx_pending
= efx
->rxq_entries
;
171 ring
->tx_pending
= efx
->txq_entries
;
175 efx_ethtool_set_ringparam(struct net_device
*net_dev
,
176 struct ethtool_ringparam
*ring
,
177 struct kernel_ethtool_ringparam
*kernel_ring
,
178 struct netlink_ext_ack
*extack
)
180 struct efx_nic
*efx
= netdev_priv(net_dev
);
183 if (ring
->rx_mini_pending
|| ring
->rx_jumbo_pending
||
184 ring
->rx_pending
> EFX_MAX_DMAQ_SIZE
||
185 ring
->tx_pending
> EFX_TXQ_MAX_ENT(efx
))
188 if (ring
->rx_pending
< EFX_RXQ_MIN_ENT
) {
189 netif_err(efx
, drv
, efx
->net_dev
,
190 "RX queues cannot be smaller than %u\n",
195 txq_entries
= max(ring
->tx_pending
, EFX_TXQ_MIN_ENT(efx
));
196 if (txq_entries
!= ring
->tx_pending
)
197 netif_warn(efx
, drv
, efx
->net_dev
,
198 "increasing TX queue size to minimum of %u\n",
201 return efx_siena_realloc_channels(efx
, ring
->rx_pending
, txq_entries
);
204 static void efx_ethtool_get_wol(struct net_device
*net_dev
,
205 struct ethtool_wolinfo
*wol
)
207 struct efx_nic
*efx
= netdev_priv(net_dev
);
208 return efx
->type
->get_wol(efx
, wol
);
212 static int efx_ethtool_set_wol(struct net_device
*net_dev
,
213 struct ethtool_wolinfo
*wol
)
215 struct efx_nic
*efx
= netdev_priv(net_dev
);
216 return efx
->type
->set_wol(efx
, wol
->wolopts
);
219 static void efx_ethtool_get_fec_stats(struct net_device
*net_dev
,
220 struct ethtool_fec_stats
*fec_stats
)
222 struct efx_nic
*efx
= netdev_priv(net_dev
);
224 if (efx
->type
->get_fec_stats
)
225 efx
->type
->get_fec_stats(efx
, fec_stats
);
228 static int efx_ethtool_get_ts_info(struct net_device
*net_dev
,
229 struct kernel_ethtool_ts_info
*ts_info
)
231 struct efx_nic
*efx
= netdev_priv(net_dev
);
233 efx_siena_ptp_get_ts_info(efx
, ts_info
);
237 const struct ethtool_ops efx_siena_ethtool_ops
= {
238 .supported_coalesce_params
= ETHTOOL_COALESCE_USECS
|
239 ETHTOOL_COALESCE_USECS_IRQ
|
240 ETHTOOL_COALESCE_USE_ADAPTIVE_RX
,
241 .get_drvinfo
= efx_siena_ethtool_get_drvinfo
,
242 .get_regs_len
= efx_ethtool_get_regs_len
,
243 .get_regs
= efx_ethtool_get_regs
,
244 .get_msglevel
= efx_siena_ethtool_get_msglevel
,
245 .set_msglevel
= efx_siena_ethtool_set_msglevel
,
246 .get_link
= ethtool_op_get_link
,
247 .get_coalesce
= efx_ethtool_get_coalesce
,
248 .set_coalesce
= efx_ethtool_set_coalesce
,
249 .get_ringparam
= efx_ethtool_get_ringparam
,
250 .set_ringparam
= efx_ethtool_set_ringparam
,
251 .get_pauseparam
= efx_siena_ethtool_get_pauseparam
,
252 .set_pauseparam
= efx_siena_ethtool_set_pauseparam
,
253 .get_sset_count
= efx_siena_ethtool_get_sset_count
,
254 .self_test
= efx_siena_ethtool_self_test
,
255 .get_strings
= efx_siena_ethtool_get_strings
,
256 .set_phys_id
= efx_ethtool_phys_id
,
257 .get_ethtool_stats
= efx_siena_ethtool_get_stats
,
258 .get_wol
= efx_ethtool_get_wol
,
259 .set_wol
= efx_ethtool_set_wol
,
260 .reset
= efx_siena_ethtool_reset
,
261 .get_rxnfc
= efx_siena_ethtool_get_rxnfc
,
262 .set_rxnfc
= efx_siena_ethtool_set_rxnfc
,
263 .get_rxfh_indir_size
= efx_siena_ethtool_get_rxfh_indir_size
,
264 .get_rxfh_key_size
= efx_siena_ethtool_get_rxfh_key_size
,
265 .get_rxfh
= efx_siena_ethtool_get_rxfh
,
266 .set_rxfh
= efx_siena_ethtool_set_rxfh
,
267 .get_ts_info
= efx_ethtool_get_ts_info
,
268 .get_module_info
= efx_siena_ethtool_get_module_info
,
269 .get_module_eeprom
= efx_siena_ethtool_get_module_eeprom
,
270 .get_link_ksettings
= efx_siena_ethtool_get_link_ksettings
,
271 .set_link_ksettings
= efx_siena_ethtool_set_link_ksettings
,
272 .get_fec_stats
= efx_ethtool_get_fec_stats
,
273 .get_fecparam
= efx_siena_ethtool_get_fecparam
,
274 .set_fecparam
= efx_siena_ethtool_set_fecparam
,