diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-04-27 07:55:59 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-04-29 01:42:43 -0400 |
commit | 8ceee660aacb29721e26f08e336c58dc4847d1bd (patch) | |
tree | 158122642e6f21fe85d072c50d6185a0d0cf6834 /drivers/net/sfc/ethtool.c | |
parent | 358c12953b88c5a06a57c33eb27c753b2e7934d1 (diff) |
New driver "sfc" for Solarstorm SFC4000 controller.
The driver supports the 10Xpress PHY and XFP modules on our reference
designs SFE4001 and SFE4002 and the SMC models SMC10GPCIe-XFP and
SMC10GPCIe-10BT.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/sfc/ethtool.c')
-rw-r--r-- | drivers/net/sfc/ethtool.c | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c new file mode 100644 index 000000000000..ad541badbd98 --- /dev/null +++ b/drivers/net/sfc/ethtool.c | |||
@@ -0,0 +1,460 @@ | |||
1 | /**************************************************************************** | ||
2 | * Driver for Solarflare Solarstorm network controllers and boards | ||
3 | * Copyright 2005-2006 Fen Systems Ltd. | ||
4 | * Copyright 2006-2008 Solarflare Communications Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published | ||
8 | * by the Free Software Foundation, incorporated herein by reference. | ||
9 | */ | ||
10 | |||
11 | #include <linux/netdevice.h> | ||
12 | #include <linux/ethtool.h> | ||
13 | #include <linux/rtnetlink.h> | ||
14 | #include "net_driver.h" | ||
15 | #include "efx.h" | ||
16 | #include "ethtool.h" | ||
17 | #include "falcon.h" | ||
18 | #include "gmii.h" | ||
19 | #include "mac.h" | ||
20 | |||
21 | static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable); | ||
22 | |||
23 | struct ethtool_string { | ||
24 | char name[ETH_GSTRING_LEN]; | ||
25 | }; | ||
26 | |||
27 | struct efx_ethtool_stat { | ||
28 | const char *name; | ||
29 | enum { | ||
30 | EFX_ETHTOOL_STAT_SOURCE_mac_stats, | ||
31 | EFX_ETHTOOL_STAT_SOURCE_nic, | ||
32 | EFX_ETHTOOL_STAT_SOURCE_channel | ||
33 | } source; | ||
34 | unsigned offset; | ||
35 | u64(*get_stat) (void *field); /* Reader function */ | ||
36 | }; | ||
37 | |||
38 | /* Initialiser for a struct #efx_ethtool_stat with type-checking */ | ||
39 | #define EFX_ETHTOOL_STAT(stat_name, source_name, field, field_type, \ | ||
40 | get_stat_function) { \ | ||
41 | .name = #stat_name, \ | ||
42 | .source = EFX_ETHTOOL_STAT_SOURCE_##source_name, \ | ||
43 | .offset = ((((field_type *) 0) == \ | ||
44 | &((struct efx_##source_name *)0)->field) ? \ | ||
45 | offsetof(struct efx_##source_name, field) : \ | ||
46 | offsetof(struct efx_##source_name, field)), \ | ||
47 | .get_stat = get_stat_function, \ | ||
48 | } | ||
49 | |||
50 | static u64 efx_get_uint_stat(void *field) | ||
51 | { | ||
52 | return *(unsigned int *)field; | ||
53 | } | ||
54 | |||
55 | static u64 efx_get_ulong_stat(void *field) | ||
56 | { | ||
57 | return *(unsigned long *)field; | ||
58 | } | ||
59 | |||
60 | static u64 efx_get_u64_stat(void *field) | ||
61 | { | ||
62 | return *(u64 *) field; | ||
63 | } | ||
64 | |||
65 | static u64 efx_get_atomic_stat(void *field) | ||
66 | { | ||
67 | return atomic_read((atomic_t *) field); | ||
68 | } | ||
69 | |||
70 | #define EFX_ETHTOOL_ULONG_MAC_STAT(field) \ | ||
71 | EFX_ETHTOOL_STAT(field, mac_stats, field, \ | ||
72 | unsigned long, efx_get_ulong_stat) | ||
73 | |||
74 | #define EFX_ETHTOOL_U64_MAC_STAT(field) \ | ||
75 | EFX_ETHTOOL_STAT(field, mac_stats, field, \ | ||
76 | u64, efx_get_u64_stat) | ||
77 | |||
78 | #define EFX_ETHTOOL_UINT_NIC_STAT(name) \ | ||
79 | EFX_ETHTOOL_STAT(name, nic, n_##name, \ | ||
80 | unsigned int, efx_get_uint_stat) | ||
81 | |||
82 | #define EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field) \ | ||
83 | EFX_ETHTOOL_STAT(field, nic, field, \ | ||
84 | atomic_t, efx_get_atomic_stat) | ||
85 | |||
86 | #define EFX_ETHTOOL_UINT_CHANNEL_STAT(field) \ | ||
87 | EFX_ETHTOOL_STAT(field, channel, n_##field, \ | ||
88 | unsigned int, efx_get_uint_stat) | ||
89 | |||
90 | static struct efx_ethtool_stat efx_ethtool_stats[] = { | ||
91 | EFX_ETHTOOL_U64_MAC_STAT(tx_bytes), | ||
92 | EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes), | ||
93 | EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes), | ||
94 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_packets), | ||
95 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_bad), | ||
96 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_pause), | ||
97 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_control), | ||
98 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_unicast), | ||
99 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_multicast), | ||
100 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_broadcast), | ||
101 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_lt64), | ||
102 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_64), | ||
103 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_65_to_127), | ||
104 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_128_to_255), | ||
105 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_256_to_511), | ||
106 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_512_to_1023), | ||
107 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_1024_to_15xx), | ||
108 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_15xx_to_jumbo), | ||
109 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_gtjumbo), | ||
110 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_collision), | ||
111 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_single_collision), | ||
112 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_multiple_collision), | ||
113 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_collision), | ||
114 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_deferred), | ||
115 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_late_collision), | ||
116 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_deferred), | ||
117 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_non_tcpudp), | ||
118 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_mac_src_error), | ||
119 | EFX_ETHTOOL_ULONG_MAC_STAT(tx_ip_src_error), | ||
120 | EFX_ETHTOOL_U64_MAC_STAT(rx_bytes), | ||
121 | EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes), | ||
122 | EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes), | ||
123 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_packets), | ||
124 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_good), | ||
125 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad), | ||
126 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_pause), | ||
127 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_control), | ||
128 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_unicast), | ||
129 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_multicast), | ||
130 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_broadcast), | ||
131 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_lt64), | ||
132 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_64), | ||
133 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_65_to_127), | ||
134 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_128_to_255), | ||
135 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_256_to_511), | ||
136 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_512_to_1023), | ||
137 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_1024_to_15xx), | ||
138 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_15xx_to_jumbo), | ||
139 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_gtjumbo), | ||
140 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_lt64), | ||
141 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_64_to_15xx), | ||
142 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_15xx_to_jumbo), | ||
143 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_gtjumbo), | ||
144 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_overflow), | ||
145 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_missed), | ||
146 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_false_carrier), | ||
147 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_symbol_error), | ||
148 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_align_error), | ||
149 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_length_error), | ||
150 | EFX_ETHTOOL_ULONG_MAC_STAT(rx_internal_error), | ||
151 | EFX_ETHTOOL_UINT_NIC_STAT(rx_nodesc_drop_cnt), | ||
152 | EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset), | ||
153 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc), | ||
154 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err), | ||
155 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err), | ||
156 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc), | ||
157 | }; | ||
158 | |||
159 | /* Number of ethtool statistics */ | ||
160 | #define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats) | ||
161 | |||
162 | /************************************************************************** | ||
163 | * | ||
164 | * Ethtool operations | ||
165 | * | ||
166 | ************************************************************************** | ||
167 | */ | ||
168 | |||
169 | /* Identify device by flashing LEDs */ | ||
170 | static int efx_ethtool_phys_id(struct net_device *net_dev, u32 seconds) | ||
171 | { | ||
172 | struct efx_nic *efx = net_dev->priv; | ||
173 | |||
174 | efx->board_info.blink(efx, 1); | ||
175 | schedule_timeout_interruptible(seconds * HZ); | ||
176 | efx->board_info.blink(efx, 0); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | /* This must be called with rtnl_lock held. */ | ||
181 | int efx_ethtool_get_settings(struct net_device *net_dev, | ||
182 | struct ethtool_cmd *ecmd) | ||
183 | { | ||
184 | struct efx_nic *efx = net_dev->priv; | ||
185 | int rc; | ||
186 | |||
187 | mutex_lock(&efx->mac_lock); | ||
188 | rc = falcon_xmac_get_settings(efx, ecmd); | ||
189 | mutex_unlock(&efx->mac_lock); | ||
190 | |||
191 | return rc; | ||
192 | } | ||
193 | |||
194 | /* This must be called with rtnl_lock held. */ | ||
195 | int efx_ethtool_set_settings(struct net_device *net_dev, | ||
196 | struct ethtool_cmd *ecmd) | ||
197 | { | ||
198 | struct efx_nic *efx = net_dev->priv; | ||
199 | int rc; | ||
200 | |||
201 | mutex_lock(&efx->mac_lock); | ||
202 | rc = falcon_xmac_set_settings(efx, ecmd); | ||
203 | mutex_unlock(&efx->mac_lock); | ||
204 | if (!rc) | ||
205 | efx_reconfigure_port(efx); | ||
206 | |||
207 | return rc; | ||
208 | } | ||
209 | |||
210 | static void efx_ethtool_get_drvinfo(struct net_device *net_dev, | ||
211 | struct ethtool_drvinfo *info) | ||
212 | { | ||
213 | struct efx_nic *efx = net_dev->priv; | ||
214 | |||
215 | strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver)); | ||
216 | strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version)); | ||
217 | strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info)); | ||
218 | } | ||
219 | |||
220 | static int efx_ethtool_get_stats_count(struct net_device *net_dev) | ||
221 | { | ||
222 | return EFX_ETHTOOL_NUM_STATS; | ||
223 | } | ||
224 | |||
225 | static void efx_ethtool_get_strings(struct net_device *net_dev, | ||
226 | u32 string_set, u8 *strings) | ||
227 | { | ||
228 | struct ethtool_string *ethtool_strings = | ||
229 | (struct ethtool_string *)strings; | ||
230 | int i; | ||
231 | |||
232 | if (string_set == ETH_SS_STATS) | ||
233 | for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) | ||
234 | strncpy(ethtool_strings[i].name, | ||
235 | efx_ethtool_stats[i].name, | ||
236 | sizeof(ethtool_strings[i].name)); | ||
237 | } | ||
238 | |||
239 | static void efx_ethtool_get_stats(struct net_device *net_dev, | ||
240 | struct ethtool_stats *stats, | ||
241 | u64 *data) | ||
242 | { | ||
243 | struct efx_nic *efx = net_dev->priv; | ||
244 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | ||
245 | struct efx_ethtool_stat *stat; | ||
246 | struct efx_channel *channel; | ||
247 | int i; | ||
248 | |||
249 | EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS); | ||
250 | |||
251 | /* Update MAC and NIC statistics */ | ||
252 | net_dev->get_stats(net_dev); | ||
253 | |||
254 | /* Fill detailed statistics buffer */ | ||
255 | for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) { | ||
256 | stat = &efx_ethtool_stats[i]; | ||
257 | switch (stat->source) { | ||
258 | case EFX_ETHTOOL_STAT_SOURCE_mac_stats: | ||
259 | data[i] = stat->get_stat((void *)mac_stats + | ||
260 | stat->offset); | ||
261 | break; | ||
262 | case EFX_ETHTOOL_STAT_SOURCE_nic: | ||
263 | data[i] = stat->get_stat((void *)efx + stat->offset); | ||
264 | break; | ||
265 | case EFX_ETHTOOL_STAT_SOURCE_channel: | ||
266 | data[i] = 0; | ||
267 | efx_for_each_channel(channel, efx) | ||
268 | data[i] += stat->get_stat((void *)channel + | ||
269 | stat->offset); | ||
270 | break; | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable) | ||
276 | { | ||
277 | struct efx_nic *efx = net_dev->priv; | ||
278 | int rc; | ||
279 | |||
280 | rc = ethtool_op_set_tx_csum(net_dev, enable); | ||
281 | if (rc) | ||
282 | return rc; | ||
283 | |||
284 | efx_flush_queues(efx); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable) | ||
290 | { | ||
291 | struct efx_nic *efx = net_dev->priv; | ||
292 | |||
293 | /* No way to stop the hardware doing the checks; we just | ||
294 | * ignore the result. | ||
295 | */ | ||
296 | efx->rx_checksum_enabled = (enable ? 1 : 0); | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev) | ||
302 | { | ||
303 | struct efx_nic *efx = net_dev->priv; | ||
304 | |||
305 | return efx->rx_checksum_enabled; | ||
306 | } | ||
307 | |||
308 | /* Restart autonegotiation */ | ||
309 | static int efx_ethtool_nway_reset(struct net_device *net_dev) | ||
310 | { | ||
311 | struct efx_nic *efx = net_dev->priv; | ||
312 | |||
313 | return mii_nway_restart(&efx->mii); | ||
314 | } | ||
315 | |||
316 | static u32 efx_ethtool_get_link(struct net_device *net_dev) | ||
317 | { | ||
318 | struct efx_nic *efx = net_dev->priv; | ||
319 | |||
320 | return efx->link_up; | ||
321 | } | ||
322 | |||
323 | static int efx_ethtool_get_coalesce(struct net_device *net_dev, | ||
324 | struct ethtool_coalesce *coalesce) | ||
325 | { | ||
326 | struct efx_nic *efx = net_dev->priv; | ||
327 | struct efx_tx_queue *tx_queue; | ||
328 | struct efx_rx_queue *rx_queue; | ||
329 | struct efx_channel *channel; | ||
330 | |||
331 | memset(coalesce, 0, sizeof(*coalesce)); | ||
332 | |||
333 | /* Find lowest IRQ moderation across all used TX queues */ | ||
334 | coalesce->tx_coalesce_usecs_irq = ~((u32) 0); | ||
335 | efx_for_each_tx_queue(tx_queue, efx) { | ||
336 | channel = tx_queue->channel; | ||
337 | if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) { | ||
338 | if (channel->used_flags != EFX_USED_BY_RX_TX) | ||
339 | coalesce->tx_coalesce_usecs_irq = | ||
340 | channel->irq_moderation; | ||
341 | else | ||
342 | coalesce->tx_coalesce_usecs_irq = 0; | ||
343 | } | ||
344 | } | ||
345 | |||
346 | /* Find lowest IRQ moderation across all used RX queues */ | ||
347 | coalesce->rx_coalesce_usecs_irq = ~((u32) 0); | ||
348 | efx_for_each_rx_queue(rx_queue, efx) { | ||
349 | channel = rx_queue->channel; | ||
350 | if (channel->irq_moderation < coalesce->rx_coalesce_usecs_irq) | ||
351 | coalesce->rx_coalesce_usecs_irq = | ||
352 | channel->irq_moderation; | ||
353 | } | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | /* Set coalescing parameters | ||
359 | * The difficulties occur for shared channels | ||
360 | */ | ||
361 | static int efx_ethtool_set_coalesce(struct net_device *net_dev, | ||
362 | struct ethtool_coalesce *coalesce) | ||
363 | { | ||
364 | struct efx_nic *efx = net_dev->priv; | ||
365 | struct efx_channel *channel; | ||
366 | struct efx_tx_queue *tx_queue; | ||
367 | unsigned tx_usecs, rx_usecs; | ||
368 | |||
369 | if (coalesce->use_adaptive_rx_coalesce || | ||
370 | coalesce->use_adaptive_tx_coalesce) | ||
371 | return -EOPNOTSUPP; | ||
372 | |||
373 | if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) { | ||
374 | EFX_ERR(efx, "invalid coalescing setting. " | ||
375 | "Only rx/tx_coalesce_usecs_irq are supported\n"); | ||
376 | return -EOPNOTSUPP; | ||
377 | } | ||
378 | |||
379 | rx_usecs = coalesce->rx_coalesce_usecs_irq; | ||
380 | tx_usecs = coalesce->tx_coalesce_usecs_irq; | ||
381 | |||
382 | /* If the channel is shared only allow RX parameters to be set */ | ||
383 | efx_for_each_tx_queue(tx_queue, efx) { | ||
384 | if ((tx_queue->channel->used_flags == EFX_USED_BY_RX_TX) && | ||
385 | tx_usecs) { | ||
386 | EFX_ERR(efx, "Channel is shared. " | ||
387 | "Only RX coalescing may be set\n"); | ||
388 | return -EOPNOTSUPP; | ||
389 | } | ||
390 | } | ||
391 | |||
392 | efx_init_irq_moderation(efx, tx_usecs, rx_usecs); | ||
393 | |||
394 | /* Reset channel to pick up new moderation value. Note that | ||
395 | * this may change the value of the irq_moderation field | ||
396 | * (e.g. to allow for hardware timer granularity). | ||
397 | */ | ||
398 | efx_for_each_channel(channel, efx) | ||
399 | falcon_set_int_moderation(channel); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | ||
405 | struct ethtool_pauseparam *pause) | ||
406 | { | ||
407 | struct efx_nic *efx = net_dev->priv; | ||
408 | enum efx_fc_type flow_control = efx->flow_control; | ||
409 | int rc; | ||
410 | |||
411 | flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO); | ||
412 | flow_control |= pause->rx_pause ? EFX_FC_RX : 0; | ||
413 | flow_control |= pause->tx_pause ? EFX_FC_TX : 0; | ||
414 | flow_control |= pause->autoneg ? EFX_FC_AUTO : 0; | ||
415 | |||
416 | /* Try to push the pause parameters */ | ||
417 | mutex_lock(&efx->mac_lock); | ||
418 | rc = falcon_xmac_set_pause(efx, flow_control); | ||
419 | mutex_unlock(&efx->mac_lock); | ||
420 | |||
421 | if (!rc) | ||
422 | efx_reconfigure_port(efx); | ||
423 | |||
424 | return rc; | ||
425 | } | ||
426 | |||
427 | static void efx_ethtool_get_pauseparam(struct net_device *net_dev, | ||
428 | struct ethtool_pauseparam *pause) | ||
429 | { | ||
430 | struct efx_nic *efx = net_dev->priv; | ||
431 | |||
432 | pause->rx_pause = (efx->flow_control & EFX_FC_RX) ? 1 : 0; | ||
433 | pause->tx_pause = (efx->flow_control & EFX_FC_TX) ? 1 : 0; | ||
434 | pause->autoneg = (efx->flow_control & EFX_FC_AUTO) ? 1 : 0; | ||
435 | } | ||
436 | |||
437 | |||
438 | struct ethtool_ops efx_ethtool_ops = { | ||
439 | .get_settings = efx_ethtool_get_settings, | ||
440 | .set_settings = efx_ethtool_set_settings, | ||
441 | .get_drvinfo = efx_ethtool_get_drvinfo, | ||
442 | .nway_reset = efx_ethtool_nway_reset, | ||
443 | .get_link = efx_ethtool_get_link, | ||
444 | .get_coalesce = efx_ethtool_get_coalesce, | ||
445 | .set_coalesce = efx_ethtool_set_coalesce, | ||
446 | .get_pauseparam = efx_ethtool_get_pauseparam, | ||
447 | .set_pauseparam = efx_ethtool_set_pauseparam, | ||
448 | .get_rx_csum = efx_ethtool_get_rx_csum, | ||
449 | .set_rx_csum = efx_ethtool_set_rx_csum, | ||
450 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
451 | .set_tx_csum = efx_ethtool_set_tx_csum, | ||
452 | .get_sg = ethtool_op_get_sg, | ||
453 | .set_sg = ethtool_op_set_sg, | ||
454 | .get_flags = ethtool_op_get_flags, | ||
455 | .set_flags = ethtool_op_set_flags, | ||
456 | .get_strings = efx_ethtool_get_strings, | ||
457 | .phys_id = efx_ethtool_phys_id, | ||
458 | .get_stats_count = efx_ethtool_get_stats_count, | ||
459 | .get_ethtool_stats = efx_ethtool_get_stats, | ||
460 | }; | ||