]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
iio: imu: inv_mpu6050: test whoami first and against all known values
[mirror_ubuntu-artful-kernel.git] / drivers / staging / fsl-dpaa2 / ethernet / dpaa2-ethtool.c
1 /* Copyright 2014-2016 Freescale Semiconductor Inc.
2 * Copyright 2016 NXP
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of Freescale Semiconductor nor the
12 * names of its contributors may be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 *
16 * ALTERNATIVELY, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") as published by the Free Software
18 * Foundation, either version 2 of that License or (at your option) any
19 * later version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "dpni.h" /* DPNI_LINK_OPT_* */
34 #include "dpaa2-eth.h"
35
36 /* To be kept in sync with DPNI statistics */
37 char dpaa2_ethtool_stats[][ETH_GSTRING_LEN] = {
38 "rx frames",
39 "rx bytes",
40 "rx mcast frames",
41 "rx mcast bytes",
42 "rx bcast frames",
43 "rx bcast bytes",
44 "tx frames",
45 "tx bytes",
46 "tx mcast frames",
47 "tx mcast bytes",
48 "tx bcast frames",
49 "tx bcast bytes",
50 "rx filtered frames",
51 "rx discarded frames",
52 "rx nobuffer discards",
53 "tx discarded frames",
54 "tx confirmed frames",
55 };
56
57 #define DPAA2_ETH_NUM_STATS ARRAY_SIZE(dpaa2_ethtool_stats)
58
59 char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
60 /* per-cpu stats */
61 "tx conf frames",
62 "tx conf bytes",
63 "tx sg frames",
64 "tx sg bytes",
65 "rx sg frames",
66 "rx sg bytes",
67 "enqueue portal busy",
68 /* Channel stats */
69 "dequeue portal busy",
70 "channel pull errors",
71 "cdan",
72 };
73
74 #define DPAA2_ETH_NUM_EXTRA_STATS ARRAY_SIZE(dpaa2_ethtool_extras)
75
76 static void dpaa2_eth_get_drvinfo(struct net_device *net_dev,
77 struct ethtool_drvinfo *drvinfo)
78 {
79 strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
80 strlcpy(drvinfo->version, dpaa2_eth_drv_version,
81 sizeof(drvinfo->version));
82 strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
83 strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
84 sizeof(drvinfo->bus_info));
85 }
86
87 static int
88 dpaa2_eth_get_link_ksettings(struct net_device *net_dev,
89 struct ethtool_link_ksettings *link_settings)
90 {
91 struct dpni_link_state state = {0};
92 int err = 0;
93 struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
94
95 err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
96 if (err) {
97 netdev_err(net_dev, "ERROR %d getting link state", err);
98 goto out;
99 }
100
101 /* At the moment, we have no way of interrogating the DPMAC
102 * from the DPNI side - and for that matter there may exist
103 * no DPMAC at all. So for now we just don't report anything
104 * beyond the DPNI attributes.
105 */
106 if (state.options & DPNI_LINK_OPT_AUTONEG)
107 link_settings->base.autoneg = AUTONEG_ENABLE;
108 if (!(state.options & DPNI_LINK_OPT_HALF_DUPLEX))
109 link_settings->base.duplex = DUPLEX_FULL;
110 link_settings->base.speed = state.rate;
111
112 out:
113 return err;
114 }
115
116 static int
117 dpaa2_eth_set_link_ksettings(struct net_device *net_dev,
118 const struct ethtool_link_ksettings *link_settings)
119 {
120 struct dpni_link_cfg cfg = {0};
121 struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
122 int err = 0;
123
124 netdev_dbg(net_dev, "Setting link parameters...");
125
126 /* Due to a temporary MC limitation, the DPNI must be down
127 * in order to be able to change link settings. Taking steps to let
128 * the user know that.
129 */
130 if (netif_running(net_dev)) {
131 netdev_info(net_dev, "Sorry, interface must be brought down first.\n");
132 return -EACCES;
133 }
134
135 cfg.rate = link_settings->base.speed;
136 if (link_settings->base.autoneg == AUTONEG_ENABLE)
137 cfg.options |= DPNI_LINK_OPT_AUTONEG;
138 else
139 cfg.options &= ~DPNI_LINK_OPT_AUTONEG;
140 if (link_settings->base.duplex == DUPLEX_HALF)
141 cfg.options |= DPNI_LINK_OPT_HALF_DUPLEX;
142 else
143 cfg.options &= ~DPNI_LINK_OPT_HALF_DUPLEX;
144
145 err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
146 if (err)
147 /* ethtool will be loud enough if we return an error; no point
148 * in putting our own error message on the console by default
149 */
150 netdev_dbg(net_dev, "ERROR %d setting link cfg", err);
151
152 return err;
153 }
154
155 static void dpaa2_eth_get_strings(struct net_device *netdev, u32 stringset,
156 u8 *data)
157 {
158 u8 *p = data;
159 int i;
160
161 switch (stringset) {
162 case ETH_SS_STATS:
163 for (i = 0; i < DPAA2_ETH_NUM_STATS; i++) {
164 strlcpy(p, dpaa2_ethtool_stats[i], ETH_GSTRING_LEN);
165 p += ETH_GSTRING_LEN;
166 }
167 for (i = 0; i < DPAA2_ETH_NUM_EXTRA_STATS; i++) {
168 strlcpy(p, dpaa2_ethtool_extras[i], ETH_GSTRING_LEN);
169 p += ETH_GSTRING_LEN;
170 }
171 break;
172 }
173 }
174
175 static int dpaa2_eth_get_sset_count(struct net_device *net_dev, int sset)
176 {
177 switch (sset) {
178 case ETH_SS_STATS: /* ethtool_get_stats(), ethtool_get_drvinfo() */
179 return DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS;
180 default:
181 return -EOPNOTSUPP;
182 }
183 }
184
185 /** Fill in hardware counters, as returned by MC.
186 */
187 static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev,
188 struct ethtool_stats *stats,
189 u64 *data)
190 {
191 int i = 0;
192 int j, k, err;
193 int num_cnt;
194 union dpni_statistics dpni_stats;
195 u64 cdan = 0;
196 u64 portal_busy = 0, pull_err = 0;
197 struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
198 struct dpaa2_eth_drv_stats *extras;
199 struct dpaa2_eth_ch_stats *ch_stats;
200
201 memset(data, 0,
202 sizeof(u64) * (DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS));
203
204 /* Print standard counters, from DPNI statistics */
205 for (j = 0; j <= 2; j++) {
206 err = dpni_get_statistics(priv->mc_io, 0, priv->mc_token,
207 j, &dpni_stats);
208 if (err != 0)
209 netdev_warn(net_dev, "dpni_get_stats(%d) failed", j);
210 switch (j) {
211 case 0:
212 num_cnt = sizeof(dpni_stats.page_0) / sizeof(u64);
213 break;
214 case 1:
215 num_cnt = sizeof(dpni_stats.page_1) / sizeof(u64);
216 break;
217 case 2:
218 num_cnt = sizeof(dpni_stats.page_2) / sizeof(u64);
219 break;
220 default:
221 break;
222 }
223 for (k = 0; k < num_cnt; k++)
224 *(data + i++) = dpni_stats.raw.counter[k];
225 }
226
227 /* Print per-cpu extra stats */
228 for_each_online_cpu(k) {
229 extras = per_cpu_ptr(priv->percpu_extras, k);
230 for (j = 0; j < sizeof(*extras) / sizeof(__u64); j++)
231 *((__u64 *)data + i + j) += *((__u64 *)extras + j);
232 }
233 i += j;
234
235 for (j = 0; j < priv->num_channels; j++) {
236 ch_stats = &priv->channel[j]->stats;
237 cdan += ch_stats->cdan;
238 portal_busy += ch_stats->dequeue_portal_busy;
239 pull_err += ch_stats->pull_err;
240 }
241
242 *(data + i++) = portal_busy;
243 *(data + i++) = pull_err;
244 *(data + i++) = cdan;
245 }
246
247 static int dpaa2_eth_get_rxnfc(struct net_device *net_dev,
248 struct ethtool_rxnfc *rxnfc, u32 *rule_locs)
249 {
250 struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
251
252 switch (rxnfc->cmd) {
253 case ETHTOOL_GRXFH:
254 /* we purposely ignore cmd->flow_type for now, because the
255 * classifier only supports a single set of fields for all
256 * protocols
257 */
258 rxnfc->data = priv->rx_hash_fields;
259 break;
260 case ETHTOOL_GRXRINGS:
261 rxnfc->data = dpaa2_eth_queue_count(priv);
262 break;
263 default:
264 return -EOPNOTSUPP;
265 }
266
267 return 0;
268 }
269
270 const struct ethtool_ops dpaa2_ethtool_ops = {
271 .get_drvinfo = dpaa2_eth_get_drvinfo,
272 .get_link = ethtool_op_get_link,
273 .get_link_ksettings = dpaa2_eth_get_link_ksettings,
274 .set_link_ksettings = dpaa2_eth_set_link_ksettings,
275 .get_sset_count = dpaa2_eth_get_sset_count,
276 .get_ethtool_stats = dpaa2_eth_get_ethtool_stats,
277 .get_strings = dpaa2_eth_get_strings,
278 .get_rxnfc = dpaa2_eth_get_rxnfc,
279 };