pause.c (03ab8e6297acd1bc0eedaa050e2a1635c576fd11) | pause.c (04692c9020b76939715d6f2b4ff84d832246e0fc) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2 3#include "netlink.h" 4#include "common.h" 5 6struct pause_req_info { 7 struct ethnl_req_info base; | 1// SPDX-License-Identifier: GPL-2.0-only 2 3#include "netlink.h" 4#include "common.h" 5 6struct pause_req_info { 7 struct ethnl_req_info base; |
8 enum ethtool_mac_stats_src src; |
|
8}; 9 | 9}; 10 |
11#define PAUSE_REQINFO(__req_base) \ 12 container_of(__req_base, struct pause_req_info, base) 13 |
|
10struct pause_reply_data { 11 struct ethnl_reply_data base; 12 struct ethtool_pauseparam pauseparam; 13 struct ethtool_pause_stats pausestat; 14}; 15 16#define PAUSE_REPDATA(__reply_base) \ 17 container_of(__reply_base, struct pause_reply_data, base) 18 19const struct nla_policy ethnl_pause_get_policy[] = { 20 [ETHTOOL_A_PAUSE_HEADER] = 21 NLA_POLICY_NESTED(ethnl_header_policy_stats), | 14struct pause_reply_data { 15 struct ethnl_reply_data base; 16 struct ethtool_pauseparam pauseparam; 17 struct ethtool_pause_stats pausestat; 18}; 19 20#define PAUSE_REPDATA(__reply_base) \ 21 container_of(__reply_base, struct pause_reply_data, base) 22 23const struct nla_policy ethnl_pause_get_policy[] = { 24 [ETHTOOL_A_PAUSE_HEADER] = 25 NLA_POLICY_NESTED(ethnl_header_policy_stats), |
26 [ETHTOOL_A_PAUSE_STATS_SRC] = 27 NLA_POLICY_MAX(NLA_U32, ETHTOOL_MAC_STATS_SRC_PMAC), |
|
22}; 23 | 28}; 29 |
30static int pause_parse_request(struct ethnl_req_info *req_base, 31 struct nlattr **tb, 32 struct netlink_ext_ack *extack) 33{ 34 enum ethtool_mac_stats_src src = ETHTOOL_MAC_STATS_SRC_AGGREGATE; 35 struct pause_req_info *req_info = PAUSE_REQINFO(req_base); 36 37 if (tb[ETHTOOL_A_PAUSE_STATS_SRC]) { 38 if (!(req_base->flags & ETHTOOL_FLAG_STATS)) { 39 NL_SET_ERR_MSG_MOD(extack, 40 "ETHTOOL_FLAG_STATS must be set when requesting a source of stats"); 41 return -EINVAL; 42 } 43 44 src = nla_get_u32(tb[ETHTOOL_A_PAUSE_STATS_SRC]); 45 } 46 47 req_info->src = src; 48 49 return 0; 50} 51 |
|
24static int pause_prepare_data(const struct ethnl_req_info *req_base, 25 struct ethnl_reply_data *reply_base, 26 struct genl_info *info) 27{ | 52static int pause_prepare_data(const struct ethnl_req_info *req_base, 53 struct ethnl_reply_data *reply_base, 54 struct genl_info *info) 55{ |
56 const struct pause_req_info *req_info = PAUSE_REQINFO(req_base); |
|
28 struct pause_reply_data *data = PAUSE_REPDATA(reply_base); | 57 struct pause_reply_data *data = PAUSE_REPDATA(reply_base); |
58 enum ethtool_mac_stats_src src = req_info->src; 59 struct netlink_ext_ack *extack = info->extack; |
|
29 struct net_device *dev = reply_base->dev; 30 int ret; 31 32 if (!dev->ethtool_ops->get_pauseparam) 33 return -EOPNOTSUPP; 34 35 ethtool_stats_init((u64 *)&data->pausestat, 36 sizeof(data->pausestat) / 8); | 60 struct net_device *dev = reply_base->dev; 61 int ret; 62 63 if (!dev->ethtool_ops->get_pauseparam) 64 return -EOPNOTSUPP; 65 66 ethtool_stats_init((u64 *)&data->pausestat, 67 sizeof(data->pausestat) / 8); |
68 data->pausestat.src = src; |
|
37 38 ret = ethnl_ops_begin(dev); 39 if (ret < 0) 40 return ret; | 69 70 ret = ethnl_ops_begin(dev); 71 if (ret < 0) 72 return ret; |
73 74 if ((src == ETHTOOL_MAC_STATS_SRC_EMAC || 75 src == ETHTOOL_MAC_STATS_SRC_PMAC) && 76 !__ethtool_dev_mm_supported(dev)) { 77 NL_SET_ERR_MSG_MOD(extack, 78 "Device does not support MAC merge layer"); 79 ethnl_ops_complete(dev); 80 return -EOPNOTSUPP; 81 } 82 |
|
41 dev->ethtool_ops->get_pauseparam(dev, &data->pauseparam); 42 if (req_base->flags & ETHTOOL_FLAG_STATS && 43 dev->ethtool_ops->get_pause_stats) 44 dev->ethtool_ops->get_pause_stats(dev, &data->pausestat); | 83 dev->ethtool_ops->get_pauseparam(dev, &data->pauseparam); 84 if (req_base->flags & ETHTOOL_FLAG_STATS && 85 dev->ethtool_ops->get_pause_stats) 86 dev->ethtool_ops->get_pause_stats(dev, &data->pausestat); |
87 |
|
45 ethnl_ops_complete(dev); 46 47 return 0; 48} 49 50static int pause_reply_size(const struct ethnl_req_info *req_base, 51 const struct ethnl_reply_data *reply_base) 52{ 53 int n = nla_total_size(sizeof(u8)) + /* _PAUSE_AUTONEG */ 54 nla_total_size(sizeof(u8)) + /* _PAUSE_RX */ 55 nla_total_size(sizeof(u8)); /* _PAUSE_TX */ 56 57 if (req_base->flags & ETHTOOL_FLAG_STATS) 58 n += nla_total_size(0) + /* _PAUSE_STATS */ | 88 ethnl_ops_complete(dev); 89 90 return 0; 91} 92 93static int pause_reply_size(const struct ethnl_req_info *req_base, 94 const struct ethnl_reply_data *reply_base) 95{ 96 int n = nla_total_size(sizeof(u8)) + /* _PAUSE_AUTONEG */ 97 nla_total_size(sizeof(u8)) + /* _PAUSE_RX */ 98 nla_total_size(sizeof(u8)); /* _PAUSE_TX */ 99 100 if (req_base->flags & ETHTOOL_FLAG_STATS) 101 n += nla_total_size(0) + /* _PAUSE_STATS */ |
102 nla_total_size(sizeof(u32)) + /* _PAUSE_STATS_SRC */ |
|
59 nla_total_size_64bit(sizeof(u64)) * ETHTOOL_PAUSE_STAT_CNT; 60 return n; 61} 62 63static int ethtool_put_stat(struct sk_buff *skb, u64 val, u16 attrtype, 64 u16 padtype) 65{ 66 if (val == ETHTOOL_STAT_NOT_SET) --- 5 unchanged lines hidden (view full) --- 72} 73 74static int pause_put_stats(struct sk_buff *skb, 75 const struct ethtool_pause_stats *pause_stats) 76{ 77 const u16 pad = ETHTOOL_A_PAUSE_STAT_PAD; 78 struct nlattr *nest; 79 | 103 nla_total_size_64bit(sizeof(u64)) * ETHTOOL_PAUSE_STAT_CNT; 104 return n; 105} 106 107static int ethtool_put_stat(struct sk_buff *skb, u64 val, u16 attrtype, 108 u16 padtype) 109{ 110 if (val == ETHTOOL_STAT_NOT_SET) --- 5 unchanged lines hidden (view full) --- 116} 117 118static int pause_put_stats(struct sk_buff *skb, 119 const struct ethtool_pause_stats *pause_stats) 120{ 121 const u16 pad = ETHTOOL_A_PAUSE_STAT_PAD; 122 struct nlattr *nest; 123 |
124 if (nla_put_u32(skb, ETHTOOL_A_PAUSE_STATS_SRC, pause_stats->src)) 125 return -EMSGSIZE; 126 |
|
80 nest = nla_nest_start(skb, ETHTOOL_A_PAUSE_STATS); 81 if (!nest) 82 return -EMSGSIZE; 83 84 if (ethtool_put_stat(skb, pause_stats->tx_pause_frames, 85 ETHTOOL_A_PAUSE_STAT_TX_FRAMES, pad) || 86 ethtool_put_stat(skb, pause_stats->rx_pause_frames, 87 ETHTOOL_A_PAUSE_STAT_RX_FRAMES, pad)) --- 28 unchanged lines hidden (view full) --- 116 117const struct ethnl_request_ops ethnl_pause_request_ops = { 118 .request_cmd = ETHTOOL_MSG_PAUSE_GET, 119 .reply_cmd = ETHTOOL_MSG_PAUSE_GET_REPLY, 120 .hdr_attr = ETHTOOL_A_PAUSE_HEADER, 121 .req_info_size = sizeof(struct pause_req_info), 122 .reply_data_size = sizeof(struct pause_reply_data), 123 | 127 nest = nla_nest_start(skb, ETHTOOL_A_PAUSE_STATS); 128 if (!nest) 129 return -EMSGSIZE; 130 131 if (ethtool_put_stat(skb, pause_stats->tx_pause_frames, 132 ETHTOOL_A_PAUSE_STAT_TX_FRAMES, pad) || 133 ethtool_put_stat(skb, pause_stats->rx_pause_frames, 134 ETHTOOL_A_PAUSE_STAT_RX_FRAMES, pad)) --- 28 unchanged lines hidden (view full) --- 163 164const struct ethnl_request_ops ethnl_pause_request_ops = { 165 .request_cmd = ETHTOOL_MSG_PAUSE_GET, 166 .reply_cmd = ETHTOOL_MSG_PAUSE_GET_REPLY, 167 .hdr_attr = ETHTOOL_A_PAUSE_HEADER, 168 .req_info_size = sizeof(struct pause_req_info), 169 .reply_data_size = sizeof(struct pause_reply_data), 170 |
171 .parse_request = pause_parse_request, |
|
124 .prepare_data = pause_prepare_data, 125 .reply_size = pause_reply_size, 126 .fill_reply = pause_fill_reply, 127}; 128 129/* PAUSE_SET */ 130 131const struct nla_policy ethnl_pause_set_policy[] = { --- 55 unchanged lines hidden --- | 172 .prepare_data = pause_prepare_data, 173 .reply_size = pause_reply_size, 174 .fill_reply = pause_fill_reply, 175}; 176 177/* PAUSE_SET */ 178 179const struct nla_policy ethnl_pause_set_policy[] = { --- 55 unchanged lines hidden --- |