1 // SPDX-License-Identifier: GPL-2.0-only
7 struct stats_req_info
{
8 struct ethnl_req_info base
;
9 DECLARE_BITMAP(stat_mask
, __ETHTOOL_STATS_CNT
);
10 enum ethtool_mac_stats_src src
;
13 #define STATS_REQINFO(__req_base) \
14 container_of(__req_base, struct stats_req_info, base)
16 struct stats_reply_data
{
17 struct ethnl_reply_data base
;
19 struct ethtool_eth_phy_stats phy_stats
;
20 struct ethtool_eth_mac_stats mac_stats
;
21 struct ethtool_eth_ctrl_stats ctrl_stats
;
22 struct ethtool_rmon_stats rmon_stats
;
24 const struct ethtool_rmon_hist_range
*rmon_ranges
;
27 #define STATS_REPDATA(__reply_base) \
28 container_of(__reply_base, struct stats_reply_data, base)
30 const char stats_std_names
[__ETHTOOL_STATS_CNT
][ETH_GSTRING_LEN
] = {
31 [ETHTOOL_STATS_ETH_PHY
] = "eth-phy",
32 [ETHTOOL_STATS_ETH_MAC
] = "eth-mac",
33 [ETHTOOL_STATS_ETH_CTRL
] = "eth-ctrl",
34 [ETHTOOL_STATS_RMON
] = "rmon",
37 const char stats_eth_phy_names
[__ETHTOOL_A_STATS_ETH_PHY_CNT
][ETH_GSTRING_LEN
] = {
38 [ETHTOOL_A_STATS_ETH_PHY_5_SYM_ERR
] = "SymbolErrorDuringCarrier",
41 const char stats_eth_mac_names
[__ETHTOOL_A_STATS_ETH_MAC_CNT
][ETH_GSTRING_LEN
] = {
42 [ETHTOOL_A_STATS_ETH_MAC_2_TX_PKT
] = "FramesTransmittedOK",
43 [ETHTOOL_A_STATS_ETH_MAC_3_SINGLE_COL
] = "SingleCollisionFrames",
44 [ETHTOOL_A_STATS_ETH_MAC_4_MULTI_COL
] = "MultipleCollisionFrames",
45 [ETHTOOL_A_STATS_ETH_MAC_5_RX_PKT
] = "FramesReceivedOK",
46 [ETHTOOL_A_STATS_ETH_MAC_6_FCS_ERR
] = "FrameCheckSequenceErrors",
47 [ETHTOOL_A_STATS_ETH_MAC_7_ALIGN_ERR
] = "AlignmentErrors",
48 [ETHTOOL_A_STATS_ETH_MAC_8_TX_BYTES
] = "OctetsTransmittedOK",
49 [ETHTOOL_A_STATS_ETH_MAC_9_TX_DEFER
] = "FramesWithDeferredXmissions",
50 [ETHTOOL_A_STATS_ETH_MAC_10_LATE_COL
] = "LateCollisions",
51 [ETHTOOL_A_STATS_ETH_MAC_11_XS_COL
] = "FramesAbortedDueToXSColls",
52 [ETHTOOL_A_STATS_ETH_MAC_12_TX_INT_ERR
] = "FramesLostDueToIntMACXmitError",
53 [ETHTOOL_A_STATS_ETH_MAC_13_CS_ERR
] = "CarrierSenseErrors",
54 [ETHTOOL_A_STATS_ETH_MAC_14_RX_BYTES
] = "OctetsReceivedOK",
55 [ETHTOOL_A_STATS_ETH_MAC_15_RX_INT_ERR
] = "FramesLostDueToIntMACRcvError",
56 [ETHTOOL_A_STATS_ETH_MAC_18_TX_MCAST
] = "MulticastFramesXmittedOK",
57 [ETHTOOL_A_STATS_ETH_MAC_19_TX_BCAST
] = "BroadcastFramesXmittedOK",
58 [ETHTOOL_A_STATS_ETH_MAC_20_XS_DEFER
] = "FramesWithExcessiveDeferral",
59 [ETHTOOL_A_STATS_ETH_MAC_21_RX_MCAST
] = "MulticastFramesReceivedOK",
60 [ETHTOOL_A_STATS_ETH_MAC_22_RX_BCAST
] = "BroadcastFramesReceivedOK",
61 [ETHTOOL_A_STATS_ETH_MAC_23_IR_LEN_ERR
] = "InRangeLengthErrors",
62 [ETHTOOL_A_STATS_ETH_MAC_24_OOR_LEN
] = "OutOfRangeLengthField",
63 [ETHTOOL_A_STATS_ETH_MAC_25_TOO_LONG_ERR
] = "FrameTooLongErrors",
66 const char stats_eth_ctrl_names
[__ETHTOOL_A_STATS_ETH_CTRL_CNT
][ETH_GSTRING_LEN
] = {
67 [ETHTOOL_A_STATS_ETH_CTRL_3_TX
] = "MACControlFramesTransmitted",
68 [ETHTOOL_A_STATS_ETH_CTRL_4_RX
] = "MACControlFramesReceived",
69 [ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP
] = "UnsupportedOpcodesReceived",
72 const char stats_rmon_names
[__ETHTOOL_A_STATS_RMON_CNT
][ETH_GSTRING_LEN
] = {
73 [ETHTOOL_A_STATS_RMON_UNDERSIZE
] = "etherStatsUndersizePkts",
74 [ETHTOOL_A_STATS_RMON_OVERSIZE
] = "etherStatsOversizePkts",
75 [ETHTOOL_A_STATS_RMON_FRAG
] = "etherStatsFragments",
76 [ETHTOOL_A_STATS_RMON_JABBER
] = "etherStatsJabbers",
79 const struct nla_policy ethnl_stats_get_policy
[ETHTOOL_A_STATS_SRC
+ 1] = {
80 [ETHTOOL_A_STATS_HEADER
] =
81 NLA_POLICY_NESTED(ethnl_header_policy
),
82 [ETHTOOL_A_STATS_GROUPS
] = { .type
= NLA_NESTED
},
83 [ETHTOOL_A_STATS_SRC
] =
84 NLA_POLICY_MAX(NLA_U32
, ETHTOOL_MAC_STATS_SRC_PMAC
),
87 static int stats_parse_request(struct ethnl_req_info
*req_base
,
89 struct netlink_ext_ack
*extack
)
91 enum ethtool_mac_stats_src src
= ETHTOOL_MAC_STATS_SRC_AGGREGATE
;
92 struct stats_req_info
*req_info
= STATS_REQINFO(req_base
);
96 err
= ethnl_update_bitset(req_info
->stat_mask
, __ETHTOOL_STATS_CNT
,
97 tb
[ETHTOOL_A_STATS_GROUPS
], stats_std_names
,
103 NL_SET_ERR_MSG(extack
, "no stats requested");
107 if (tb
[ETHTOOL_A_STATS_SRC
])
108 src
= nla_get_u32(tb
[ETHTOOL_A_STATS_SRC
]);
115 static int stats_prepare_data(const struct ethnl_req_info
*req_base
,
116 struct ethnl_reply_data
*reply_base
,
117 const struct genl_info
*info
)
119 const struct stats_req_info
*req_info
= STATS_REQINFO(req_base
);
120 struct stats_reply_data
*data
= STATS_REPDATA(reply_base
);
121 enum ethtool_mac_stats_src src
= req_info
->src
;
122 struct net_device
*dev
= reply_base
->dev
;
125 ret
= ethnl_ops_begin(dev
);
129 if ((src
== ETHTOOL_MAC_STATS_SRC_EMAC
||
130 src
== ETHTOOL_MAC_STATS_SRC_PMAC
) &&
131 !__ethtool_dev_mm_supported(dev
)) {
132 NL_SET_ERR_MSG_MOD(info
->extack
,
133 "Device does not support MAC merge layer");
134 ethnl_ops_complete(dev
);
138 /* Mark all stats as unset (see ETHTOOL_STAT_NOT_SET) to prevent them
139 * from being reported to user space in case driver did not set them.
141 memset(&data
->stats
, 0xff, sizeof(data
->stats
));
143 data
->phy_stats
.src
= src
;
144 data
->mac_stats
.src
= src
;
145 data
->ctrl_stats
.src
= src
;
146 data
->rmon_stats
.src
= src
;
148 if (test_bit(ETHTOOL_STATS_ETH_PHY
, req_info
->stat_mask
) &&
149 dev
->ethtool_ops
->get_eth_phy_stats
)
150 dev
->ethtool_ops
->get_eth_phy_stats(dev
, &data
->phy_stats
);
151 if (test_bit(ETHTOOL_STATS_ETH_MAC
, req_info
->stat_mask
) &&
152 dev
->ethtool_ops
->get_eth_mac_stats
)
153 dev
->ethtool_ops
->get_eth_mac_stats(dev
, &data
->mac_stats
);
154 if (test_bit(ETHTOOL_STATS_ETH_CTRL
, req_info
->stat_mask
) &&
155 dev
->ethtool_ops
->get_eth_ctrl_stats
)
156 dev
->ethtool_ops
->get_eth_ctrl_stats(dev
, &data
->ctrl_stats
);
157 if (test_bit(ETHTOOL_STATS_RMON
, req_info
->stat_mask
) &&
158 dev
->ethtool_ops
->get_rmon_stats
)
159 dev
->ethtool_ops
->get_rmon_stats(dev
, &data
->rmon_stats
,
162 ethnl_ops_complete(dev
);
166 static int stats_reply_size(const struct ethnl_req_info
*req_base
,
167 const struct ethnl_reply_data
*reply_base
)
169 const struct stats_req_info
*req_info
= STATS_REQINFO(req_base
);
170 unsigned int n_grps
= 0, n_stats
= 0;
173 len
+= nla_total_size(sizeof(u32
)); /* _STATS_SRC */
175 if (test_bit(ETHTOOL_STATS_ETH_PHY
, req_info
->stat_mask
)) {
176 n_stats
+= sizeof(struct ethtool_eth_phy_stats
) / sizeof(u64
);
179 if (test_bit(ETHTOOL_STATS_ETH_MAC
, req_info
->stat_mask
)) {
180 n_stats
+= sizeof(struct ethtool_eth_mac_stats
) / sizeof(u64
);
183 if (test_bit(ETHTOOL_STATS_ETH_CTRL
, req_info
->stat_mask
)) {
184 n_stats
+= sizeof(struct ethtool_eth_ctrl_stats
) / sizeof(u64
);
187 if (test_bit(ETHTOOL_STATS_RMON
, req_info
->stat_mask
)) {
188 n_stats
+= sizeof(struct ethtool_rmon_stats
) / sizeof(u64
);
190 /* Above includes the space for _A_STATS_GRP_HIST_VALs */
192 len
+= (nla_total_size(0) + /* _A_STATS_GRP_HIST */
193 nla_total_size(4) + /* _A_STATS_GRP_HIST_BKT_LOW */
194 nla_total_size(4)) * /* _A_STATS_GRP_HIST_BKT_HI */
195 ETHTOOL_RMON_HIST_MAX
* 2;
198 len
+= n_grps
* (nla_total_size(0) + /* _A_STATS_GRP */
199 nla_total_size(4) + /* _A_STATS_GRP_ID */
200 nla_total_size(4)); /* _A_STATS_GRP_SS_ID */
201 len
+= n_stats
* (nla_total_size(0) + /* _A_STATS_GRP_STAT */
202 nla_total_size_64bit(sizeof(u64
)));
207 static int stat_put(struct sk_buff
*skb
, u16 attrtype
, u64 val
)
212 if (val
== ETHTOOL_STAT_NOT_SET
)
215 /* We want to start stats attr types from 0, so we don't have a type
216 * for pad inside ETHTOOL_A_STATS_GRP_STAT. Pad things on the outside
217 * of ETHTOOL_A_STATS_GRP_STAT. Since we're one nest away from the
218 * actual attr we're 4B off - nla_need_padding_for_64bit() & co.
221 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
222 if (!IS_ALIGNED((unsigned long)skb_tail_pointer(skb
), 8))
223 if (!nla_reserve(skb
, ETHTOOL_A_STATS_GRP_PAD
, 0))
227 nest
= nla_nest_start(skb
, ETHTOOL_A_STATS_GRP_STAT
);
231 ret
= nla_put_u64_64bit(skb
, attrtype
, val
, -1 /* not used */);
233 nla_nest_cancel(skb
, nest
);
237 nla_nest_end(skb
, nest
);
241 static int stats_put_phy_stats(struct sk_buff
*skb
,
242 const struct stats_reply_data
*data
)
244 if (stat_put(skb
, ETHTOOL_A_STATS_ETH_PHY_5_SYM_ERR
,
245 data
->phy_stats
.SymbolErrorDuringCarrier
))
250 static int stats_put_mac_stats(struct sk_buff
*skb
,
251 const struct stats_reply_data
*data
)
253 if (stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_2_TX_PKT
,
254 data
->mac_stats
.FramesTransmittedOK
) ||
255 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_3_SINGLE_COL
,
256 data
->mac_stats
.SingleCollisionFrames
) ||
257 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_4_MULTI_COL
,
258 data
->mac_stats
.MultipleCollisionFrames
) ||
259 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_5_RX_PKT
,
260 data
->mac_stats
.FramesReceivedOK
) ||
261 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_6_FCS_ERR
,
262 data
->mac_stats
.FrameCheckSequenceErrors
) ||
263 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_7_ALIGN_ERR
,
264 data
->mac_stats
.AlignmentErrors
) ||
265 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_8_TX_BYTES
,
266 data
->mac_stats
.OctetsTransmittedOK
) ||
267 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_9_TX_DEFER
,
268 data
->mac_stats
.FramesWithDeferredXmissions
) ||
269 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_10_LATE_COL
,
270 data
->mac_stats
.LateCollisions
) ||
271 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_11_XS_COL
,
272 data
->mac_stats
.FramesAbortedDueToXSColls
) ||
273 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_12_TX_INT_ERR
,
274 data
->mac_stats
.FramesLostDueToIntMACXmitError
) ||
275 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_13_CS_ERR
,
276 data
->mac_stats
.CarrierSenseErrors
) ||
277 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_14_RX_BYTES
,
278 data
->mac_stats
.OctetsReceivedOK
) ||
279 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_15_RX_INT_ERR
,
280 data
->mac_stats
.FramesLostDueToIntMACRcvError
) ||
281 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_18_TX_MCAST
,
282 data
->mac_stats
.MulticastFramesXmittedOK
) ||
283 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_19_TX_BCAST
,
284 data
->mac_stats
.BroadcastFramesXmittedOK
) ||
285 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_20_XS_DEFER
,
286 data
->mac_stats
.FramesWithExcessiveDeferral
) ||
287 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_21_RX_MCAST
,
288 data
->mac_stats
.MulticastFramesReceivedOK
) ||
289 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_22_RX_BCAST
,
290 data
->mac_stats
.BroadcastFramesReceivedOK
) ||
291 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_23_IR_LEN_ERR
,
292 data
->mac_stats
.InRangeLengthErrors
) ||
293 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_24_OOR_LEN
,
294 data
->mac_stats
.OutOfRangeLengthField
) ||
295 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_25_TOO_LONG_ERR
,
296 data
->mac_stats
.FrameTooLongErrors
))
301 static int stats_put_ctrl_stats(struct sk_buff
*skb
,
302 const struct stats_reply_data
*data
)
304 if (stat_put(skb
, ETHTOOL_A_STATS_ETH_CTRL_3_TX
,
305 data
->ctrl_stats
.MACControlFramesTransmitted
) ||
306 stat_put(skb
, ETHTOOL_A_STATS_ETH_CTRL_4_RX
,
307 data
->ctrl_stats
.MACControlFramesReceived
) ||
308 stat_put(skb
, ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP
,
309 data
->ctrl_stats
.UnsupportedOpcodesReceived
))
314 static int stats_put_rmon_hist(struct sk_buff
*skb
, u32 attr
, const u64
*hist
,
315 const struct ethtool_rmon_hist_range
*ranges
)
323 for (i
= 0; i
< ETHTOOL_RMON_HIST_MAX
; i
++) {
324 if (!ranges
[i
].low
&& !ranges
[i
].high
)
326 if (hist
[i
] == ETHTOOL_STAT_NOT_SET
)
329 nest
= nla_nest_start(skb
, attr
);
333 if (nla_put_u32(skb
, ETHTOOL_A_STATS_GRP_HIST_BKT_LOW
,
335 nla_put_u32(skb
, ETHTOOL_A_STATS_GRP_HIST_BKT_HI
,
337 nla_put_u64_64bit(skb
, ETHTOOL_A_STATS_GRP_HIST_VAL
,
338 hist
[i
], ETHTOOL_A_STATS_GRP_PAD
))
339 goto err_cancel_hist
;
341 nla_nest_end(skb
, nest
);
347 nla_nest_cancel(skb
, nest
);
351 static int stats_put_rmon_stats(struct sk_buff
*skb
,
352 const struct stats_reply_data
*data
)
354 if (stats_put_rmon_hist(skb
, ETHTOOL_A_STATS_GRP_HIST_RX
,
355 data
->rmon_stats
.hist
, data
->rmon_ranges
) ||
356 stats_put_rmon_hist(skb
, ETHTOOL_A_STATS_GRP_HIST_TX
,
357 data
->rmon_stats
.hist_tx
, data
->rmon_ranges
))
360 if (stat_put(skb
, ETHTOOL_A_STATS_RMON_UNDERSIZE
,
361 data
->rmon_stats
.undersize_pkts
) ||
362 stat_put(skb
, ETHTOOL_A_STATS_RMON_OVERSIZE
,
363 data
->rmon_stats
.oversize_pkts
) ||
364 stat_put(skb
, ETHTOOL_A_STATS_RMON_FRAG
,
365 data
->rmon_stats
.fragments
) ||
366 stat_put(skb
, ETHTOOL_A_STATS_RMON_JABBER
,
367 data
->rmon_stats
.jabbers
))
373 static int stats_put_stats(struct sk_buff
*skb
,
374 const struct stats_reply_data
*data
,
376 int (*cb
)(struct sk_buff
*skb
,
377 const struct stats_reply_data
*data
))
381 nest
= nla_nest_start(skb
, ETHTOOL_A_STATS_GRP
);
385 if (nla_put_u32(skb
, ETHTOOL_A_STATS_GRP_ID
, id
) ||
386 nla_put_u32(skb
, ETHTOOL_A_STATS_GRP_SS_ID
, ss_id
))
392 nla_nest_end(skb
, nest
);
396 nla_nest_cancel(skb
, nest
);
400 static int stats_fill_reply(struct sk_buff
*skb
,
401 const struct ethnl_req_info
*req_base
,
402 const struct ethnl_reply_data
*reply_base
)
404 const struct stats_req_info
*req_info
= STATS_REQINFO(req_base
);
405 const struct stats_reply_data
*data
= STATS_REPDATA(reply_base
);
408 if (nla_put_u32(skb
, ETHTOOL_A_STATS_SRC
, req_info
->src
))
411 if (!ret
&& test_bit(ETHTOOL_STATS_ETH_PHY
, req_info
->stat_mask
))
412 ret
= stats_put_stats(skb
, data
, ETHTOOL_STATS_ETH_PHY
,
413 ETH_SS_STATS_ETH_PHY
,
414 stats_put_phy_stats
);
415 if (!ret
&& test_bit(ETHTOOL_STATS_ETH_MAC
, req_info
->stat_mask
))
416 ret
= stats_put_stats(skb
, data
, ETHTOOL_STATS_ETH_MAC
,
417 ETH_SS_STATS_ETH_MAC
,
418 stats_put_mac_stats
);
419 if (!ret
&& test_bit(ETHTOOL_STATS_ETH_CTRL
, req_info
->stat_mask
))
420 ret
= stats_put_stats(skb
, data
, ETHTOOL_STATS_ETH_CTRL
,
421 ETH_SS_STATS_ETH_CTRL
,
422 stats_put_ctrl_stats
);
423 if (!ret
&& test_bit(ETHTOOL_STATS_RMON
, req_info
->stat_mask
))
424 ret
= stats_put_stats(skb
, data
, ETHTOOL_STATS_RMON
,
425 ETH_SS_STATS_RMON
, stats_put_rmon_stats
);
430 const struct ethnl_request_ops ethnl_stats_request_ops
= {
431 .request_cmd
= ETHTOOL_MSG_STATS_GET
,
432 .reply_cmd
= ETHTOOL_MSG_STATS_GET_REPLY
,
433 .hdr_attr
= ETHTOOL_A_STATS_HEADER
,
434 .req_info_size
= sizeof(struct stats_req_info
),
435 .reply_data_size
= sizeof(struct stats_reply_data
),
437 .parse_request
= stats_parse_request
,
438 .prepare_data
= stats_prepare_data
,
439 .reply_size
= stats_reply_size
,
440 .fill_reply
= stats_fill_reply
,
443 static u64
ethtool_stats_sum(u64 a
, u64 b
)
445 if (a
== ETHTOOL_STAT_NOT_SET
)
447 if (b
== ETHTOOL_STAT_NOT_SET
)
452 /* Avoid modifying the aggregation procedure every time a new counter is added
453 * by treating the structures as an array of u64 statistics.
455 static void ethtool_aggregate_stats(void *aggr_stats
, const void *emac_stats
,
456 const void *pmac_stats
, size_t stats_size
,
459 size_t num_stats
= stats_size
/ sizeof(u64
);
460 const u64
*s1
= emac_stats
+ stats_offset
;
461 const u64
*s2
= pmac_stats
+ stats_offset
;
462 u64
*s
= aggr_stats
+ stats_offset
;
465 for (i
= 0; i
< num_stats
; i
++)
466 s
[i
] = ethtool_stats_sum(s1
[i
], s2
[i
]);
469 void ethtool_aggregate_mac_stats(struct net_device
*dev
,
470 struct ethtool_eth_mac_stats
*mac_stats
)
472 const struct ethtool_ops
*ops
= dev
->ethtool_ops
;
473 struct ethtool_eth_mac_stats pmac
, emac
;
475 memset(&emac
, 0xff, sizeof(emac
));
476 memset(&pmac
, 0xff, sizeof(pmac
));
477 emac
.src
= ETHTOOL_MAC_STATS_SRC_EMAC
;
478 pmac
.src
= ETHTOOL_MAC_STATS_SRC_PMAC
;
480 ops
->get_eth_mac_stats(dev
, &emac
);
481 ops
->get_eth_mac_stats(dev
, &pmac
);
483 ethtool_aggregate_stats(mac_stats
, &emac
, &pmac
,
484 sizeof(mac_stats
->stats
),
485 offsetof(struct ethtool_eth_mac_stats
, stats
));
487 EXPORT_SYMBOL(ethtool_aggregate_mac_stats
);
489 void ethtool_aggregate_phy_stats(struct net_device
*dev
,
490 struct ethtool_eth_phy_stats
*phy_stats
)
492 const struct ethtool_ops
*ops
= dev
->ethtool_ops
;
493 struct ethtool_eth_phy_stats pmac
, emac
;
495 memset(&emac
, 0xff, sizeof(emac
));
496 memset(&pmac
, 0xff, sizeof(pmac
));
497 emac
.src
= ETHTOOL_MAC_STATS_SRC_EMAC
;
498 pmac
.src
= ETHTOOL_MAC_STATS_SRC_PMAC
;
500 ops
->get_eth_phy_stats(dev
, &emac
);
501 ops
->get_eth_phy_stats(dev
, &pmac
);
503 ethtool_aggregate_stats(phy_stats
, &emac
, &pmac
,
504 sizeof(phy_stats
->stats
),
505 offsetof(struct ethtool_eth_phy_stats
, stats
));
507 EXPORT_SYMBOL(ethtool_aggregate_phy_stats
);
509 void ethtool_aggregate_ctrl_stats(struct net_device
*dev
,
510 struct ethtool_eth_ctrl_stats
*ctrl_stats
)
512 const struct ethtool_ops
*ops
= dev
->ethtool_ops
;
513 struct ethtool_eth_ctrl_stats pmac
, emac
;
515 memset(&emac
, 0xff, sizeof(emac
));
516 memset(&pmac
, 0xff, sizeof(pmac
));
517 emac
.src
= ETHTOOL_MAC_STATS_SRC_EMAC
;
518 pmac
.src
= ETHTOOL_MAC_STATS_SRC_PMAC
;
520 ops
->get_eth_ctrl_stats(dev
, &emac
);
521 ops
->get_eth_ctrl_stats(dev
, &pmac
);
523 ethtool_aggregate_stats(ctrl_stats
, &emac
, &pmac
,
524 sizeof(ctrl_stats
->stats
),
525 offsetof(struct ethtool_eth_ctrl_stats
, stats
));
527 EXPORT_SYMBOL(ethtool_aggregate_ctrl_stats
);
529 void ethtool_aggregate_pause_stats(struct net_device
*dev
,
530 struct ethtool_pause_stats
*pause_stats
)
532 const struct ethtool_ops
*ops
= dev
->ethtool_ops
;
533 struct ethtool_pause_stats pmac
, emac
;
535 memset(&emac
, 0xff, sizeof(emac
));
536 memset(&pmac
, 0xff, sizeof(pmac
));
537 emac
.src
= ETHTOOL_MAC_STATS_SRC_EMAC
;
538 pmac
.src
= ETHTOOL_MAC_STATS_SRC_PMAC
;
540 ops
->get_pause_stats(dev
, &emac
);
541 ops
->get_pause_stats(dev
, &pmac
);
543 ethtool_aggregate_stats(pause_stats
, &emac
, &pmac
,
544 sizeof(pause_stats
->stats
),
545 offsetof(struct ethtool_pause_stats
, stats
));
547 EXPORT_SYMBOL(ethtool_aggregate_pause_stats
);
549 void ethtool_aggregate_rmon_stats(struct net_device
*dev
,
550 struct ethtool_rmon_stats
*rmon_stats
)
552 const struct ethtool_ops
*ops
= dev
->ethtool_ops
;
553 const struct ethtool_rmon_hist_range
*dummy
;
554 struct ethtool_rmon_stats pmac
, emac
;
556 memset(&emac
, 0xff, sizeof(emac
));
557 memset(&pmac
, 0xff, sizeof(pmac
));
558 emac
.src
= ETHTOOL_MAC_STATS_SRC_EMAC
;
559 pmac
.src
= ETHTOOL_MAC_STATS_SRC_PMAC
;
561 ops
->get_rmon_stats(dev
, &emac
, &dummy
);
562 ops
->get_rmon_stats(dev
, &pmac
, &dummy
);
564 ethtool_aggregate_stats(rmon_stats
, &emac
, &pmac
,
565 sizeof(rmon_stats
->stats
),
566 offsetof(struct ethtool_rmon_stats
, stats
));
568 EXPORT_SYMBOL(ethtool_aggregate_rmon_stats
);