]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/net/ethernet/cisco/enic/enic_ethtool.c
net: get rid of SET_ETHTOOL_OPS
[mirror_ubuntu-artful-kernel.git] / drivers / net / ethernet / cisco / enic / enic_ethtool.c
1 /**
2 * Copyright 2013 Cisco Systems, Inc. All rights reserved.
3 *
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.
7 *
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
15 * SOFTWARE.
16 *
17 */
18
19 #include <linux/netdevice.h>
20 #include <linux/ethtool.h>
21
22 #include "enic_res.h"
23 #include "enic.h"
24 #include "enic_dev.h"
25
26 struct enic_stat {
27 char name[ETH_GSTRING_LEN];
28 unsigned int index;
29 };
30
31 #define ENIC_TX_STAT(stat) { \
32 .name = #stat, \
33 .index = offsetof(struct vnic_tx_stats, stat) / sizeof(u64) \
34 }
35
36 #define ENIC_RX_STAT(stat) { \
37 .name = #stat, \
38 .index = offsetof(struct vnic_rx_stats, stat) / sizeof(u64) \
39 }
40
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),
52 ENIC_TX_STAT(tx_tso),
53 };
54
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),
68 ENIC_RX_STAT(rx_rss),
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),
77 };
78
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);
81
82 static int enic_get_settings(struct net_device *netdev,
83 struct ethtool_cmd *ecmd)
84 {
85 struct enic *enic = netdev_priv(netdev);
86
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;
91
92 if (netif_carrier_ok(netdev)) {
93 ethtool_cmd_speed_set(ecmd, vnic_dev_port_speed(enic->vdev));
94 ecmd->duplex = DUPLEX_FULL;
95 } else {
96 ethtool_cmd_speed_set(ecmd, -1);
97 ecmd->duplex = -1;
98 }
99
100 ecmd->autoneg = AUTONEG_DISABLE;
101
102 return 0;
103 }
104
105 static void enic_get_drvinfo(struct net_device *netdev,
106 struct ethtool_drvinfo *drvinfo)
107 {
108 struct enic *enic = netdev_priv(netdev);
109 struct vnic_devcmd_fw_info *fw_info;
110
111 enic_dev_fw_info(enic, &fw_info);
112
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));
119 }
120
121 static void enic_get_strings(struct net_device *netdev, u32 stringset,
122 u8 *data)
123 {
124 unsigned int i;
125
126 switch (stringset) {
127 case ETH_SS_STATS:
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;
131 }
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;
135 }
136 break;
137 }
138 }
139
140 static int enic_get_sset_count(struct net_device *netdev, int sset)
141 {
142 switch (sset) {
143 case ETH_SS_STATS:
144 return enic_n_tx_stats + enic_n_rx_stats;
145 default:
146 return -EOPNOTSUPP;
147 }
148 }
149
150 static void enic_get_ethtool_stats(struct net_device *netdev,
151 struct ethtool_stats *stats, u64 *data)
152 {
153 struct enic *enic = netdev_priv(netdev);
154 struct vnic_stats *vstats;
155 unsigned int i;
156
157 enic_dev_stats_dump(enic, &vstats);
158
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];
163 }
164
165 static u32 enic_get_msglevel(struct net_device *netdev)
166 {
167 struct enic *enic = netdev_priv(netdev);
168 return enic->msg_enable;
169 }
170
171 static void enic_set_msglevel(struct net_device *netdev, u32 value)
172 {
173 struct enic *enic = netdev_priv(netdev);
174 enic->msg_enable = value;
175 }
176
177 static int enic_get_coalesce(struct net_device *netdev,
178 struct ethtool_coalesce *ecmd)
179 {
180 struct enic *enic = netdev_priv(netdev);
181
182 ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs;
183 ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs;
184
185 return 0;
186 }
187
188 static int enic_set_coalesce(struct net_device *netdev,
189 struct ethtool_coalesce *ecmd)
190 {
191 struct enic *enic = netdev_priv(netdev);
192 u32 tx_coalesce_usecs;
193 u32 rx_coalesce_usecs;
194 unsigned int i, intr;
195
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));
200
201 switch (vnic_dev_get_intr_mode(enic->vdev)) {
202 case VNIC_DEV_INTR_MODE_INTX:
203 if (tx_coalesce_usecs != rx_coalesce_usecs)
204 return -EINVAL;
205
206 intr = enic_legacy_io_intr();
207 vnic_intr_coalescing_timer_set(&enic->intr[intr],
208 tx_coalesce_usecs);
209 break;
210 case VNIC_DEV_INTR_MODE_MSI:
211 if (tx_coalesce_usecs != rx_coalesce_usecs)
212 return -EINVAL;
213
214 vnic_intr_coalescing_timer_set(&enic->intr[0],
215 tx_coalesce_usecs);
216 break;
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],
221 tx_coalesce_usecs);
222 }
223
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],
227 rx_coalesce_usecs);
228 }
229
230 break;
231 default:
232 break;
233 }
234
235 enic->tx_coalesce_usecs = tx_coalesce_usecs;
236 enic->rx_coalesce_usecs = rx_coalesce_usecs;
237
238 return 0;
239 }
240
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,
252 };
253
254 void enic_set_ethtool_ops(struct net_device *netdev)
255 {
256 netdev->ethtool_ops = &enic_ethtool_ops;
257 }