2 * Copyright 2013 Cisco Systems, Inc. All rights reserved.
4 * This program is free software; you may redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 #include <linux/netdevice.h>
20 #include <linux/ethtool.h>
27 char name
[ETH_GSTRING_LEN
];
31 #define ENIC_TX_STAT(stat) { \
33 .index = offsetof(struct vnic_tx_stats, stat) / sizeof(u64) \
36 #define ENIC_RX_STAT(stat) { \
38 .index = offsetof(struct vnic_rx_stats, stat) / sizeof(u64) \
41 static const struct enic_stat enic_tx_stats
[] = {
42 ENIC_TX_STAT(tx_frames_ok
),
43 ENIC_TX_STAT(tx_unicast_frames_ok
),
44 ENIC_TX_STAT(tx_multicast_frames_ok
),
45 ENIC_TX_STAT(tx_broadcast_frames_ok
),
46 ENIC_TX_STAT(tx_bytes_ok
),
47 ENIC_TX_STAT(tx_unicast_bytes_ok
),
48 ENIC_TX_STAT(tx_multicast_bytes_ok
),
49 ENIC_TX_STAT(tx_broadcast_bytes_ok
),
50 ENIC_TX_STAT(tx_drops
),
51 ENIC_TX_STAT(tx_errors
),
55 static const struct enic_stat enic_rx_stats
[] = {
56 ENIC_RX_STAT(rx_frames_ok
),
57 ENIC_RX_STAT(rx_frames_total
),
58 ENIC_RX_STAT(rx_unicast_frames_ok
),
59 ENIC_RX_STAT(rx_multicast_frames_ok
),
60 ENIC_RX_STAT(rx_broadcast_frames_ok
),
61 ENIC_RX_STAT(rx_bytes_ok
),
62 ENIC_RX_STAT(rx_unicast_bytes_ok
),
63 ENIC_RX_STAT(rx_multicast_bytes_ok
),
64 ENIC_RX_STAT(rx_broadcast_bytes_ok
),
65 ENIC_RX_STAT(rx_drop
),
66 ENIC_RX_STAT(rx_no_bufs
),
67 ENIC_RX_STAT(rx_errors
),
69 ENIC_RX_STAT(rx_crc_errors
),
70 ENIC_RX_STAT(rx_frames_64
),
71 ENIC_RX_STAT(rx_frames_127
),
72 ENIC_RX_STAT(rx_frames_255
),
73 ENIC_RX_STAT(rx_frames_511
),
74 ENIC_RX_STAT(rx_frames_1023
),
75 ENIC_RX_STAT(rx_frames_1518
),
76 ENIC_RX_STAT(rx_frames_to_max
),
79 static const unsigned int enic_n_tx_stats
= ARRAY_SIZE(enic_tx_stats
);
80 static const unsigned int enic_n_rx_stats
= ARRAY_SIZE(enic_rx_stats
);
82 static int enic_get_settings(struct net_device
*netdev
,
83 struct ethtool_cmd
*ecmd
)
85 struct enic
*enic
= netdev_priv(netdev
);
87 ecmd
->supported
= (SUPPORTED_10000baseT_Full
| SUPPORTED_FIBRE
);
88 ecmd
->advertising
= (ADVERTISED_10000baseT_Full
| ADVERTISED_FIBRE
);
89 ecmd
->port
= PORT_FIBRE
;
90 ecmd
->transceiver
= XCVR_EXTERNAL
;
92 if (netif_carrier_ok(netdev
)) {
93 ethtool_cmd_speed_set(ecmd
, vnic_dev_port_speed(enic
->vdev
));
94 ecmd
->duplex
= DUPLEX_FULL
;
96 ethtool_cmd_speed_set(ecmd
, -1);
100 ecmd
->autoneg
= AUTONEG_DISABLE
;
105 static void enic_get_drvinfo(struct net_device
*netdev
,
106 struct ethtool_drvinfo
*drvinfo
)
108 struct enic
*enic
= netdev_priv(netdev
);
109 struct vnic_devcmd_fw_info
*fw_info
;
111 enic_dev_fw_info(enic
, &fw_info
);
113 strlcpy(drvinfo
->driver
, DRV_NAME
, sizeof(drvinfo
->driver
));
114 strlcpy(drvinfo
->version
, DRV_VERSION
, sizeof(drvinfo
->version
));
115 strlcpy(drvinfo
->fw_version
, fw_info
->fw_version
,
116 sizeof(drvinfo
->fw_version
));
117 strlcpy(drvinfo
->bus_info
, pci_name(enic
->pdev
),
118 sizeof(drvinfo
->bus_info
));
121 static void enic_get_strings(struct net_device
*netdev
, u32 stringset
,
128 for (i
= 0; i
< enic_n_tx_stats
; i
++) {
129 memcpy(data
, enic_tx_stats
[i
].name
, ETH_GSTRING_LEN
);
130 data
+= ETH_GSTRING_LEN
;
132 for (i
= 0; i
< enic_n_rx_stats
; i
++) {
133 memcpy(data
, enic_rx_stats
[i
].name
, ETH_GSTRING_LEN
);
134 data
+= ETH_GSTRING_LEN
;
140 static int enic_get_sset_count(struct net_device
*netdev
, int sset
)
144 return enic_n_tx_stats
+ enic_n_rx_stats
;
150 static void enic_get_ethtool_stats(struct net_device
*netdev
,
151 struct ethtool_stats
*stats
, u64
*data
)
153 struct enic
*enic
= netdev_priv(netdev
);
154 struct vnic_stats
*vstats
;
157 enic_dev_stats_dump(enic
, &vstats
);
159 for (i
= 0; i
< enic_n_tx_stats
; i
++)
160 *(data
++) = ((u64
*)&vstats
->tx
)[enic_tx_stats
[i
].index
];
161 for (i
= 0; i
< enic_n_rx_stats
; i
++)
162 *(data
++) = ((u64
*)&vstats
->rx
)[enic_rx_stats
[i
].index
];
165 static u32
enic_get_msglevel(struct net_device
*netdev
)
167 struct enic
*enic
= netdev_priv(netdev
);
168 return enic
->msg_enable
;
171 static void enic_set_msglevel(struct net_device
*netdev
, u32 value
)
173 struct enic
*enic
= netdev_priv(netdev
);
174 enic
->msg_enable
= value
;
177 static int enic_get_coalesce(struct net_device
*netdev
,
178 struct ethtool_coalesce
*ecmd
)
180 struct enic
*enic
= netdev_priv(netdev
);
182 ecmd
->tx_coalesce_usecs
= enic
->tx_coalesce_usecs
;
183 ecmd
->rx_coalesce_usecs
= enic
->rx_coalesce_usecs
;
188 static int enic_set_coalesce(struct net_device
*netdev
,
189 struct ethtool_coalesce
*ecmd
)
191 struct enic
*enic
= netdev_priv(netdev
);
192 u32 tx_coalesce_usecs
;
193 u32 rx_coalesce_usecs
;
194 unsigned int i
, intr
;
196 tx_coalesce_usecs
= min_t(u32
, ecmd
->tx_coalesce_usecs
,
197 vnic_dev_get_intr_coal_timer_max(enic
->vdev
));
198 rx_coalesce_usecs
= min_t(u32
, ecmd
->rx_coalesce_usecs
,
199 vnic_dev_get_intr_coal_timer_max(enic
->vdev
));
201 switch (vnic_dev_get_intr_mode(enic
->vdev
)) {
202 case VNIC_DEV_INTR_MODE_INTX
:
203 if (tx_coalesce_usecs
!= rx_coalesce_usecs
)
206 intr
= enic_legacy_io_intr();
207 vnic_intr_coalescing_timer_set(&enic
->intr
[intr
],
210 case VNIC_DEV_INTR_MODE_MSI
:
211 if (tx_coalesce_usecs
!= rx_coalesce_usecs
)
214 vnic_intr_coalescing_timer_set(&enic
->intr
[0],
217 case VNIC_DEV_INTR_MODE_MSIX
:
218 for (i
= 0; i
< enic
->wq_count
; i
++) {
219 intr
= enic_msix_wq_intr(enic
, i
);
220 vnic_intr_coalescing_timer_set(&enic
->intr
[intr
],
224 for (i
= 0; i
< enic
->rq_count
; i
++) {
225 intr
= enic_msix_rq_intr(enic
, i
);
226 vnic_intr_coalescing_timer_set(&enic
->intr
[intr
],
235 enic
->tx_coalesce_usecs
= tx_coalesce_usecs
;
236 enic
->rx_coalesce_usecs
= rx_coalesce_usecs
;
241 static const struct ethtool_ops enic_ethtool_ops
= {
242 .get_settings
= enic_get_settings
,
243 .get_drvinfo
= enic_get_drvinfo
,
244 .get_msglevel
= enic_get_msglevel
,
245 .set_msglevel
= enic_set_msglevel
,
246 .get_link
= ethtool_op_get_link
,
247 .get_strings
= enic_get_strings
,
248 .get_sset_count
= enic_get_sset_count
,
249 .get_ethtool_stats
= enic_get_ethtool_stats
,
250 .get_coalesce
= enic_get_coalesce
,
251 .set_coalesce
= enic_set_coalesce
,
254 void enic_set_ethtool_ops(struct net_device
*netdev
)
256 SET_ETHTOOL_OPS(netdev
, &enic_ethtool_ops
);