1*2b4d8bb0SJiri Pirko // SPDX-License-Identifier: GPL-2.0-or-later
2*2b4d8bb0SJiri Pirko /*
3*2b4d8bb0SJiri Pirko * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4*2b4d8bb0SJiri Pirko * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
5*2b4d8bb0SJiri Pirko */
6*2b4d8bb0SJiri Pirko
7*2b4d8bb0SJiri Pirko #include "devl_internal.h"
8*2b4d8bb0SJiri Pirko
9*2b4d8bb0SJiri Pirko struct devlink_sb {
10*2b4d8bb0SJiri Pirko struct list_head list;
11*2b4d8bb0SJiri Pirko unsigned int index;
12*2b4d8bb0SJiri Pirko u32 size;
13*2b4d8bb0SJiri Pirko u16 ingress_pools_count;
14*2b4d8bb0SJiri Pirko u16 egress_pools_count;
15*2b4d8bb0SJiri Pirko u16 ingress_tc_count;
16*2b4d8bb0SJiri Pirko u16 egress_tc_count;
17*2b4d8bb0SJiri Pirko };
18*2b4d8bb0SJiri Pirko
devlink_sb_pool_count(struct devlink_sb * devlink_sb)19*2b4d8bb0SJiri Pirko static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
20*2b4d8bb0SJiri Pirko {
21*2b4d8bb0SJiri Pirko return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
22*2b4d8bb0SJiri Pirko }
23*2b4d8bb0SJiri Pirko
devlink_sb_get_by_index(struct devlink * devlink,unsigned int sb_index)24*2b4d8bb0SJiri Pirko static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
25*2b4d8bb0SJiri Pirko unsigned int sb_index)
26*2b4d8bb0SJiri Pirko {
27*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
28*2b4d8bb0SJiri Pirko
29*2b4d8bb0SJiri Pirko list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
30*2b4d8bb0SJiri Pirko if (devlink_sb->index == sb_index)
31*2b4d8bb0SJiri Pirko return devlink_sb;
32*2b4d8bb0SJiri Pirko }
33*2b4d8bb0SJiri Pirko return NULL;
34*2b4d8bb0SJiri Pirko }
35*2b4d8bb0SJiri Pirko
devlink_sb_index_exists(struct devlink * devlink,unsigned int sb_index)36*2b4d8bb0SJiri Pirko static bool devlink_sb_index_exists(struct devlink *devlink,
37*2b4d8bb0SJiri Pirko unsigned int sb_index)
38*2b4d8bb0SJiri Pirko {
39*2b4d8bb0SJiri Pirko return devlink_sb_get_by_index(devlink, sb_index);
40*2b4d8bb0SJiri Pirko }
41*2b4d8bb0SJiri Pirko
devlink_sb_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)42*2b4d8bb0SJiri Pirko static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
43*2b4d8bb0SJiri Pirko struct nlattr **attrs)
44*2b4d8bb0SJiri Pirko {
45*2b4d8bb0SJiri Pirko if (attrs[DEVLINK_ATTR_SB_INDEX]) {
46*2b4d8bb0SJiri Pirko u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
47*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
48*2b4d8bb0SJiri Pirko
49*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
50*2b4d8bb0SJiri Pirko if (!devlink_sb)
51*2b4d8bb0SJiri Pirko return ERR_PTR(-ENODEV);
52*2b4d8bb0SJiri Pirko return devlink_sb;
53*2b4d8bb0SJiri Pirko }
54*2b4d8bb0SJiri Pirko return ERR_PTR(-EINVAL);
55*2b4d8bb0SJiri Pirko }
56*2b4d8bb0SJiri Pirko
devlink_sb_get_from_info(struct devlink * devlink,struct genl_info * info)57*2b4d8bb0SJiri Pirko static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
58*2b4d8bb0SJiri Pirko struct genl_info *info)
59*2b4d8bb0SJiri Pirko {
60*2b4d8bb0SJiri Pirko return devlink_sb_get_from_attrs(devlink, info->attrs);
61*2b4d8bb0SJiri Pirko }
62*2b4d8bb0SJiri Pirko
devlink_sb_pool_index_get_from_attrs(struct devlink_sb * devlink_sb,struct nlattr ** attrs,u16 * p_pool_index)63*2b4d8bb0SJiri Pirko static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
64*2b4d8bb0SJiri Pirko struct nlattr **attrs,
65*2b4d8bb0SJiri Pirko u16 *p_pool_index)
66*2b4d8bb0SJiri Pirko {
67*2b4d8bb0SJiri Pirko u16 val;
68*2b4d8bb0SJiri Pirko
69*2b4d8bb0SJiri Pirko if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
70*2b4d8bb0SJiri Pirko return -EINVAL;
71*2b4d8bb0SJiri Pirko
72*2b4d8bb0SJiri Pirko val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
73*2b4d8bb0SJiri Pirko if (val >= devlink_sb_pool_count(devlink_sb))
74*2b4d8bb0SJiri Pirko return -EINVAL;
75*2b4d8bb0SJiri Pirko *p_pool_index = val;
76*2b4d8bb0SJiri Pirko return 0;
77*2b4d8bb0SJiri Pirko }
78*2b4d8bb0SJiri Pirko
devlink_sb_pool_index_get_from_info(struct devlink_sb * devlink_sb,struct genl_info * info,u16 * p_pool_index)79*2b4d8bb0SJiri Pirko static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
80*2b4d8bb0SJiri Pirko struct genl_info *info,
81*2b4d8bb0SJiri Pirko u16 *p_pool_index)
82*2b4d8bb0SJiri Pirko {
83*2b4d8bb0SJiri Pirko return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
84*2b4d8bb0SJiri Pirko p_pool_index);
85*2b4d8bb0SJiri Pirko }
86*2b4d8bb0SJiri Pirko
87*2b4d8bb0SJiri Pirko static int
devlink_sb_pool_type_get_from_attrs(struct nlattr ** attrs,enum devlink_sb_pool_type * p_pool_type)88*2b4d8bb0SJiri Pirko devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
89*2b4d8bb0SJiri Pirko enum devlink_sb_pool_type *p_pool_type)
90*2b4d8bb0SJiri Pirko {
91*2b4d8bb0SJiri Pirko u8 val;
92*2b4d8bb0SJiri Pirko
93*2b4d8bb0SJiri Pirko if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
94*2b4d8bb0SJiri Pirko return -EINVAL;
95*2b4d8bb0SJiri Pirko
96*2b4d8bb0SJiri Pirko val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
97*2b4d8bb0SJiri Pirko if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
98*2b4d8bb0SJiri Pirko val != DEVLINK_SB_POOL_TYPE_EGRESS)
99*2b4d8bb0SJiri Pirko return -EINVAL;
100*2b4d8bb0SJiri Pirko *p_pool_type = val;
101*2b4d8bb0SJiri Pirko return 0;
102*2b4d8bb0SJiri Pirko }
103*2b4d8bb0SJiri Pirko
104*2b4d8bb0SJiri Pirko static int
devlink_sb_pool_type_get_from_info(struct genl_info * info,enum devlink_sb_pool_type * p_pool_type)105*2b4d8bb0SJiri Pirko devlink_sb_pool_type_get_from_info(struct genl_info *info,
106*2b4d8bb0SJiri Pirko enum devlink_sb_pool_type *p_pool_type)
107*2b4d8bb0SJiri Pirko {
108*2b4d8bb0SJiri Pirko return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
109*2b4d8bb0SJiri Pirko }
110*2b4d8bb0SJiri Pirko
111*2b4d8bb0SJiri Pirko static int
devlink_sb_th_type_get_from_attrs(struct nlattr ** attrs,enum devlink_sb_threshold_type * p_th_type)112*2b4d8bb0SJiri Pirko devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
113*2b4d8bb0SJiri Pirko enum devlink_sb_threshold_type *p_th_type)
114*2b4d8bb0SJiri Pirko {
115*2b4d8bb0SJiri Pirko u8 val;
116*2b4d8bb0SJiri Pirko
117*2b4d8bb0SJiri Pirko if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
118*2b4d8bb0SJiri Pirko return -EINVAL;
119*2b4d8bb0SJiri Pirko
120*2b4d8bb0SJiri Pirko val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
121*2b4d8bb0SJiri Pirko if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
122*2b4d8bb0SJiri Pirko val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
123*2b4d8bb0SJiri Pirko return -EINVAL;
124*2b4d8bb0SJiri Pirko *p_th_type = val;
125*2b4d8bb0SJiri Pirko return 0;
126*2b4d8bb0SJiri Pirko }
127*2b4d8bb0SJiri Pirko
128*2b4d8bb0SJiri Pirko static int
devlink_sb_th_type_get_from_info(struct genl_info * info,enum devlink_sb_threshold_type * p_th_type)129*2b4d8bb0SJiri Pirko devlink_sb_th_type_get_from_info(struct genl_info *info,
130*2b4d8bb0SJiri Pirko enum devlink_sb_threshold_type *p_th_type)
131*2b4d8bb0SJiri Pirko {
132*2b4d8bb0SJiri Pirko return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
133*2b4d8bb0SJiri Pirko }
134*2b4d8bb0SJiri Pirko
135*2b4d8bb0SJiri Pirko static int
devlink_sb_tc_index_get_from_attrs(struct devlink_sb * devlink_sb,struct nlattr ** attrs,enum devlink_sb_pool_type pool_type,u16 * p_tc_index)136*2b4d8bb0SJiri Pirko devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
137*2b4d8bb0SJiri Pirko struct nlattr **attrs,
138*2b4d8bb0SJiri Pirko enum devlink_sb_pool_type pool_type,
139*2b4d8bb0SJiri Pirko u16 *p_tc_index)
140*2b4d8bb0SJiri Pirko {
141*2b4d8bb0SJiri Pirko u16 val;
142*2b4d8bb0SJiri Pirko
143*2b4d8bb0SJiri Pirko if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
144*2b4d8bb0SJiri Pirko return -EINVAL;
145*2b4d8bb0SJiri Pirko
146*2b4d8bb0SJiri Pirko val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
147*2b4d8bb0SJiri Pirko if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
148*2b4d8bb0SJiri Pirko val >= devlink_sb->ingress_tc_count)
149*2b4d8bb0SJiri Pirko return -EINVAL;
150*2b4d8bb0SJiri Pirko if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
151*2b4d8bb0SJiri Pirko val >= devlink_sb->egress_tc_count)
152*2b4d8bb0SJiri Pirko return -EINVAL;
153*2b4d8bb0SJiri Pirko *p_tc_index = val;
154*2b4d8bb0SJiri Pirko return 0;
155*2b4d8bb0SJiri Pirko }
156*2b4d8bb0SJiri Pirko
157*2b4d8bb0SJiri Pirko static int
devlink_sb_tc_index_get_from_info(struct devlink_sb * devlink_sb,struct genl_info * info,enum devlink_sb_pool_type pool_type,u16 * p_tc_index)158*2b4d8bb0SJiri Pirko devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
159*2b4d8bb0SJiri Pirko struct genl_info *info,
160*2b4d8bb0SJiri Pirko enum devlink_sb_pool_type pool_type,
161*2b4d8bb0SJiri Pirko u16 *p_tc_index)
162*2b4d8bb0SJiri Pirko {
163*2b4d8bb0SJiri Pirko return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
164*2b4d8bb0SJiri Pirko pool_type, p_tc_index);
165*2b4d8bb0SJiri Pirko }
166*2b4d8bb0SJiri Pirko
devlink_nl_sb_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_sb * devlink_sb,enum devlink_command cmd,u32 portid,u32 seq,int flags)167*2b4d8bb0SJiri Pirko static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
168*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb,
169*2b4d8bb0SJiri Pirko enum devlink_command cmd, u32 portid,
170*2b4d8bb0SJiri Pirko u32 seq, int flags)
171*2b4d8bb0SJiri Pirko {
172*2b4d8bb0SJiri Pirko void *hdr;
173*2b4d8bb0SJiri Pirko
174*2b4d8bb0SJiri Pirko hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
175*2b4d8bb0SJiri Pirko if (!hdr)
176*2b4d8bb0SJiri Pirko return -EMSGSIZE;
177*2b4d8bb0SJiri Pirko
178*2b4d8bb0SJiri Pirko if (devlink_nl_put_handle(msg, devlink))
179*2b4d8bb0SJiri Pirko goto nla_put_failure;
180*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
181*2b4d8bb0SJiri Pirko goto nla_put_failure;
182*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
183*2b4d8bb0SJiri Pirko goto nla_put_failure;
184*2b4d8bb0SJiri Pirko if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
185*2b4d8bb0SJiri Pirko devlink_sb->ingress_pools_count))
186*2b4d8bb0SJiri Pirko goto nla_put_failure;
187*2b4d8bb0SJiri Pirko if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
188*2b4d8bb0SJiri Pirko devlink_sb->egress_pools_count))
189*2b4d8bb0SJiri Pirko goto nla_put_failure;
190*2b4d8bb0SJiri Pirko if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
191*2b4d8bb0SJiri Pirko devlink_sb->ingress_tc_count))
192*2b4d8bb0SJiri Pirko goto nla_put_failure;
193*2b4d8bb0SJiri Pirko if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
194*2b4d8bb0SJiri Pirko devlink_sb->egress_tc_count))
195*2b4d8bb0SJiri Pirko goto nla_put_failure;
196*2b4d8bb0SJiri Pirko
197*2b4d8bb0SJiri Pirko genlmsg_end(msg, hdr);
198*2b4d8bb0SJiri Pirko return 0;
199*2b4d8bb0SJiri Pirko
200*2b4d8bb0SJiri Pirko nla_put_failure:
201*2b4d8bb0SJiri Pirko genlmsg_cancel(msg, hdr);
202*2b4d8bb0SJiri Pirko return -EMSGSIZE;
203*2b4d8bb0SJiri Pirko }
204*2b4d8bb0SJiri Pirko
devlink_nl_sb_get_doit(struct sk_buff * skb,struct genl_info * info)205*2b4d8bb0SJiri Pirko int devlink_nl_sb_get_doit(struct sk_buff *skb, struct genl_info *info)
206*2b4d8bb0SJiri Pirko {
207*2b4d8bb0SJiri Pirko struct devlink *devlink = info->user_ptr[0];
208*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
209*2b4d8bb0SJiri Pirko struct sk_buff *msg;
210*2b4d8bb0SJiri Pirko int err;
211*2b4d8bb0SJiri Pirko
212*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_from_info(devlink, info);
213*2b4d8bb0SJiri Pirko if (IS_ERR(devlink_sb))
214*2b4d8bb0SJiri Pirko return PTR_ERR(devlink_sb);
215*2b4d8bb0SJiri Pirko
216*2b4d8bb0SJiri Pirko msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
217*2b4d8bb0SJiri Pirko if (!msg)
218*2b4d8bb0SJiri Pirko return -ENOMEM;
219*2b4d8bb0SJiri Pirko
220*2b4d8bb0SJiri Pirko err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
221*2b4d8bb0SJiri Pirko DEVLINK_CMD_SB_NEW,
222*2b4d8bb0SJiri Pirko info->snd_portid, info->snd_seq, 0);
223*2b4d8bb0SJiri Pirko if (err) {
224*2b4d8bb0SJiri Pirko nlmsg_free(msg);
225*2b4d8bb0SJiri Pirko return err;
226*2b4d8bb0SJiri Pirko }
227*2b4d8bb0SJiri Pirko
228*2b4d8bb0SJiri Pirko return genlmsg_reply(msg, info);
229*2b4d8bb0SJiri Pirko }
230*2b4d8bb0SJiri Pirko
231*2b4d8bb0SJiri Pirko static int
devlink_nl_sb_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)232*2b4d8bb0SJiri Pirko devlink_nl_sb_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
233*2b4d8bb0SJiri Pirko struct netlink_callback *cb, int flags)
234*2b4d8bb0SJiri Pirko {
235*2b4d8bb0SJiri Pirko struct devlink_nl_dump_state *state = devlink_dump_state(cb);
236*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
237*2b4d8bb0SJiri Pirko int idx = 0;
238*2b4d8bb0SJiri Pirko int err = 0;
239*2b4d8bb0SJiri Pirko
240*2b4d8bb0SJiri Pirko list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
241*2b4d8bb0SJiri Pirko if (idx < state->idx) {
242*2b4d8bb0SJiri Pirko idx++;
243*2b4d8bb0SJiri Pirko continue;
244*2b4d8bb0SJiri Pirko }
245*2b4d8bb0SJiri Pirko err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
246*2b4d8bb0SJiri Pirko DEVLINK_CMD_SB_NEW,
247*2b4d8bb0SJiri Pirko NETLINK_CB(cb->skb).portid,
248*2b4d8bb0SJiri Pirko cb->nlh->nlmsg_seq, flags);
249*2b4d8bb0SJiri Pirko if (err) {
250*2b4d8bb0SJiri Pirko state->idx = idx;
251*2b4d8bb0SJiri Pirko break;
252*2b4d8bb0SJiri Pirko }
253*2b4d8bb0SJiri Pirko idx++;
254*2b4d8bb0SJiri Pirko }
255*2b4d8bb0SJiri Pirko
256*2b4d8bb0SJiri Pirko return err;
257*2b4d8bb0SJiri Pirko }
258*2b4d8bb0SJiri Pirko
devlink_nl_sb_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)259*2b4d8bb0SJiri Pirko int devlink_nl_sb_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
260*2b4d8bb0SJiri Pirko {
261*2b4d8bb0SJiri Pirko return devlink_nl_dumpit(skb, cb, devlink_nl_sb_get_dump_one);
262*2b4d8bb0SJiri Pirko }
263*2b4d8bb0SJiri Pirko
devlink_nl_sb_pool_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_sb * devlink_sb,u16 pool_index,enum devlink_command cmd,u32 portid,u32 seq,int flags)264*2b4d8bb0SJiri Pirko static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
265*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb,
266*2b4d8bb0SJiri Pirko u16 pool_index, enum devlink_command cmd,
267*2b4d8bb0SJiri Pirko u32 portid, u32 seq, int flags)
268*2b4d8bb0SJiri Pirko {
269*2b4d8bb0SJiri Pirko struct devlink_sb_pool_info pool_info;
270*2b4d8bb0SJiri Pirko void *hdr;
271*2b4d8bb0SJiri Pirko int err;
272*2b4d8bb0SJiri Pirko
273*2b4d8bb0SJiri Pirko err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
274*2b4d8bb0SJiri Pirko pool_index, &pool_info);
275*2b4d8bb0SJiri Pirko if (err)
276*2b4d8bb0SJiri Pirko return err;
277*2b4d8bb0SJiri Pirko
278*2b4d8bb0SJiri Pirko hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
279*2b4d8bb0SJiri Pirko if (!hdr)
280*2b4d8bb0SJiri Pirko return -EMSGSIZE;
281*2b4d8bb0SJiri Pirko
282*2b4d8bb0SJiri Pirko if (devlink_nl_put_handle(msg, devlink))
283*2b4d8bb0SJiri Pirko goto nla_put_failure;
284*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
285*2b4d8bb0SJiri Pirko goto nla_put_failure;
286*2b4d8bb0SJiri Pirko if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
287*2b4d8bb0SJiri Pirko goto nla_put_failure;
288*2b4d8bb0SJiri Pirko if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
289*2b4d8bb0SJiri Pirko goto nla_put_failure;
290*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
291*2b4d8bb0SJiri Pirko goto nla_put_failure;
292*2b4d8bb0SJiri Pirko if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
293*2b4d8bb0SJiri Pirko pool_info.threshold_type))
294*2b4d8bb0SJiri Pirko goto nla_put_failure;
295*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE,
296*2b4d8bb0SJiri Pirko pool_info.cell_size))
297*2b4d8bb0SJiri Pirko goto nla_put_failure;
298*2b4d8bb0SJiri Pirko
299*2b4d8bb0SJiri Pirko genlmsg_end(msg, hdr);
300*2b4d8bb0SJiri Pirko return 0;
301*2b4d8bb0SJiri Pirko
302*2b4d8bb0SJiri Pirko nla_put_failure:
303*2b4d8bb0SJiri Pirko genlmsg_cancel(msg, hdr);
304*2b4d8bb0SJiri Pirko return -EMSGSIZE;
305*2b4d8bb0SJiri Pirko }
306*2b4d8bb0SJiri Pirko
devlink_nl_sb_pool_get_doit(struct sk_buff * skb,struct genl_info * info)307*2b4d8bb0SJiri Pirko int devlink_nl_sb_pool_get_doit(struct sk_buff *skb, struct genl_info *info)
308*2b4d8bb0SJiri Pirko {
309*2b4d8bb0SJiri Pirko struct devlink *devlink = info->user_ptr[0];
310*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
311*2b4d8bb0SJiri Pirko struct sk_buff *msg;
312*2b4d8bb0SJiri Pirko u16 pool_index;
313*2b4d8bb0SJiri Pirko int err;
314*2b4d8bb0SJiri Pirko
315*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_from_info(devlink, info);
316*2b4d8bb0SJiri Pirko if (IS_ERR(devlink_sb))
317*2b4d8bb0SJiri Pirko return PTR_ERR(devlink_sb);
318*2b4d8bb0SJiri Pirko
319*2b4d8bb0SJiri Pirko err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
320*2b4d8bb0SJiri Pirko &pool_index);
321*2b4d8bb0SJiri Pirko if (err)
322*2b4d8bb0SJiri Pirko return err;
323*2b4d8bb0SJiri Pirko
324*2b4d8bb0SJiri Pirko if (!devlink->ops->sb_pool_get)
325*2b4d8bb0SJiri Pirko return -EOPNOTSUPP;
326*2b4d8bb0SJiri Pirko
327*2b4d8bb0SJiri Pirko msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
328*2b4d8bb0SJiri Pirko if (!msg)
329*2b4d8bb0SJiri Pirko return -ENOMEM;
330*2b4d8bb0SJiri Pirko
331*2b4d8bb0SJiri Pirko err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
332*2b4d8bb0SJiri Pirko DEVLINK_CMD_SB_POOL_NEW,
333*2b4d8bb0SJiri Pirko info->snd_portid, info->snd_seq, 0);
334*2b4d8bb0SJiri Pirko if (err) {
335*2b4d8bb0SJiri Pirko nlmsg_free(msg);
336*2b4d8bb0SJiri Pirko return err;
337*2b4d8bb0SJiri Pirko }
338*2b4d8bb0SJiri Pirko
339*2b4d8bb0SJiri Pirko return genlmsg_reply(msg, info);
340*2b4d8bb0SJiri Pirko }
341*2b4d8bb0SJiri Pirko
__sb_pool_get_dumpit(struct sk_buff * msg,int start,int * p_idx,struct devlink * devlink,struct devlink_sb * devlink_sb,u32 portid,u32 seq,int flags)342*2b4d8bb0SJiri Pirko static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
343*2b4d8bb0SJiri Pirko struct devlink *devlink,
344*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb,
345*2b4d8bb0SJiri Pirko u32 portid, u32 seq, int flags)
346*2b4d8bb0SJiri Pirko {
347*2b4d8bb0SJiri Pirko u16 pool_count = devlink_sb_pool_count(devlink_sb);
348*2b4d8bb0SJiri Pirko u16 pool_index;
349*2b4d8bb0SJiri Pirko int err;
350*2b4d8bb0SJiri Pirko
351*2b4d8bb0SJiri Pirko for (pool_index = 0; pool_index < pool_count; pool_index++) {
352*2b4d8bb0SJiri Pirko if (*p_idx < start) {
353*2b4d8bb0SJiri Pirko (*p_idx)++;
354*2b4d8bb0SJiri Pirko continue;
355*2b4d8bb0SJiri Pirko }
356*2b4d8bb0SJiri Pirko err = devlink_nl_sb_pool_fill(msg, devlink,
357*2b4d8bb0SJiri Pirko devlink_sb,
358*2b4d8bb0SJiri Pirko pool_index,
359*2b4d8bb0SJiri Pirko DEVLINK_CMD_SB_POOL_NEW,
360*2b4d8bb0SJiri Pirko portid, seq, flags);
361*2b4d8bb0SJiri Pirko if (err)
362*2b4d8bb0SJiri Pirko return err;
363*2b4d8bb0SJiri Pirko (*p_idx)++;
364*2b4d8bb0SJiri Pirko }
365*2b4d8bb0SJiri Pirko return 0;
366*2b4d8bb0SJiri Pirko }
367*2b4d8bb0SJiri Pirko
368*2b4d8bb0SJiri Pirko static int
devlink_nl_sb_pool_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)369*2b4d8bb0SJiri Pirko devlink_nl_sb_pool_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
370*2b4d8bb0SJiri Pirko struct netlink_callback *cb, int flags)
371*2b4d8bb0SJiri Pirko {
372*2b4d8bb0SJiri Pirko struct devlink_nl_dump_state *state = devlink_dump_state(cb);
373*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
374*2b4d8bb0SJiri Pirko int err = 0;
375*2b4d8bb0SJiri Pirko int idx = 0;
376*2b4d8bb0SJiri Pirko
377*2b4d8bb0SJiri Pirko if (!devlink->ops->sb_pool_get)
378*2b4d8bb0SJiri Pirko return 0;
379*2b4d8bb0SJiri Pirko
380*2b4d8bb0SJiri Pirko list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
381*2b4d8bb0SJiri Pirko err = __sb_pool_get_dumpit(msg, state->idx, &idx,
382*2b4d8bb0SJiri Pirko devlink, devlink_sb,
383*2b4d8bb0SJiri Pirko NETLINK_CB(cb->skb).portid,
384*2b4d8bb0SJiri Pirko cb->nlh->nlmsg_seq, flags);
385*2b4d8bb0SJiri Pirko if (err == -EOPNOTSUPP) {
386*2b4d8bb0SJiri Pirko err = 0;
387*2b4d8bb0SJiri Pirko } else if (err) {
388*2b4d8bb0SJiri Pirko state->idx = idx;
389*2b4d8bb0SJiri Pirko break;
390*2b4d8bb0SJiri Pirko }
391*2b4d8bb0SJiri Pirko }
392*2b4d8bb0SJiri Pirko
393*2b4d8bb0SJiri Pirko return err;
394*2b4d8bb0SJiri Pirko }
395*2b4d8bb0SJiri Pirko
devlink_nl_sb_pool_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)396*2b4d8bb0SJiri Pirko int devlink_nl_sb_pool_get_dumpit(struct sk_buff *skb,
397*2b4d8bb0SJiri Pirko struct netlink_callback *cb)
398*2b4d8bb0SJiri Pirko {
399*2b4d8bb0SJiri Pirko return devlink_nl_dumpit(skb, cb, devlink_nl_sb_pool_get_dump_one);
400*2b4d8bb0SJiri Pirko }
401*2b4d8bb0SJiri Pirko
devlink_sb_pool_set(struct devlink * devlink,unsigned int sb_index,u16 pool_index,u32 size,enum devlink_sb_threshold_type threshold_type,struct netlink_ext_ack * extack)402*2b4d8bb0SJiri Pirko static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
403*2b4d8bb0SJiri Pirko u16 pool_index, u32 size,
404*2b4d8bb0SJiri Pirko enum devlink_sb_threshold_type threshold_type,
405*2b4d8bb0SJiri Pirko struct netlink_ext_ack *extack)
406*2b4d8bb0SJiri Pirko
407*2b4d8bb0SJiri Pirko {
408*2b4d8bb0SJiri Pirko const struct devlink_ops *ops = devlink->ops;
409*2b4d8bb0SJiri Pirko
410*2b4d8bb0SJiri Pirko if (ops->sb_pool_set)
411*2b4d8bb0SJiri Pirko return ops->sb_pool_set(devlink, sb_index, pool_index,
412*2b4d8bb0SJiri Pirko size, threshold_type, extack);
413*2b4d8bb0SJiri Pirko return -EOPNOTSUPP;
414*2b4d8bb0SJiri Pirko }
415*2b4d8bb0SJiri Pirko
devlink_nl_cmd_sb_pool_set_doit(struct sk_buff * skb,struct genl_info * info)416*2b4d8bb0SJiri Pirko int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, struct genl_info *info)
417*2b4d8bb0SJiri Pirko {
418*2b4d8bb0SJiri Pirko struct devlink *devlink = info->user_ptr[0];
419*2b4d8bb0SJiri Pirko enum devlink_sb_threshold_type threshold_type;
420*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
421*2b4d8bb0SJiri Pirko u16 pool_index;
422*2b4d8bb0SJiri Pirko u32 size;
423*2b4d8bb0SJiri Pirko int err;
424*2b4d8bb0SJiri Pirko
425*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_from_info(devlink, info);
426*2b4d8bb0SJiri Pirko if (IS_ERR(devlink_sb))
427*2b4d8bb0SJiri Pirko return PTR_ERR(devlink_sb);
428*2b4d8bb0SJiri Pirko
429*2b4d8bb0SJiri Pirko err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
430*2b4d8bb0SJiri Pirko &pool_index);
431*2b4d8bb0SJiri Pirko if (err)
432*2b4d8bb0SJiri Pirko return err;
433*2b4d8bb0SJiri Pirko
434*2b4d8bb0SJiri Pirko err = devlink_sb_th_type_get_from_info(info, &threshold_type);
435*2b4d8bb0SJiri Pirko if (err)
436*2b4d8bb0SJiri Pirko return err;
437*2b4d8bb0SJiri Pirko
438*2b4d8bb0SJiri Pirko if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_POOL_SIZE))
439*2b4d8bb0SJiri Pirko return -EINVAL;
440*2b4d8bb0SJiri Pirko
441*2b4d8bb0SJiri Pirko size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
442*2b4d8bb0SJiri Pirko return devlink_sb_pool_set(devlink, devlink_sb->index,
443*2b4d8bb0SJiri Pirko pool_index, size, threshold_type,
444*2b4d8bb0SJiri Pirko info->extack);
445*2b4d8bb0SJiri Pirko }
446*2b4d8bb0SJiri Pirko
devlink_nl_sb_port_pool_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_port * devlink_port,struct devlink_sb * devlink_sb,u16 pool_index,enum devlink_command cmd,u32 portid,u32 seq,int flags)447*2b4d8bb0SJiri Pirko static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
448*2b4d8bb0SJiri Pirko struct devlink *devlink,
449*2b4d8bb0SJiri Pirko struct devlink_port *devlink_port,
450*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb,
451*2b4d8bb0SJiri Pirko u16 pool_index,
452*2b4d8bb0SJiri Pirko enum devlink_command cmd,
453*2b4d8bb0SJiri Pirko u32 portid, u32 seq, int flags)
454*2b4d8bb0SJiri Pirko {
455*2b4d8bb0SJiri Pirko const struct devlink_ops *ops = devlink->ops;
456*2b4d8bb0SJiri Pirko u32 threshold;
457*2b4d8bb0SJiri Pirko void *hdr;
458*2b4d8bb0SJiri Pirko int err;
459*2b4d8bb0SJiri Pirko
460*2b4d8bb0SJiri Pirko err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
461*2b4d8bb0SJiri Pirko pool_index, &threshold);
462*2b4d8bb0SJiri Pirko if (err)
463*2b4d8bb0SJiri Pirko return err;
464*2b4d8bb0SJiri Pirko
465*2b4d8bb0SJiri Pirko hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
466*2b4d8bb0SJiri Pirko if (!hdr)
467*2b4d8bb0SJiri Pirko return -EMSGSIZE;
468*2b4d8bb0SJiri Pirko
469*2b4d8bb0SJiri Pirko if (devlink_nl_put_handle(msg, devlink))
470*2b4d8bb0SJiri Pirko goto nla_put_failure;
471*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
472*2b4d8bb0SJiri Pirko goto nla_put_failure;
473*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
474*2b4d8bb0SJiri Pirko goto nla_put_failure;
475*2b4d8bb0SJiri Pirko if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
476*2b4d8bb0SJiri Pirko goto nla_put_failure;
477*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
478*2b4d8bb0SJiri Pirko goto nla_put_failure;
479*2b4d8bb0SJiri Pirko
480*2b4d8bb0SJiri Pirko if (ops->sb_occ_port_pool_get) {
481*2b4d8bb0SJiri Pirko u32 cur;
482*2b4d8bb0SJiri Pirko u32 max;
483*2b4d8bb0SJiri Pirko
484*2b4d8bb0SJiri Pirko err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
485*2b4d8bb0SJiri Pirko pool_index, &cur, &max);
486*2b4d8bb0SJiri Pirko if (err && err != -EOPNOTSUPP)
487*2b4d8bb0SJiri Pirko goto sb_occ_get_failure;
488*2b4d8bb0SJiri Pirko if (!err) {
489*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
490*2b4d8bb0SJiri Pirko goto nla_put_failure;
491*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
492*2b4d8bb0SJiri Pirko goto nla_put_failure;
493*2b4d8bb0SJiri Pirko }
494*2b4d8bb0SJiri Pirko }
495*2b4d8bb0SJiri Pirko
496*2b4d8bb0SJiri Pirko genlmsg_end(msg, hdr);
497*2b4d8bb0SJiri Pirko return 0;
498*2b4d8bb0SJiri Pirko
499*2b4d8bb0SJiri Pirko nla_put_failure:
500*2b4d8bb0SJiri Pirko err = -EMSGSIZE;
501*2b4d8bb0SJiri Pirko sb_occ_get_failure:
502*2b4d8bb0SJiri Pirko genlmsg_cancel(msg, hdr);
503*2b4d8bb0SJiri Pirko return err;
504*2b4d8bb0SJiri Pirko }
505*2b4d8bb0SJiri Pirko
devlink_nl_sb_port_pool_get_doit(struct sk_buff * skb,struct genl_info * info)506*2b4d8bb0SJiri Pirko int devlink_nl_sb_port_pool_get_doit(struct sk_buff *skb,
507*2b4d8bb0SJiri Pirko struct genl_info *info)
508*2b4d8bb0SJiri Pirko {
509*2b4d8bb0SJiri Pirko struct devlink_port *devlink_port = info->user_ptr[1];
510*2b4d8bb0SJiri Pirko struct devlink *devlink = devlink_port->devlink;
511*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
512*2b4d8bb0SJiri Pirko struct sk_buff *msg;
513*2b4d8bb0SJiri Pirko u16 pool_index;
514*2b4d8bb0SJiri Pirko int err;
515*2b4d8bb0SJiri Pirko
516*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_from_info(devlink, info);
517*2b4d8bb0SJiri Pirko if (IS_ERR(devlink_sb))
518*2b4d8bb0SJiri Pirko return PTR_ERR(devlink_sb);
519*2b4d8bb0SJiri Pirko
520*2b4d8bb0SJiri Pirko err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
521*2b4d8bb0SJiri Pirko &pool_index);
522*2b4d8bb0SJiri Pirko if (err)
523*2b4d8bb0SJiri Pirko return err;
524*2b4d8bb0SJiri Pirko
525*2b4d8bb0SJiri Pirko if (!devlink->ops->sb_port_pool_get)
526*2b4d8bb0SJiri Pirko return -EOPNOTSUPP;
527*2b4d8bb0SJiri Pirko
528*2b4d8bb0SJiri Pirko msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
529*2b4d8bb0SJiri Pirko if (!msg)
530*2b4d8bb0SJiri Pirko return -ENOMEM;
531*2b4d8bb0SJiri Pirko
532*2b4d8bb0SJiri Pirko err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
533*2b4d8bb0SJiri Pirko devlink_sb, pool_index,
534*2b4d8bb0SJiri Pirko DEVLINK_CMD_SB_PORT_POOL_NEW,
535*2b4d8bb0SJiri Pirko info->snd_portid, info->snd_seq, 0);
536*2b4d8bb0SJiri Pirko if (err) {
537*2b4d8bb0SJiri Pirko nlmsg_free(msg);
538*2b4d8bb0SJiri Pirko return err;
539*2b4d8bb0SJiri Pirko }
540*2b4d8bb0SJiri Pirko
541*2b4d8bb0SJiri Pirko return genlmsg_reply(msg, info);
542*2b4d8bb0SJiri Pirko }
543*2b4d8bb0SJiri Pirko
__sb_port_pool_get_dumpit(struct sk_buff * msg,int start,int * p_idx,struct devlink * devlink,struct devlink_sb * devlink_sb,u32 portid,u32 seq,int flags)544*2b4d8bb0SJiri Pirko static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
545*2b4d8bb0SJiri Pirko struct devlink *devlink,
546*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb,
547*2b4d8bb0SJiri Pirko u32 portid, u32 seq, int flags)
548*2b4d8bb0SJiri Pirko {
549*2b4d8bb0SJiri Pirko struct devlink_port *devlink_port;
550*2b4d8bb0SJiri Pirko u16 pool_count = devlink_sb_pool_count(devlink_sb);
551*2b4d8bb0SJiri Pirko unsigned long port_index;
552*2b4d8bb0SJiri Pirko u16 pool_index;
553*2b4d8bb0SJiri Pirko int err;
554*2b4d8bb0SJiri Pirko
555*2b4d8bb0SJiri Pirko xa_for_each(&devlink->ports, port_index, devlink_port) {
556*2b4d8bb0SJiri Pirko for (pool_index = 0; pool_index < pool_count; pool_index++) {
557*2b4d8bb0SJiri Pirko if (*p_idx < start) {
558*2b4d8bb0SJiri Pirko (*p_idx)++;
559*2b4d8bb0SJiri Pirko continue;
560*2b4d8bb0SJiri Pirko }
561*2b4d8bb0SJiri Pirko err = devlink_nl_sb_port_pool_fill(msg, devlink,
562*2b4d8bb0SJiri Pirko devlink_port,
563*2b4d8bb0SJiri Pirko devlink_sb,
564*2b4d8bb0SJiri Pirko pool_index,
565*2b4d8bb0SJiri Pirko DEVLINK_CMD_SB_PORT_POOL_NEW,
566*2b4d8bb0SJiri Pirko portid, seq, flags);
567*2b4d8bb0SJiri Pirko if (err)
568*2b4d8bb0SJiri Pirko return err;
569*2b4d8bb0SJiri Pirko (*p_idx)++;
570*2b4d8bb0SJiri Pirko }
571*2b4d8bb0SJiri Pirko }
572*2b4d8bb0SJiri Pirko return 0;
573*2b4d8bb0SJiri Pirko }
574*2b4d8bb0SJiri Pirko
575*2b4d8bb0SJiri Pirko static int
devlink_nl_sb_port_pool_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)576*2b4d8bb0SJiri Pirko devlink_nl_sb_port_pool_get_dump_one(struct sk_buff *msg,
577*2b4d8bb0SJiri Pirko struct devlink *devlink,
578*2b4d8bb0SJiri Pirko struct netlink_callback *cb, int flags)
579*2b4d8bb0SJiri Pirko {
580*2b4d8bb0SJiri Pirko struct devlink_nl_dump_state *state = devlink_dump_state(cb);
581*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
582*2b4d8bb0SJiri Pirko int idx = 0;
583*2b4d8bb0SJiri Pirko int err = 0;
584*2b4d8bb0SJiri Pirko
585*2b4d8bb0SJiri Pirko if (!devlink->ops->sb_port_pool_get)
586*2b4d8bb0SJiri Pirko return 0;
587*2b4d8bb0SJiri Pirko
588*2b4d8bb0SJiri Pirko list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
589*2b4d8bb0SJiri Pirko err = __sb_port_pool_get_dumpit(msg, state->idx, &idx,
590*2b4d8bb0SJiri Pirko devlink, devlink_sb,
591*2b4d8bb0SJiri Pirko NETLINK_CB(cb->skb).portid,
592*2b4d8bb0SJiri Pirko cb->nlh->nlmsg_seq, flags);
593*2b4d8bb0SJiri Pirko if (err == -EOPNOTSUPP) {
594*2b4d8bb0SJiri Pirko err = 0;
595*2b4d8bb0SJiri Pirko } else if (err) {
596*2b4d8bb0SJiri Pirko state->idx = idx;
597*2b4d8bb0SJiri Pirko break;
598*2b4d8bb0SJiri Pirko }
599*2b4d8bb0SJiri Pirko }
600*2b4d8bb0SJiri Pirko
601*2b4d8bb0SJiri Pirko return err;
602*2b4d8bb0SJiri Pirko }
603*2b4d8bb0SJiri Pirko
devlink_nl_sb_port_pool_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)604*2b4d8bb0SJiri Pirko int devlink_nl_sb_port_pool_get_dumpit(struct sk_buff *skb,
605*2b4d8bb0SJiri Pirko struct netlink_callback *cb)
606*2b4d8bb0SJiri Pirko {
607*2b4d8bb0SJiri Pirko return devlink_nl_dumpit(skb, cb, devlink_nl_sb_port_pool_get_dump_one);
608*2b4d8bb0SJiri Pirko }
609*2b4d8bb0SJiri Pirko
devlink_sb_port_pool_set(struct devlink_port * devlink_port,unsigned int sb_index,u16 pool_index,u32 threshold,struct netlink_ext_ack * extack)610*2b4d8bb0SJiri Pirko static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
611*2b4d8bb0SJiri Pirko unsigned int sb_index, u16 pool_index,
612*2b4d8bb0SJiri Pirko u32 threshold,
613*2b4d8bb0SJiri Pirko struct netlink_ext_ack *extack)
614*2b4d8bb0SJiri Pirko
615*2b4d8bb0SJiri Pirko {
616*2b4d8bb0SJiri Pirko const struct devlink_ops *ops = devlink_port->devlink->ops;
617*2b4d8bb0SJiri Pirko
618*2b4d8bb0SJiri Pirko if (ops->sb_port_pool_set)
619*2b4d8bb0SJiri Pirko return ops->sb_port_pool_set(devlink_port, sb_index,
620*2b4d8bb0SJiri Pirko pool_index, threshold, extack);
621*2b4d8bb0SJiri Pirko return -EOPNOTSUPP;
622*2b4d8bb0SJiri Pirko }
623*2b4d8bb0SJiri Pirko
devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff * skb,struct genl_info * info)624*2b4d8bb0SJiri Pirko int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
625*2b4d8bb0SJiri Pirko struct genl_info *info)
626*2b4d8bb0SJiri Pirko {
627*2b4d8bb0SJiri Pirko struct devlink_port *devlink_port = info->user_ptr[1];
628*2b4d8bb0SJiri Pirko struct devlink *devlink = info->user_ptr[0];
629*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
630*2b4d8bb0SJiri Pirko u16 pool_index;
631*2b4d8bb0SJiri Pirko u32 threshold;
632*2b4d8bb0SJiri Pirko int err;
633*2b4d8bb0SJiri Pirko
634*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_from_info(devlink, info);
635*2b4d8bb0SJiri Pirko if (IS_ERR(devlink_sb))
636*2b4d8bb0SJiri Pirko return PTR_ERR(devlink_sb);
637*2b4d8bb0SJiri Pirko
638*2b4d8bb0SJiri Pirko err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
639*2b4d8bb0SJiri Pirko &pool_index);
640*2b4d8bb0SJiri Pirko if (err)
641*2b4d8bb0SJiri Pirko return err;
642*2b4d8bb0SJiri Pirko
643*2b4d8bb0SJiri Pirko if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD))
644*2b4d8bb0SJiri Pirko return -EINVAL;
645*2b4d8bb0SJiri Pirko
646*2b4d8bb0SJiri Pirko threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
647*2b4d8bb0SJiri Pirko return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
648*2b4d8bb0SJiri Pirko pool_index, threshold, info->extack);
649*2b4d8bb0SJiri Pirko }
650*2b4d8bb0SJiri Pirko
651*2b4d8bb0SJiri Pirko static int
devlink_nl_sb_tc_pool_bind_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_port * devlink_port,struct devlink_sb * devlink_sb,u16 tc_index,enum devlink_sb_pool_type pool_type,enum devlink_command cmd,u32 portid,u32 seq,int flags)652*2b4d8bb0SJiri Pirko devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
653*2b4d8bb0SJiri Pirko struct devlink_port *devlink_port,
654*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb, u16 tc_index,
655*2b4d8bb0SJiri Pirko enum devlink_sb_pool_type pool_type,
656*2b4d8bb0SJiri Pirko enum devlink_command cmd,
657*2b4d8bb0SJiri Pirko u32 portid, u32 seq, int flags)
658*2b4d8bb0SJiri Pirko {
659*2b4d8bb0SJiri Pirko const struct devlink_ops *ops = devlink->ops;
660*2b4d8bb0SJiri Pirko u16 pool_index;
661*2b4d8bb0SJiri Pirko u32 threshold;
662*2b4d8bb0SJiri Pirko void *hdr;
663*2b4d8bb0SJiri Pirko int err;
664*2b4d8bb0SJiri Pirko
665*2b4d8bb0SJiri Pirko err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
666*2b4d8bb0SJiri Pirko tc_index, pool_type,
667*2b4d8bb0SJiri Pirko &pool_index, &threshold);
668*2b4d8bb0SJiri Pirko if (err)
669*2b4d8bb0SJiri Pirko return err;
670*2b4d8bb0SJiri Pirko
671*2b4d8bb0SJiri Pirko hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
672*2b4d8bb0SJiri Pirko if (!hdr)
673*2b4d8bb0SJiri Pirko return -EMSGSIZE;
674*2b4d8bb0SJiri Pirko
675*2b4d8bb0SJiri Pirko if (devlink_nl_put_handle(msg, devlink))
676*2b4d8bb0SJiri Pirko goto nla_put_failure;
677*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
678*2b4d8bb0SJiri Pirko goto nla_put_failure;
679*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
680*2b4d8bb0SJiri Pirko goto nla_put_failure;
681*2b4d8bb0SJiri Pirko if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
682*2b4d8bb0SJiri Pirko goto nla_put_failure;
683*2b4d8bb0SJiri Pirko if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
684*2b4d8bb0SJiri Pirko goto nla_put_failure;
685*2b4d8bb0SJiri Pirko if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
686*2b4d8bb0SJiri Pirko goto nla_put_failure;
687*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
688*2b4d8bb0SJiri Pirko goto nla_put_failure;
689*2b4d8bb0SJiri Pirko
690*2b4d8bb0SJiri Pirko if (ops->sb_occ_tc_port_bind_get) {
691*2b4d8bb0SJiri Pirko u32 cur;
692*2b4d8bb0SJiri Pirko u32 max;
693*2b4d8bb0SJiri Pirko
694*2b4d8bb0SJiri Pirko err = ops->sb_occ_tc_port_bind_get(devlink_port,
695*2b4d8bb0SJiri Pirko devlink_sb->index,
696*2b4d8bb0SJiri Pirko tc_index, pool_type,
697*2b4d8bb0SJiri Pirko &cur, &max);
698*2b4d8bb0SJiri Pirko if (err && err != -EOPNOTSUPP)
699*2b4d8bb0SJiri Pirko return err;
700*2b4d8bb0SJiri Pirko if (!err) {
701*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
702*2b4d8bb0SJiri Pirko goto nla_put_failure;
703*2b4d8bb0SJiri Pirko if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
704*2b4d8bb0SJiri Pirko goto nla_put_failure;
705*2b4d8bb0SJiri Pirko }
706*2b4d8bb0SJiri Pirko }
707*2b4d8bb0SJiri Pirko
708*2b4d8bb0SJiri Pirko genlmsg_end(msg, hdr);
709*2b4d8bb0SJiri Pirko return 0;
710*2b4d8bb0SJiri Pirko
711*2b4d8bb0SJiri Pirko nla_put_failure:
712*2b4d8bb0SJiri Pirko genlmsg_cancel(msg, hdr);
713*2b4d8bb0SJiri Pirko return -EMSGSIZE;
714*2b4d8bb0SJiri Pirko }
715*2b4d8bb0SJiri Pirko
devlink_nl_sb_tc_pool_bind_get_doit(struct sk_buff * skb,struct genl_info * info)716*2b4d8bb0SJiri Pirko int devlink_nl_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
717*2b4d8bb0SJiri Pirko struct genl_info *info)
718*2b4d8bb0SJiri Pirko {
719*2b4d8bb0SJiri Pirko struct devlink_port *devlink_port = info->user_ptr[1];
720*2b4d8bb0SJiri Pirko struct devlink *devlink = devlink_port->devlink;
721*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
722*2b4d8bb0SJiri Pirko struct sk_buff *msg;
723*2b4d8bb0SJiri Pirko enum devlink_sb_pool_type pool_type;
724*2b4d8bb0SJiri Pirko u16 tc_index;
725*2b4d8bb0SJiri Pirko int err;
726*2b4d8bb0SJiri Pirko
727*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_from_info(devlink, info);
728*2b4d8bb0SJiri Pirko if (IS_ERR(devlink_sb))
729*2b4d8bb0SJiri Pirko return PTR_ERR(devlink_sb);
730*2b4d8bb0SJiri Pirko
731*2b4d8bb0SJiri Pirko err = devlink_sb_pool_type_get_from_info(info, &pool_type);
732*2b4d8bb0SJiri Pirko if (err)
733*2b4d8bb0SJiri Pirko return err;
734*2b4d8bb0SJiri Pirko
735*2b4d8bb0SJiri Pirko err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
736*2b4d8bb0SJiri Pirko pool_type, &tc_index);
737*2b4d8bb0SJiri Pirko if (err)
738*2b4d8bb0SJiri Pirko return err;
739*2b4d8bb0SJiri Pirko
740*2b4d8bb0SJiri Pirko if (!devlink->ops->sb_tc_pool_bind_get)
741*2b4d8bb0SJiri Pirko return -EOPNOTSUPP;
742*2b4d8bb0SJiri Pirko
743*2b4d8bb0SJiri Pirko msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
744*2b4d8bb0SJiri Pirko if (!msg)
745*2b4d8bb0SJiri Pirko return -ENOMEM;
746*2b4d8bb0SJiri Pirko
747*2b4d8bb0SJiri Pirko err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
748*2b4d8bb0SJiri Pirko devlink_sb, tc_index, pool_type,
749*2b4d8bb0SJiri Pirko DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
750*2b4d8bb0SJiri Pirko info->snd_portid,
751*2b4d8bb0SJiri Pirko info->snd_seq, 0);
752*2b4d8bb0SJiri Pirko if (err) {
753*2b4d8bb0SJiri Pirko nlmsg_free(msg);
754*2b4d8bb0SJiri Pirko return err;
755*2b4d8bb0SJiri Pirko }
756*2b4d8bb0SJiri Pirko
757*2b4d8bb0SJiri Pirko return genlmsg_reply(msg, info);
758*2b4d8bb0SJiri Pirko }
759*2b4d8bb0SJiri Pirko
__sb_tc_pool_bind_get_dumpit(struct sk_buff * msg,int start,int * p_idx,struct devlink * devlink,struct devlink_sb * devlink_sb,u32 portid,u32 seq,int flags)760*2b4d8bb0SJiri Pirko static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
761*2b4d8bb0SJiri Pirko int start, int *p_idx,
762*2b4d8bb0SJiri Pirko struct devlink *devlink,
763*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb,
764*2b4d8bb0SJiri Pirko u32 portid, u32 seq, int flags)
765*2b4d8bb0SJiri Pirko {
766*2b4d8bb0SJiri Pirko struct devlink_port *devlink_port;
767*2b4d8bb0SJiri Pirko unsigned long port_index;
768*2b4d8bb0SJiri Pirko u16 tc_index;
769*2b4d8bb0SJiri Pirko int err;
770*2b4d8bb0SJiri Pirko
771*2b4d8bb0SJiri Pirko xa_for_each(&devlink->ports, port_index, devlink_port) {
772*2b4d8bb0SJiri Pirko for (tc_index = 0;
773*2b4d8bb0SJiri Pirko tc_index < devlink_sb->ingress_tc_count; tc_index++) {
774*2b4d8bb0SJiri Pirko if (*p_idx < start) {
775*2b4d8bb0SJiri Pirko (*p_idx)++;
776*2b4d8bb0SJiri Pirko continue;
777*2b4d8bb0SJiri Pirko }
778*2b4d8bb0SJiri Pirko err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
779*2b4d8bb0SJiri Pirko devlink_port,
780*2b4d8bb0SJiri Pirko devlink_sb,
781*2b4d8bb0SJiri Pirko tc_index,
782*2b4d8bb0SJiri Pirko DEVLINK_SB_POOL_TYPE_INGRESS,
783*2b4d8bb0SJiri Pirko DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
784*2b4d8bb0SJiri Pirko portid, seq,
785*2b4d8bb0SJiri Pirko flags);
786*2b4d8bb0SJiri Pirko if (err)
787*2b4d8bb0SJiri Pirko return err;
788*2b4d8bb0SJiri Pirko (*p_idx)++;
789*2b4d8bb0SJiri Pirko }
790*2b4d8bb0SJiri Pirko for (tc_index = 0;
791*2b4d8bb0SJiri Pirko tc_index < devlink_sb->egress_tc_count; tc_index++) {
792*2b4d8bb0SJiri Pirko if (*p_idx < start) {
793*2b4d8bb0SJiri Pirko (*p_idx)++;
794*2b4d8bb0SJiri Pirko continue;
795*2b4d8bb0SJiri Pirko }
796*2b4d8bb0SJiri Pirko err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
797*2b4d8bb0SJiri Pirko devlink_port,
798*2b4d8bb0SJiri Pirko devlink_sb,
799*2b4d8bb0SJiri Pirko tc_index,
800*2b4d8bb0SJiri Pirko DEVLINK_SB_POOL_TYPE_EGRESS,
801*2b4d8bb0SJiri Pirko DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
802*2b4d8bb0SJiri Pirko portid, seq,
803*2b4d8bb0SJiri Pirko flags);
804*2b4d8bb0SJiri Pirko if (err)
805*2b4d8bb0SJiri Pirko return err;
806*2b4d8bb0SJiri Pirko (*p_idx)++;
807*2b4d8bb0SJiri Pirko }
808*2b4d8bb0SJiri Pirko }
809*2b4d8bb0SJiri Pirko return 0;
810*2b4d8bb0SJiri Pirko }
811*2b4d8bb0SJiri Pirko
devlink_nl_sb_tc_pool_bind_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)812*2b4d8bb0SJiri Pirko static int devlink_nl_sb_tc_pool_bind_get_dump_one(struct sk_buff *msg,
813*2b4d8bb0SJiri Pirko struct devlink *devlink,
814*2b4d8bb0SJiri Pirko struct netlink_callback *cb,
815*2b4d8bb0SJiri Pirko int flags)
816*2b4d8bb0SJiri Pirko {
817*2b4d8bb0SJiri Pirko struct devlink_nl_dump_state *state = devlink_dump_state(cb);
818*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
819*2b4d8bb0SJiri Pirko int idx = 0;
820*2b4d8bb0SJiri Pirko int err = 0;
821*2b4d8bb0SJiri Pirko
822*2b4d8bb0SJiri Pirko if (!devlink->ops->sb_tc_pool_bind_get)
823*2b4d8bb0SJiri Pirko return 0;
824*2b4d8bb0SJiri Pirko
825*2b4d8bb0SJiri Pirko list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
826*2b4d8bb0SJiri Pirko err = __sb_tc_pool_bind_get_dumpit(msg, state->idx, &idx,
827*2b4d8bb0SJiri Pirko devlink, devlink_sb,
828*2b4d8bb0SJiri Pirko NETLINK_CB(cb->skb).portid,
829*2b4d8bb0SJiri Pirko cb->nlh->nlmsg_seq, flags);
830*2b4d8bb0SJiri Pirko if (err == -EOPNOTSUPP) {
831*2b4d8bb0SJiri Pirko err = 0;
832*2b4d8bb0SJiri Pirko } else if (err) {
833*2b4d8bb0SJiri Pirko state->idx = idx;
834*2b4d8bb0SJiri Pirko break;
835*2b4d8bb0SJiri Pirko }
836*2b4d8bb0SJiri Pirko }
837*2b4d8bb0SJiri Pirko
838*2b4d8bb0SJiri Pirko return err;
839*2b4d8bb0SJiri Pirko }
840*2b4d8bb0SJiri Pirko
devlink_nl_sb_tc_pool_bind_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)841*2b4d8bb0SJiri Pirko int devlink_nl_sb_tc_pool_bind_get_dumpit(struct sk_buff *skb,
842*2b4d8bb0SJiri Pirko struct netlink_callback *cb)
843*2b4d8bb0SJiri Pirko {
844*2b4d8bb0SJiri Pirko return devlink_nl_dumpit(skb, cb,
845*2b4d8bb0SJiri Pirko devlink_nl_sb_tc_pool_bind_get_dump_one);
846*2b4d8bb0SJiri Pirko }
847*2b4d8bb0SJiri Pirko
devlink_sb_tc_pool_bind_set(struct devlink_port * devlink_port,unsigned int sb_index,u16 tc_index,enum devlink_sb_pool_type pool_type,u16 pool_index,u32 threshold,struct netlink_ext_ack * extack)848*2b4d8bb0SJiri Pirko static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
849*2b4d8bb0SJiri Pirko unsigned int sb_index, u16 tc_index,
850*2b4d8bb0SJiri Pirko enum devlink_sb_pool_type pool_type,
851*2b4d8bb0SJiri Pirko u16 pool_index, u32 threshold,
852*2b4d8bb0SJiri Pirko struct netlink_ext_ack *extack)
853*2b4d8bb0SJiri Pirko
854*2b4d8bb0SJiri Pirko {
855*2b4d8bb0SJiri Pirko const struct devlink_ops *ops = devlink_port->devlink->ops;
856*2b4d8bb0SJiri Pirko
857*2b4d8bb0SJiri Pirko if (ops->sb_tc_pool_bind_set)
858*2b4d8bb0SJiri Pirko return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
859*2b4d8bb0SJiri Pirko tc_index, pool_type,
860*2b4d8bb0SJiri Pirko pool_index, threshold, extack);
861*2b4d8bb0SJiri Pirko return -EOPNOTSUPP;
862*2b4d8bb0SJiri Pirko }
863*2b4d8bb0SJiri Pirko
devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff * skb,struct genl_info * info)864*2b4d8bb0SJiri Pirko int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
865*2b4d8bb0SJiri Pirko struct genl_info *info)
866*2b4d8bb0SJiri Pirko {
867*2b4d8bb0SJiri Pirko struct devlink_port *devlink_port = info->user_ptr[1];
868*2b4d8bb0SJiri Pirko struct devlink *devlink = info->user_ptr[0];
869*2b4d8bb0SJiri Pirko enum devlink_sb_pool_type pool_type;
870*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
871*2b4d8bb0SJiri Pirko u16 tc_index;
872*2b4d8bb0SJiri Pirko u16 pool_index;
873*2b4d8bb0SJiri Pirko u32 threshold;
874*2b4d8bb0SJiri Pirko int err;
875*2b4d8bb0SJiri Pirko
876*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_from_info(devlink, info);
877*2b4d8bb0SJiri Pirko if (IS_ERR(devlink_sb))
878*2b4d8bb0SJiri Pirko return PTR_ERR(devlink_sb);
879*2b4d8bb0SJiri Pirko
880*2b4d8bb0SJiri Pirko err = devlink_sb_pool_type_get_from_info(info, &pool_type);
881*2b4d8bb0SJiri Pirko if (err)
882*2b4d8bb0SJiri Pirko return err;
883*2b4d8bb0SJiri Pirko
884*2b4d8bb0SJiri Pirko err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
885*2b4d8bb0SJiri Pirko pool_type, &tc_index);
886*2b4d8bb0SJiri Pirko if (err)
887*2b4d8bb0SJiri Pirko return err;
888*2b4d8bb0SJiri Pirko
889*2b4d8bb0SJiri Pirko err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
890*2b4d8bb0SJiri Pirko &pool_index);
891*2b4d8bb0SJiri Pirko if (err)
892*2b4d8bb0SJiri Pirko return err;
893*2b4d8bb0SJiri Pirko
894*2b4d8bb0SJiri Pirko if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD))
895*2b4d8bb0SJiri Pirko return -EINVAL;
896*2b4d8bb0SJiri Pirko
897*2b4d8bb0SJiri Pirko threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
898*2b4d8bb0SJiri Pirko return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
899*2b4d8bb0SJiri Pirko tc_index, pool_type,
900*2b4d8bb0SJiri Pirko pool_index, threshold, info->extack);
901*2b4d8bb0SJiri Pirko }
902*2b4d8bb0SJiri Pirko
devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff * skb,struct genl_info * info)903*2b4d8bb0SJiri Pirko int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
904*2b4d8bb0SJiri Pirko struct genl_info *info)
905*2b4d8bb0SJiri Pirko {
906*2b4d8bb0SJiri Pirko struct devlink *devlink = info->user_ptr[0];
907*2b4d8bb0SJiri Pirko const struct devlink_ops *ops = devlink->ops;
908*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
909*2b4d8bb0SJiri Pirko
910*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_from_info(devlink, info);
911*2b4d8bb0SJiri Pirko if (IS_ERR(devlink_sb))
912*2b4d8bb0SJiri Pirko return PTR_ERR(devlink_sb);
913*2b4d8bb0SJiri Pirko
914*2b4d8bb0SJiri Pirko if (ops->sb_occ_snapshot)
915*2b4d8bb0SJiri Pirko return ops->sb_occ_snapshot(devlink, devlink_sb->index);
916*2b4d8bb0SJiri Pirko return -EOPNOTSUPP;
917*2b4d8bb0SJiri Pirko }
918*2b4d8bb0SJiri Pirko
devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff * skb,struct genl_info * info)919*2b4d8bb0SJiri Pirko int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
920*2b4d8bb0SJiri Pirko struct genl_info *info)
921*2b4d8bb0SJiri Pirko {
922*2b4d8bb0SJiri Pirko struct devlink *devlink = info->user_ptr[0];
923*2b4d8bb0SJiri Pirko const struct devlink_ops *ops = devlink->ops;
924*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
925*2b4d8bb0SJiri Pirko
926*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_from_info(devlink, info);
927*2b4d8bb0SJiri Pirko if (IS_ERR(devlink_sb))
928*2b4d8bb0SJiri Pirko return PTR_ERR(devlink_sb);
929*2b4d8bb0SJiri Pirko
930*2b4d8bb0SJiri Pirko if (ops->sb_occ_max_clear)
931*2b4d8bb0SJiri Pirko return ops->sb_occ_max_clear(devlink, devlink_sb->index);
932*2b4d8bb0SJiri Pirko return -EOPNOTSUPP;
933*2b4d8bb0SJiri Pirko }
934*2b4d8bb0SJiri Pirko
devl_sb_register(struct devlink * devlink,unsigned int sb_index,u32 size,u16 ingress_pools_count,u16 egress_pools_count,u16 ingress_tc_count,u16 egress_tc_count)935*2b4d8bb0SJiri Pirko int devl_sb_register(struct devlink *devlink, unsigned int sb_index,
936*2b4d8bb0SJiri Pirko u32 size, u16 ingress_pools_count,
937*2b4d8bb0SJiri Pirko u16 egress_pools_count, u16 ingress_tc_count,
938*2b4d8bb0SJiri Pirko u16 egress_tc_count)
939*2b4d8bb0SJiri Pirko {
940*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
941*2b4d8bb0SJiri Pirko
942*2b4d8bb0SJiri Pirko lockdep_assert_held(&devlink->lock);
943*2b4d8bb0SJiri Pirko
944*2b4d8bb0SJiri Pirko if (devlink_sb_index_exists(devlink, sb_index))
945*2b4d8bb0SJiri Pirko return -EEXIST;
946*2b4d8bb0SJiri Pirko
947*2b4d8bb0SJiri Pirko devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
948*2b4d8bb0SJiri Pirko if (!devlink_sb)
949*2b4d8bb0SJiri Pirko return -ENOMEM;
950*2b4d8bb0SJiri Pirko devlink_sb->index = sb_index;
951*2b4d8bb0SJiri Pirko devlink_sb->size = size;
952*2b4d8bb0SJiri Pirko devlink_sb->ingress_pools_count = ingress_pools_count;
953*2b4d8bb0SJiri Pirko devlink_sb->egress_pools_count = egress_pools_count;
954*2b4d8bb0SJiri Pirko devlink_sb->ingress_tc_count = ingress_tc_count;
955*2b4d8bb0SJiri Pirko devlink_sb->egress_tc_count = egress_tc_count;
956*2b4d8bb0SJiri Pirko list_add_tail(&devlink_sb->list, &devlink->sb_list);
957*2b4d8bb0SJiri Pirko return 0;
958*2b4d8bb0SJiri Pirko }
959*2b4d8bb0SJiri Pirko EXPORT_SYMBOL_GPL(devl_sb_register);
960*2b4d8bb0SJiri Pirko
devlink_sb_register(struct devlink * devlink,unsigned int sb_index,u32 size,u16 ingress_pools_count,u16 egress_pools_count,u16 ingress_tc_count,u16 egress_tc_count)961*2b4d8bb0SJiri Pirko int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
962*2b4d8bb0SJiri Pirko u32 size, u16 ingress_pools_count,
963*2b4d8bb0SJiri Pirko u16 egress_pools_count, u16 ingress_tc_count,
964*2b4d8bb0SJiri Pirko u16 egress_tc_count)
965*2b4d8bb0SJiri Pirko {
966*2b4d8bb0SJiri Pirko int err;
967*2b4d8bb0SJiri Pirko
968*2b4d8bb0SJiri Pirko devl_lock(devlink);
969*2b4d8bb0SJiri Pirko err = devl_sb_register(devlink, sb_index, size, ingress_pools_count,
970*2b4d8bb0SJiri Pirko egress_pools_count, ingress_tc_count,
971*2b4d8bb0SJiri Pirko egress_tc_count);
972*2b4d8bb0SJiri Pirko devl_unlock(devlink);
973*2b4d8bb0SJiri Pirko return err;
974*2b4d8bb0SJiri Pirko }
975*2b4d8bb0SJiri Pirko EXPORT_SYMBOL_GPL(devlink_sb_register);
976*2b4d8bb0SJiri Pirko
devl_sb_unregister(struct devlink * devlink,unsigned int sb_index)977*2b4d8bb0SJiri Pirko void devl_sb_unregister(struct devlink *devlink, unsigned int sb_index)
978*2b4d8bb0SJiri Pirko {
979*2b4d8bb0SJiri Pirko struct devlink_sb *devlink_sb;
980*2b4d8bb0SJiri Pirko
981*2b4d8bb0SJiri Pirko lockdep_assert_held(&devlink->lock);
982*2b4d8bb0SJiri Pirko
983*2b4d8bb0SJiri Pirko devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
984*2b4d8bb0SJiri Pirko WARN_ON(!devlink_sb);
985*2b4d8bb0SJiri Pirko list_del(&devlink_sb->list);
986*2b4d8bb0SJiri Pirko kfree(devlink_sb);
987*2b4d8bb0SJiri Pirko }
988*2b4d8bb0SJiri Pirko EXPORT_SYMBOL_GPL(devl_sb_unregister);
989*2b4d8bb0SJiri Pirko
devlink_sb_unregister(struct devlink * devlink,unsigned int sb_index)990*2b4d8bb0SJiri Pirko void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
991*2b4d8bb0SJiri Pirko {
992*2b4d8bb0SJiri Pirko devl_lock(devlink);
993*2b4d8bb0SJiri Pirko devl_sb_unregister(devlink, sb_index);
994*2b4d8bb0SJiri Pirko devl_unlock(devlink);
995*2b4d8bb0SJiri Pirko }
996*2b4d8bb0SJiri Pirko EXPORT_SYMBOL_GPL(devlink_sb_unregister);
997