diff options
author | Neel Patel <neepatel@cisco.com> | 2013-07-22 12:59:18 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-07-24 20:01:55 -0400 |
commit | f13bbc2f9aba00c7a37b499d23060616b9a4ef9e (patch) | |
tree | f4c4558aa86db49280116b4e376e8021f1a1535e /drivers/net/ethernet/cisco | |
parent | 59ea52dc461ebb05b78545064604d92faf8bb16f (diff) |
drivers/net: enic: Move ethtool code to a separate file
This patch moves all enic ethtool hooks from enic_main.c to a new file
enic_ethtool.c
Signed-off-by: Neel Patel <neepatel@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/cisco')
-rw-r--r-- | drivers/net/ethernet/cisco/enic/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic.h | 48 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_dev.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_ethtool.c | 257 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_main.c | 270 |
5 files changed, 309 insertions, 270 deletions
diff --git a/drivers/net/ethernet/cisco/enic/Makefile b/drivers/net/ethernet/cisco/enic/Makefile index 9d4974bba247..e52296d9b256 100644 --- a/drivers/net/ethernet/cisco/enic/Makefile +++ b/drivers/net/ethernet/cisco/enic/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-$(CONFIG_ENIC) := enic.o | 1 | obj-$(CONFIG_ENIC) := enic.o |
2 | 2 | ||
3 | enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \ | 3 | enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \ |
4 | enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o | 4 | enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o \ |
5 | enic_ethtool.o | ||
5 | 6 | ||
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index afe9b1662b8c..2e37c63981c1 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h | |||
@@ -127,9 +127,57 @@ static inline struct device *enic_get_dev(struct enic *enic) | |||
127 | return &(enic->pdev->dev); | 127 | return &(enic->pdev->dev); |
128 | } | 128 | } |
129 | 129 | ||
130 | static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq) | ||
131 | { | ||
132 | return rq; | ||
133 | } | ||
134 | |||
135 | static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq) | ||
136 | { | ||
137 | return enic->rq_count + wq; | ||
138 | } | ||
139 | |||
140 | static inline unsigned int enic_legacy_io_intr(void) | ||
141 | { | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static inline unsigned int enic_legacy_err_intr(void) | ||
146 | { | ||
147 | return 1; | ||
148 | } | ||
149 | |||
150 | static inline unsigned int enic_legacy_notify_intr(void) | ||
151 | { | ||
152 | return 2; | ||
153 | } | ||
154 | |||
155 | static inline unsigned int enic_msix_rq_intr(struct enic *enic, | ||
156 | unsigned int rq) | ||
157 | { | ||
158 | return enic->cq[enic_cq_rq(enic, rq)].interrupt_offset; | ||
159 | } | ||
160 | |||
161 | static inline unsigned int enic_msix_wq_intr(struct enic *enic, | ||
162 | unsigned int wq) | ||
163 | { | ||
164 | return enic->cq[enic_cq_wq(enic, wq)].interrupt_offset; | ||
165 | } | ||
166 | |||
167 | static inline unsigned int enic_msix_err_intr(struct enic *enic) | ||
168 | { | ||
169 | return enic->rq_count + enic->wq_count; | ||
170 | } | ||
171 | |||
172 | static inline unsigned int enic_msix_notify_intr(struct enic *enic) | ||
173 | { | ||
174 | return enic->rq_count + enic->wq_count + 1; | ||
175 | } | ||
176 | |||
130 | void enic_reset_addr_lists(struct enic *enic); | 177 | void enic_reset_addr_lists(struct enic *enic); |
131 | int enic_sriov_enabled(struct enic *enic); | 178 | int enic_sriov_enabled(struct enic *enic); |
132 | int enic_is_valid_vf(struct enic *enic, int vf); | 179 | int enic_is_valid_vf(struct enic *enic, int vf); |
133 | int enic_is_dynamic(struct enic *enic); | 180 | int enic_is_dynamic(struct enic *enic); |
181 | void enic_set_ethtool_ops(struct net_device *netdev); | ||
134 | 182 | ||
135 | #endif /* _ENIC_H_ */ | 183 | #endif /* _ENIC_H_ */ |
diff --git a/drivers/net/ethernet/cisco/enic/enic_dev.h b/drivers/net/ethernet/cisco/enic/enic_dev.h index 08bded051b93..129b14a4efb0 100644 --- a/drivers/net/ethernet/cisco/enic/enic_dev.h +++ b/drivers/net/ethernet/cisco/enic/enic_dev.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #define _ENIC_DEV_H_ | 20 | #define _ENIC_DEV_H_ |
21 | 21 | ||
22 | #include "vnic_dev.h" | 22 | #include "vnic_dev.h" |
23 | #include "vnic_vic.h" | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * Calls the devcmd function given by argument vnicdevcmdfn. | 26 | * Calls the devcmd function given by argument vnicdevcmdfn. |
diff --git a/drivers/net/ethernet/cisco/enic/enic_ethtool.c b/drivers/net/ethernet/cisco/enic/enic_ethtool.c new file mode 100644 index 000000000000..47e3562f4866 --- /dev/null +++ b/drivers/net/ethernet/cisco/enic/enic_ethtool.c | |||
@@ -0,0 +1,257 @@ | |||
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 | SET_ETHTOOL_OPS(netdev, &enic_ethtool_ops); | ||
257 | } | ||
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 992ec2ee64d9..b12b32bc53a6 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/if.h> | 31 | #include <linux/if.h> |
32 | #include <linux/if_ether.h> | 32 | #include <linux/if_ether.h> |
33 | #include <linux/if_vlan.h> | 33 | #include <linux/if_vlan.h> |
34 | #include <linux/ethtool.h> | ||
35 | #include <linux/in.h> | 34 | #include <linux/in.h> |
36 | #include <linux/ip.h> | 35 | #include <linux/ip.h> |
37 | #include <linux/ipv6.h> | 36 | #include <linux/ipv6.h> |
@@ -73,57 +72,6 @@ MODULE_LICENSE("GPL"); | |||
73 | MODULE_VERSION(DRV_VERSION); | 72 | MODULE_VERSION(DRV_VERSION); |
74 | MODULE_DEVICE_TABLE(pci, enic_id_table); | 73 | MODULE_DEVICE_TABLE(pci, enic_id_table); |
75 | 74 | ||
76 | struct enic_stat { | ||
77 | char name[ETH_GSTRING_LEN]; | ||
78 | unsigned int offset; | ||
79 | }; | ||
80 | |||
81 | #define ENIC_TX_STAT(stat) \ | ||
82 | { .name = #stat, .offset = offsetof(struct vnic_tx_stats, stat) / 8 } | ||
83 | #define ENIC_RX_STAT(stat) \ | ||
84 | { .name = #stat, .offset = offsetof(struct vnic_rx_stats, stat) / 8 } | ||
85 | |||
86 | static const struct enic_stat enic_tx_stats[] = { | ||
87 | ENIC_TX_STAT(tx_frames_ok), | ||
88 | ENIC_TX_STAT(tx_unicast_frames_ok), | ||
89 | ENIC_TX_STAT(tx_multicast_frames_ok), | ||
90 | ENIC_TX_STAT(tx_broadcast_frames_ok), | ||
91 | ENIC_TX_STAT(tx_bytes_ok), | ||
92 | ENIC_TX_STAT(tx_unicast_bytes_ok), | ||
93 | ENIC_TX_STAT(tx_multicast_bytes_ok), | ||
94 | ENIC_TX_STAT(tx_broadcast_bytes_ok), | ||
95 | ENIC_TX_STAT(tx_drops), | ||
96 | ENIC_TX_STAT(tx_errors), | ||
97 | ENIC_TX_STAT(tx_tso), | ||
98 | }; | ||
99 | |||
100 | static const struct enic_stat enic_rx_stats[] = { | ||
101 | ENIC_RX_STAT(rx_frames_ok), | ||
102 | ENIC_RX_STAT(rx_frames_total), | ||
103 | ENIC_RX_STAT(rx_unicast_frames_ok), | ||
104 | ENIC_RX_STAT(rx_multicast_frames_ok), | ||
105 | ENIC_RX_STAT(rx_broadcast_frames_ok), | ||
106 | ENIC_RX_STAT(rx_bytes_ok), | ||
107 | ENIC_RX_STAT(rx_unicast_bytes_ok), | ||
108 | ENIC_RX_STAT(rx_multicast_bytes_ok), | ||
109 | ENIC_RX_STAT(rx_broadcast_bytes_ok), | ||
110 | ENIC_RX_STAT(rx_drop), | ||
111 | ENIC_RX_STAT(rx_no_bufs), | ||
112 | ENIC_RX_STAT(rx_errors), | ||
113 | ENIC_RX_STAT(rx_rss), | ||
114 | ENIC_RX_STAT(rx_crc_errors), | ||
115 | ENIC_RX_STAT(rx_frames_64), | ||
116 | ENIC_RX_STAT(rx_frames_127), | ||
117 | ENIC_RX_STAT(rx_frames_255), | ||
118 | ENIC_RX_STAT(rx_frames_511), | ||
119 | ENIC_RX_STAT(rx_frames_1023), | ||
120 | ENIC_RX_STAT(rx_frames_1518), | ||
121 | ENIC_RX_STAT(rx_frames_to_max), | ||
122 | }; | ||
123 | |||
124 | static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats); | ||
125 | static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats); | ||
126 | |||
127 | int enic_is_dynamic(struct enic *enic) | 75 | int enic_is_dynamic(struct enic *enic) |
128 | { | 76 | { |
129 | return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN; | 77 | return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN; |
@@ -148,222 +96,6 @@ int enic_is_valid_vf(struct enic *enic, int vf) | |||
148 | #endif | 96 | #endif |
149 | } | 97 | } |
150 | 98 | ||
151 | static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq) | ||
152 | { | ||
153 | return rq; | ||
154 | } | ||
155 | |||
156 | static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq) | ||
157 | { | ||
158 | return enic->rq_count + wq; | ||
159 | } | ||
160 | |||
161 | static inline unsigned int enic_legacy_io_intr(void) | ||
162 | { | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static inline unsigned int enic_legacy_err_intr(void) | ||
167 | { | ||
168 | return 1; | ||
169 | } | ||
170 | |||
171 | static inline unsigned int enic_legacy_notify_intr(void) | ||
172 | { | ||
173 | return 2; | ||
174 | } | ||
175 | |||
176 | static inline unsigned int enic_msix_rq_intr(struct enic *enic, unsigned int rq) | ||
177 | { | ||
178 | return enic->cq[enic_cq_rq(enic, rq)].interrupt_offset; | ||
179 | } | ||
180 | |||
181 | static inline unsigned int enic_msix_wq_intr(struct enic *enic, unsigned int wq) | ||
182 | { | ||
183 | return enic->cq[enic_cq_wq(enic, wq)].interrupt_offset; | ||
184 | } | ||
185 | |||
186 | static inline unsigned int enic_msix_err_intr(struct enic *enic) | ||
187 | { | ||
188 | return enic->rq_count + enic->wq_count; | ||
189 | } | ||
190 | |||
191 | static inline unsigned int enic_msix_notify_intr(struct enic *enic) | ||
192 | { | ||
193 | return enic->rq_count + enic->wq_count + 1; | ||
194 | } | ||
195 | |||
196 | static int enic_get_settings(struct net_device *netdev, | ||
197 | struct ethtool_cmd *ecmd) | ||
198 | { | ||
199 | struct enic *enic = netdev_priv(netdev); | ||
200 | |||
201 | ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); | ||
202 | ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); | ||
203 | ecmd->port = PORT_FIBRE; | ||
204 | ecmd->transceiver = XCVR_EXTERNAL; | ||
205 | |||
206 | if (netif_carrier_ok(netdev)) { | ||
207 | ethtool_cmd_speed_set(ecmd, vnic_dev_port_speed(enic->vdev)); | ||
208 | ecmd->duplex = DUPLEX_FULL; | ||
209 | } else { | ||
210 | ethtool_cmd_speed_set(ecmd, -1); | ||
211 | ecmd->duplex = -1; | ||
212 | } | ||
213 | |||
214 | ecmd->autoneg = AUTONEG_DISABLE; | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static void enic_get_drvinfo(struct net_device *netdev, | ||
220 | struct ethtool_drvinfo *drvinfo) | ||
221 | { | ||
222 | struct enic *enic = netdev_priv(netdev); | ||
223 | struct vnic_devcmd_fw_info *fw_info; | ||
224 | |||
225 | enic_dev_fw_info(enic, &fw_info); | ||
226 | |||
227 | strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); | ||
228 | strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version)); | ||
229 | strlcpy(drvinfo->fw_version, fw_info->fw_version, | ||
230 | sizeof(drvinfo->fw_version)); | ||
231 | strlcpy(drvinfo->bus_info, pci_name(enic->pdev), | ||
232 | sizeof(drvinfo->bus_info)); | ||
233 | } | ||
234 | |||
235 | static void enic_get_strings(struct net_device *netdev, u32 stringset, u8 *data) | ||
236 | { | ||
237 | unsigned int i; | ||
238 | |||
239 | switch (stringset) { | ||
240 | case ETH_SS_STATS: | ||
241 | for (i = 0; i < enic_n_tx_stats; i++) { | ||
242 | memcpy(data, enic_tx_stats[i].name, ETH_GSTRING_LEN); | ||
243 | data += ETH_GSTRING_LEN; | ||
244 | } | ||
245 | for (i = 0; i < enic_n_rx_stats; i++) { | ||
246 | memcpy(data, enic_rx_stats[i].name, ETH_GSTRING_LEN); | ||
247 | data += ETH_GSTRING_LEN; | ||
248 | } | ||
249 | break; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | static int enic_get_sset_count(struct net_device *netdev, int sset) | ||
254 | { | ||
255 | switch (sset) { | ||
256 | case ETH_SS_STATS: | ||
257 | return enic_n_tx_stats + enic_n_rx_stats; | ||
258 | default: | ||
259 | return -EOPNOTSUPP; | ||
260 | } | ||
261 | } | ||
262 | |||
263 | static void enic_get_ethtool_stats(struct net_device *netdev, | ||
264 | struct ethtool_stats *stats, u64 *data) | ||
265 | { | ||
266 | struct enic *enic = netdev_priv(netdev); | ||
267 | struct vnic_stats *vstats; | ||
268 | unsigned int i; | ||
269 | |||
270 | enic_dev_stats_dump(enic, &vstats); | ||
271 | |||
272 | for (i = 0; i < enic_n_tx_stats; i++) | ||
273 | *(data++) = ((u64 *)&vstats->tx)[enic_tx_stats[i].offset]; | ||
274 | for (i = 0; i < enic_n_rx_stats; i++) | ||
275 | *(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].offset]; | ||
276 | } | ||
277 | |||
278 | static u32 enic_get_msglevel(struct net_device *netdev) | ||
279 | { | ||
280 | struct enic *enic = netdev_priv(netdev); | ||
281 | return enic->msg_enable; | ||
282 | } | ||
283 | |||
284 | static void enic_set_msglevel(struct net_device *netdev, u32 value) | ||
285 | { | ||
286 | struct enic *enic = netdev_priv(netdev); | ||
287 | enic->msg_enable = value; | ||
288 | } | ||
289 | |||
290 | static int enic_get_coalesce(struct net_device *netdev, | ||
291 | struct ethtool_coalesce *ecmd) | ||
292 | { | ||
293 | struct enic *enic = netdev_priv(netdev); | ||
294 | |||
295 | ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs; | ||
296 | ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs; | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int enic_set_coalesce(struct net_device *netdev, | ||
302 | struct ethtool_coalesce *ecmd) | ||
303 | { | ||
304 | struct enic *enic = netdev_priv(netdev); | ||
305 | u32 tx_coalesce_usecs; | ||
306 | u32 rx_coalesce_usecs; | ||
307 | unsigned int i, intr; | ||
308 | |||
309 | tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs, | ||
310 | vnic_dev_get_intr_coal_timer_max(enic->vdev)); | ||
311 | rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs, | ||
312 | vnic_dev_get_intr_coal_timer_max(enic->vdev)); | ||
313 | |||
314 | switch (vnic_dev_get_intr_mode(enic->vdev)) { | ||
315 | case VNIC_DEV_INTR_MODE_INTX: | ||
316 | if (tx_coalesce_usecs != rx_coalesce_usecs) | ||
317 | return -EINVAL; | ||
318 | |||
319 | intr = enic_legacy_io_intr(); | ||
320 | vnic_intr_coalescing_timer_set(&enic->intr[intr], | ||
321 | tx_coalesce_usecs); | ||
322 | break; | ||
323 | case VNIC_DEV_INTR_MODE_MSI: | ||
324 | if (tx_coalesce_usecs != rx_coalesce_usecs) | ||
325 | return -EINVAL; | ||
326 | |||
327 | vnic_intr_coalescing_timer_set(&enic->intr[0], | ||
328 | tx_coalesce_usecs); | ||
329 | break; | ||
330 | case VNIC_DEV_INTR_MODE_MSIX: | ||
331 | for (i = 0; i < enic->wq_count; i++) { | ||
332 | intr = enic_msix_wq_intr(enic, i); | ||
333 | vnic_intr_coalescing_timer_set(&enic->intr[intr], | ||
334 | tx_coalesce_usecs); | ||
335 | } | ||
336 | |||
337 | for (i = 0; i < enic->rq_count; i++) { | ||
338 | intr = enic_msix_rq_intr(enic, i); | ||
339 | vnic_intr_coalescing_timer_set(&enic->intr[intr], | ||
340 | rx_coalesce_usecs); | ||
341 | } | ||
342 | |||
343 | break; | ||
344 | default: | ||
345 | break; | ||
346 | } | ||
347 | |||
348 | enic->tx_coalesce_usecs = tx_coalesce_usecs; | ||
349 | enic->rx_coalesce_usecs = rx_coalesce_usecs; | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static const struct ethtool_ops enic_ethtool_ops = { | ||
355 | .get_settings = enic_get_settings, | ||
356 | .get_drvinfo = enic_get_drvinfo, | ||
357 | .get_msglevel = enic_get_msglevel, | ||
358 | .set_msglevel = enic_set_msglevel, | ||
359 | .get_link = ethtool_op_get_link, | ||
360 | .get_strings = enic_get_strings, | ||
361 | .get_sset_count = enic_get_sset_count, | ||
362 | .get_ethtool_stats = enic_get_ethtool_stats, | ||
363 | .get_coalesce = enic_get_coalesce, | ||
364 | .set_coalesce = enic_set_coalesce, | ||
365 | }; | ||
366 | |||
367 | static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf) | 99 | static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf) |
368 | { | 100 | { |
369 | struct enic *enic = vnic_dev_priv(wq->vdev); | 101 | struct enic *enic = vnic_dev_priv(wq->vdev); |
@@ -2496,7 +2228,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2496 | netdev->netdev_ops = &enic_netdev_ops; | 2228 | netdev->netdev_ops = &enic_netdev_ops; |
2497 | 2229 | ||
2498 | netdev->watchdog_timeo = 2 * HZ; | 2230 | netdev->watchdog_timeo = 2 * HZ; |
2499 | netdev->ethtool_ops = &enic_ethtool_ops; | 2231 | enic_set_ethtool_ops(netdev); |
2500 | 2232 | ||
2501 | netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; | 2233 | netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; |
2502 | if (ENIC_SETTING(enic, LOOP)) { | 2234 | if (ENIC_SETTING(enic, LOOP)) { |