2 * Copyright (C) 2005 - 2008 ServerEngines
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation. The full GNU General
8 * Public License is included in this distribution in the file called COPYING.
10 * Contact Information:
11 * linux-drivers@serverengines.com
14 * 209 N. Fair Oaks Ave
20 * This file contains various functions that ethtool can use
21 * to talk to the driver and the BE H/W.
26 #include <linux/ethtool.h>
28 static const char benet_gstrings_stats
[][ETH_GSTRING_LEN
] = {
29 /* net_device_stats */
49 "tx_heartbeat_errors",
64 "bes_ethrx_post_fail",
65 "bes_802_3_dropped_frames",
66 "bes_802_3_malformed_frames",
70 "Num Packets collected",
74 #define NET_DEV_STATS_LEN \
75 (sizeof(struct net_device_stats)/sizeof(unsigned long))
77 #define BENET_STATS_LEN ARRAY_SIZE(benet_gstrings_stats)
80 be_get_drvinfo(struct net_device
*netdev
, struct ethtool_drvinfo
*drvinfo
)
82 struct be_net_object
*pnob
= netdev_priv(netdev
);
83 struct be_adapter
*adapter
= pnob
->adapter
;
85 strncpy(drvinfo
->driver
, be_driver_name
, 32);
86 strncpy(drvinfo
->version
, be_drvr_ver
, 32);
87 strncpy(drvinfo
->fw_version
, be_fw_ver
, 32);
88 strcpy(drvinfo
->bus_info
, pci_name(adapter
->pdev
));
89 drvinfo
->testinfo_len
= 0;
90 drvinfo
->regdump_len
= 0;
91 drvinfo
->eedump_len
= 0;
95 be_get_coalesce(struct net_device
*netdev
, struct ethtool_coalesce
*coalesce
)
97 struct be_net_object
*pnob
= netdev_priv(netdev
);
98 struct be_adapter
*adapter
= pnob
->adapter
;
100 coalesce
->rx_max_coalesced_frames
= adapter
->max_rx_coal
;
102 coalesce
->rx_coalesce_usecs
= adapter
->cur_eqd
;
103 coalesce
->rx_coalesce_usecs_high
= adapter
->max_eqd
;
104 coalesce
->rx_coalesce_usecs_low
= adapter
->min_eqd
;
106 coalesce
->tx_coalesce_usecs
= adapter
->cur_eqd
;
107 coalesce
->tx_coalesce_usecs_high
= adapter
->max_eqd
;
108 coalesce
->tx_coalesce_usecs_low
= adapter
->min_eqd
;
110 coalesce
->use_adaptive_rx_coalesce
= adapter
->enable_aic
;
111 coalesce
->use_adaptive_tx_coalesce
= adapter
->enable_aic
;
117 * This routine is used to set interrup coalescing delay *as well as*
118 * the number of pkts to coalesce for LRO.
121 be_set_coalesce(struct net_device
*netdev
, struct ethtool_coalesce
*coalesce
)
123 struct be_net_object
*pnob
= netdev_priv(netdev
);
124 struct be_adapter
*adapter
= pnob
->adapter
;
125 struct be_eq_object
*eq_objectp
;
129 adapter
->max_rx_coal
= coalesce
->rx_max_coalesced_frames
;
130 if (adapter
->max_rx_coal
>= BE_LRO_MAX_PKTS
)
131 adapter
->max_rx_coal
= BE_LRO_MAX_PKTS
;
133 if (adapter
->enable_aic
== 0 &&
134 coalesce
->use_adaptive_rx_coalesce
== 1) {
135 /* if AIC is being turned on now, start with an EQD of 0 */
136 adapter
->cur_eqd
= 0;
138 adapter
->enable_aic
= coalesce
->use_adaptive_rx_coalesce
;
140 /* round off to nearest multiple of 8 */
141 max
= (((coalesce
->rx_coalesce_usecs_high
+ 4) >> 3) << 3);
142 min
= (((coalesce
->rx_coalesce_usecs_low
+ 4) >> 3) << 3);
143 cur
= (((coalesce
->rx_coalesce_usecs
+ 4) >> 3) << 3);
145 if (adapter
->enable_aic
) {
146 /* accept low and high if AIC is enabled */
151 adapter
->max_eqd
= max
;
152 adapter
->min_eqd
= min
;
153 if (adapter
->cur_eqd
> max
)
154 adapter
->cur_eqd
= max
;
155 if (adapter
->cur_eqd
< min
)
156 adapter
->cur_eqd
= min
;
158 /* accept specified coalesce_usecs only if AIC is disabled */
161 eq_objectp
= &pnob
->event_q_obj
;
163 be_eq_modify_delay(&pnob
->fn_obj
, 1, &eq_objectp
, &cur
,
165 if (status
== BE_SUCCESS
)
166 adapter
->cur_eqd
= cur
;
171 static u32
be_get_rx_csum(struct net_device
*netdev
)
173 struct be_net_object
*pnob
= netdev_priv(netdev
);
174 struct be_adapter
*adapter
= pnob
->adapter
;
175 return adapter
->rx_csum
;
178 static int be_set_rx_csum(struct net_device
*netdev
, uint32_t data
)
180 struct be_net_object
*pnob
= netdev_priv(netdev
);
181 struct be_adapter
*adapter
= pnob
->adapter
;
184 adapter
->rx_csum
= 1;
186 adapter
->rx_csum
= 0;
192 be_get_strings(struct net_device
*netdev
, uint32_t stringset
, uint8_t *data
)
196 memcpy(data
, *benet_gstrings_stats
,
197 sizeof(benet_gstrings_stats
));
202 static int be_get_stats_count(struct net_device
*netdev
)
204 return BENET_STATS_LEN
;
208 be_get_ethtool_stats(struct net_device
*netdev
,
209 struct ethtool_stats
*stats
, uint64_t *data
)
211 struct be_net_object
*pnob
= netdev_priv(netdev
);
212 struct be_adapter
*adapter
= pnob
->adapter
;
215 benet_get_stats(netdev
);
217 for (i
= 0; i
<= NET_DEV_STATS_LEN
; i
++)
218 data
[i
] = ((unsigned long *)&adapter
->benet_stats
)[i
];
220 data
[i
] = adapter
->be_stat
.bes_tx_reqs
;
221 data
[i
++] = adapter
->be_stat
.bes_tx_fails
;
222 data
[i
++] = adapter
->be_stat
.bes_fwd_reqs
;
223 data
[i
++] = adapter
->be_stat
.bes_tx_wrbs
;
225 data
[i
++] = adapter
->be_stat
.bes_ints
;
226 data
[i
++] = adapter
->be_stat
.bes_events
;
227 data
[i
++] = adapter
->be_stat
.bes_tx_events
;
228 data
[i
++] = adapter
->be_stat
.bes_rx_events
;
229 data
[i
++] = adapter
->be_stat
.bes_tx_compl
;
230 data
[i
++] = adapter
->be_stat
.bes_rx_compl
;
231 data
[i
++] = adapter
->be_stat
.bes_ethrx_post_fail
;
232 data
[i
++] = adapter
->be_stat
.bes_802_3_dropped_frames
;
233 data
[i
++] = adapter
->be_stat
.bes_802_3_malformed_frames
;
234 data
[i
++] = adapter
->be_stat
.bes_rx_misc_pkts
;
235 data
[i
++] = adapter
->be_stat
.bes_eth_tx_rate
;
236 data
[i
++] = adapter
->be_stat
.bes_eth_rx_rate
;
237 data
[i
++] = adapter
->be_stat
.bes_rx_coal
;
238 data
[i
++] = adapter
->be_stat
.bes_rx_flush
;
242 static int be_get_settings(struct net_device
*netdev
, struct ethtool_cmd
*ecmd
)
244 ecmd
->speed
= SPEED_10000
;
245 ecmd
->duplex
= DUPLEX_FULL
;
246 ecmd
->autoneg
= AUTONEG_DISABLE
;
250 /* Get the Ring parameters from the pnob */
252 be_get_ringparam(struct net_device
*netdev
, struct ethtool_ringparam
*ring
)
254 struct be_net_object
*pnob
= netdev_priv(netdev
);
257 ring
->rx_max_pending
= pnob
->rx_q_len
;
258 ring
->rx_mini_max_pending
= ring
->rx_mini_max_pending
;
259 ring
->rx_jumbo_max_pending
= ring
->rx_jumbo_max_pending
;
260 ring
->tx_max_pending
= pnob
->tx_q_len
;
262 /* Current hardware Settings */
263 ring
->rx_pending
= atomic_read(&pnob
->rx_q_posted
);
264 ring
->rx_mini_pending
= ring
->rx_mini_pending
;
265 ring
->rx_jumbo_pending
= ring
->rx_jumbo_pending
;
266 ring
->tx_pending
= atomic_read(&pnob
->tx_q_used
);
271 be_get_pauseparam(struct net_device
*netdev
, struct ethtool_pauseparam
*ecmd
)
273 struct be_net_object
*pnob
= netdev_priv(netdev
);
277 status
= be_eth_get_flow_control(&pnob
->fn_obj
, &txfc
, &rxfc
);
278 if (status
!= BE_SUCCESS
) {
279 dev_info(&netdev
->dev
, "Unable to get pause frame settings\n");
280 /* return defaults */
283 ecmd
->autoneg
= AUTONEG_ENABLE
;
297 ecmd
->autoneg
= AUTONEG_ENABLE
;
301 be_set_pauseparam(struct net_device
*netdev
, struct ethtool_pauseparam
*ecmd
)
303 struct be_net_object
*pnob
= netdev_priv(netdev
);
307 if (ecmd
->autoneg
!= AUTONEG_ENABLE
)
320 status
= be_eth_set_flow_control(&pnob
->fn_obj
, txfc
, rxfc
);
321 if (status
!= BE_SUCCESS
) {
322 dev_info(&netdev
->dev
, "Unable to set pause frame settings\n");
328 struct ethtool_ops be_ethtool_ops
= {
329 .get_settings
= be_get_settings
,
330 .get_drvinfo
= be_get_drvinfo
,
331 .get_link
= ethtool_op_get_link
,
332 .get_coalesce
= be_get_coalesce
,
333 .set_coalesce
= be_set_coalesce
,
334 .get_ringparam
= be_get_ringparam
,
335 .get_pauseparam
= be_get_pauseparam
,
336 .set_pauseparam
= be_set_pauseparam
,
337 .get_rx_csum
= be_get_rx_csum
,
338 .set_rx_csum
= be_set_rx_csum
,
339 .get_tx_csum
= ethtool_op_get_tx_csum
,
340 .set_tx_csum
= ethtool_op_set_tx_csum
,
341 .get_sg
= ethtool_op_get_sg
,
342 .set_sg
= ethtool_op_set_sg
,
343 .get_tso
= ethtool_op_get_tso
,
344 .set_tso
= ethtool_op_set_tso
,
345 .get_strings
= be_get_strings
,
346 .get_stats_count
= be_get_stats_count
,
347 .get_ethtool_stats
= be_get_ethtool_stats
,