xref: /linux-6.15/net/devlink/sb.c (revision 53590934)
12b4d8bb0SJiri Pirko // SPDX-License-Identifier: GPL-2.0-or-later
22b4d8bb0SJiri Pirko /*
32b4d8bb0SJiri Pirko  * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
42b4d8bb0SJiri Pirko  * Copyright (c) 2016 Jiri Pirko <[email protected]>
52b4d8bb0SJiri Pirko  */
62b4d8bb0SJiri Pirko 
72b4d8bb0SJiri Pirko #include "devl_internal.h"
82b4d8bb0SJiri Pirko 
92b4d8bb0SJiri Pirko struct devlink_sb {
102b4d8bb0SJiri Pirko 	struct list_head list;
112b4d8bb0SJiri Pirko 	unsigned int index;
122b4d8bb0SJiri Pirko 	u32 size;
132b4d8bb0SJiri Pirko 	u16 ingress_pools_count;
142b4d8bb0SJiri Pirko 	u16 egress_pools_count;
152b4d8bb0SJiri Pirko 	u16 ingress_tc_count;
162b4d8bb0SJiri Pirko 	u16 egress_tc_count;
172b4d8bb0SJiri Pirko };
182b4d8bb0SJiri Pirko 
devlink_sb_pool_count(struct devlink_sb * devlink_sb)192b4d8bb0SJiri Pirko static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
202b4d8bb0SJiri Pirko {
212b4d8bb0SJiri Pirko 	return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
222b4d8bb0SJiri Pirko }
232b4d8bb0SJiri Pirko 
devlink_sb_get_by_index(struct devlink * devlink,unsigned int sb_index)242b4d8bb0SJiri Pirko static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
252b4d8bb0SJiri Pirko 						  unsigned int sb_index)
262b4d8bb0SJiri Pirko {
272b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
282b4d8bb0SJiri Pirko 
292b4d8bb0SJiri Pirko 	list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
302b4d8bb0SJiri Pirko 		if (devlink_sb->index == sb_index)
312b4d8bb0SJiri Pirko 			return devlink_sb;
322b4d8bb0SJiri Pirko 	}
332b4d8bb0SJiri Pirko 	return NULL;
342b4d8bb0SJiri Pirko }
352b4d8bb0SJiri Pirko 
devlink_sb_index_exists(struct devlink * devlink,unsigned int sb_index)362b4d8bb0SJiri Pirko static bool devlink_sb_index_exists(struct devlink *devlink,
372b4d8bb0SJiri Pirko 				    unsigned int sb_index)
382b4d8bb0SJiri Pirko {
392b4d8bb0SJiri Pirko 	return devlink_sb_get_by_index(devlink, sb_index);
402b4d8bb0SJiri Pirko }
412b4d8bb0SJiri Pirko 
devlink_sb_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)422b4d8bb0SJiri Pirko static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
432b4d8bb0SJiri Pirko 						    struct nlattr **attrs)
442b4d8bb0SJiri Pirko {
452b4d8bb0SJiri Pirko 	if (attrs[DEVLINK_ATTR_SB_INDEX]) {
462b4d8bb0SJiri Pirko 		u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
472b4d8bb0SJiri Pirko 		struct devlink_sb *devlink_sb;
482b4d8bb0SJiri Pirko 
492b4d8bb0SJiri Pirko 		devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
502b4d8bb0SJiri Pirko 		if (!devlink_sb)
512b4d8bb0SJiri Pirko 			return ERR_PTR(-ENODEV);
522b4d8bb0SJiri Pirko 		return devlink_sb;
532b4d8bb0SJiri Pirko 	}
542b4d8bb0SJiri Pirko 	return ERR_PTR(-EINVAL);
552b4d8bb0SJiri Pirko }
562b4d8bb0SJiri Pirko 
devlink_sb_get_from_info(struct devlink * devlink,struct genl_info * info)572b4d8bb0SJiri Pirko static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
582b4d8bb0SJiri Pirko 						   struct genl_info *info)
592b4d8bb0SJiri Pirko {
602b4d8bb0SJiri Pirko 	return devlink_sb_get_from_attrs(devlink, info->attrs);
612b4d8bb0SJiri Pirko }
622b4d8bb0SJiri Pirko 
devlink_sb_pool_index_get_from_attrs(struct devlink_sb * devlink_sb,struct nlattr ** attrs,u16 * p_pool_index)632b4d8bb0SJiri Pirko static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
642b4d8bb0SJiri Pirko 						struct nlattr **attrs,
652b4d8bb0SJiri Pirko 						u16 *p_pool_index)
662b4d8bb0SJiri Pirko {
672b4d8bb0SJiri Pirko 	u16 val;
682b4d8bb0SJiri Pirko 
692b4d8bb0SJiri Pirko 	if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
702b4d8bb0SJiri Pirko 		return -EINVAL;
712b4d8bb0SJiri Pirko 
722b4d8bb0SJiri Pirko 	val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
732b4d8bb0SJiri Pirko 	if (val >= devlink_sb_pool_count(devlink_sb))
742b4d8bb0SJiri Pirko 		return -EINVAL;
752b4d8bb0SJiri Pirko 	*p_pool_index = val;
762b4d8bb0SJiri Pirko 	return 0;
772b4d8bb0SJiri Pirko }
782b4d8bb0SJiri Pirko 
devlink_sb_pool_index_get_from_info(struct devlink_sb * devlink_sb,struct genl_info * info,u16 * p_pool_index)792b4d8bb0SJiri Pirko static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
802b4d8bb0SJiri Pirko 					       struct genl_info *info,
812b4d8bb0SJiri Pirko 					       u16 *p_pool_index)
822b4d8bb0SJiri Pirko {
832b4d8bb0SJiri Pirko 	return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
842b4d8bb0SJiri Pirko 						    p_pool_index);
852b4d8bb0SJiri Pirko }
862b4d8bb0SJiri Pirko 
872b4d8bb0SJiri Pirko static int
devlink_sb_pool_type_get_from_attrs(struct nlattr ** attrs,enum devlink_sb_pool_type * p_pool_type)882b4d8bb0SJiri Pirko devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
892b4d8bb0SJiri Pirko 				    enum devlink_sb_pool_type *p_pool_type)
902b4d8bb0SJiri Pirko {
912b4d8bb0SJiri Pirko 	u8 val;
922b4d8bb0SJiri Pirko 
932b4d8bb0SJiri Pirko 	if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
942b4d8bb0SJiri Pirko 		return -EINVAL;
952b4d8bb0SJiri Pirko 
962b4d8bb0SJiri Pirko 	val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
972b4d8bb0SJiri Pirko 	if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
982b4d8bb0SJiri Pirko 	    val != DEVLINK_SB_POOL_TYPE_EGRESS)
992b4d8bb0SJiri Pirko 		return -EINVAL;
1002b4d8bb0SJiri Pirko 	*p_pool_type = val;
1012b4d8bb0SJiri Pirko 	return 0;
1022b4d8bb0SJiri Pirko }
1032b4d8bb0SJiri Pirko 
1042b4d8bb0SJiri Pirko static int
devlink_sb_pool_type_get_from_info(struct genl_info * info,enum devlink_sb_pool_type * p_pool_type)1052b4d8bb0SJiri Pirko devlink_sb_pool_type_get_from_info(struct genl_info *info,
1062b4d8bb0SJiri Pirko 				   enum devlink_sb_pool_type *p_pool_type)
1072b4d8bb0SJiri Pirko {
1082b4d8bb0SJiri Pirko 	return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
1092b4d8bb0SJiri Pirko }
1102b4d8bb0SJiri Pirko 
1112b4d8bb0SJiri Pirko static int
devlink_sb_th_type_get_from_attrs(struct nlattr ** attrs,enum devlink_sb_threshold_type * p_th_type)1122b4d8bb0SJiri Pirko devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
1132b4d8bb0SJiri Pirko 				  enum devlink_sb_threshold_type *p_th_type)
1142b4d8bb0SJiri Pirko {
1152b4d8bb0SJiri Pirko 	u8 val;
1162b4d8bb0SJiri Pirko 
1172b4d8bb0SJiri Pirko 	if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
1182b4d8bb0SJiri Pirko 		return -EINVAL;
1192b4d8bb0SJiri Pirko 
1202b4d8bb0SJiri Pirko 	val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
1212b4d8bb0SJiri Pirko 	if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
1222b4d8bb0SJiri Pirko 	    val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
1232b4d8bb0SJiri Pirko 		return -EINVAL;
1242b4d8bb0SJiri Pirko 	*p_th_type = val;
1252b4d8bb0SJiri Pirko 	return 0;
1262b4d8bb0SJiri Pirko }
1272b4d8bb0SJiri Pirko 
1282b4d8bb0SJiri Pirko static int
devlink_sb_th_type_get_from_info(struct genl_info * info,enum devlink_sb_threshold_type * p_th_type)1292b4d8bb0SJiri Pirko devlink_sb_th_type_get_from_info(struct genl_info *info,
1302b4d8bb0SJiri Pirko 				 enum devlink_sb_threshold_type *p_th_type)
1312b4d8bb0SJiri Pirko {
1322b4d8bb0SJiri Pirko 	return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
1332b4d8bb0SJiri Pirko }
1342b4d8bb0SJiri Pirko 
1352b4d8bb0SJiri 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)1362b4d8bb0SJiri Pirko devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
1372b4d8bb0SJiri Pirko 				   struct nlattr **attrs,
1382b4d8bb0SJiri Pirko 				   enum devlink_sb_pool_type pool_type,
1392b4d8bb0SJiri Pirko 				   u16 *p_tc_index)
1402b4d8bb0SJiri Pirko {
1412b4d8bb0SJiri Pirko 	u16 val;
1422b4d8bb0SJiri Pirko 
1432b4d8bb0SJiri Pirko 	if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
1442b4d8bb0SJiri Pirko 		return -EINVAL;
1452b4d8bb0SJiri Pirko 
1462b4d8bb0SJiri Pirko 	val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
1472b4d8bb0SJiri Pirko 	if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
1482b4d8bb0SJiri Pirko 	    val >= devlink_sb->ingress_tc_count)
1492b4d8bb0SJiri Pirko 		return -EINVAL;
1502b4d8bb0SJiri Pirko 	if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
1512b4d8bb0SJiri Pirko 	    val >= devlink_sb->egress_tc_count)
1522b4d8bb0SJiri Pirko 		return -EINVAL;
1532b4d8bb0SJiri Pirko 	*p_tc_index = val;
1542b4d8bb0SJiri Pirko 	return 0;
1552b4d8bb0SJiri Pirko }
1562b4d8bb0SJiri Pirko 
1572b4d8bb0SJiri 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)1582b4d8bb0SJiri Pirko devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
1592b4d8bb0SJiri Pirko 				  struct genl_info *info,
1602b4d8bb0SJiri Pirko 				  enum devlink_sb_pool_type pool_type,
1612b4d8bb0SJiri Pirko 				  u16 *p_tc_index)
1622b4d8bb0SJiri Pirko {
1632b4d8bb0SJiri Pirko 	return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
1642b4d8bb0SJiri Pirko 						  pool_type, p_tc_index);
1652b4d8bb0SJiri Pirko }
1662b4d8bb0SJiri 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)1672b4d8bb0SJiri Pirko static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
1682b4d8bb0SJiri Pirko 			      struct devlink_sb *devlink_sb,
1692b4d8bb0SJiri Pirko 			      enum devlink_command cmd, u32 portid,
1702b4d8bb0SJiri Pirko 			      u32 seq, int flags)
1712b4d8bb0SJiri Pirko {
1722b4d8bb0SJiri Pirko 	void *hdr;
1732b4d8bb0SJiri Pirko 
1742b4d8bb0SJiri Pirko 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1752b4d8bb0SJiri Pirko 	if (!hdr)
1762b4d8bb0SJiri Pirko 		return -EMSGSIZE;
1772b4d8bb0SJiri Pirko 
1782b4d8bb0SJiri Pirko 	if (devlink_nl_put_handle(msg, devlink))
1792b4d8bb0SJiri Pirko 		goto nla_put_failure;
1802b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1812b4d8bb0SJiri Pirko 		goto nla_put_failure;
1822b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
1832b4d8bb0SJiri Pirko 		goto nla_put_failure;
1842b4d8bb0SJiri Pirko 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
1852b4d8bb0SJiri Pirko 			devlink_sb->ingress_pools_count))
1862b4d8bb0SJiri Pirko 		goto nla_put_failure;
1872b4d8bb0SJiri Pirko 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
1882b4d8bb0SJiri Pirko 			devlink_sb->egress_pools_count))
1892b4d8bb0SJiri Pirko 		goto nla_put_failure;
1902b4d8bb0SJiri Pirko 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
1912b4d8bb0SJiri Pirko 			devlink_sb->ingress_tc_count))
1922b4d8bb0SJiri Pirko 		goto nla_put_failure;
1932b4d8bb0SJiri Pirko 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
1942b4d8bb0SJiri Pirko 			devlink_sb->egress_tc_count))
1952b4d8bb0SJiri Pirko 		goto nla_put_failure;
1962b4d8bb0SJiri Pirko 
1972b4d8bb0SJiri Pirko 	genlmsg_end(msg, hdr);
1982b4d8bb0SJiri Pirko 	return 0;
1992b4d8bb0SJiri Pirko 
2002b4d8bb0SJiri Pirko nla_put_failure:
2012b4d8bb0SJiri Pirko 	genlmsg_cancel(msg, hdr);
2022b4d8bb0SJiri Pirko 	return -EMSGSIZE;
2032b4d8bb0SJiri Pirko }
2042b4d8bb0SJiri Pirko 
devlink_nl_sb_get_doit(struct sk_buff * skb,struct genl_info * info)2052b4d8bb0SJiri Pirko int devlink_nl_sb_get_doit(struct sk_buff *skb, struct genl_info *info)
2062b4d8bb0SJiri Pirko {
2072b4d8bb0SJiri Pirko 	struct devlink *devlink = info->user_ptr[0];
2082b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
2092b4d8bb0SJiri Pirko 	struct sk_buff *msg;
2102b4d8bb0SJiri Pirko 	int err;
2112b4d8bb0SJiri Pirko 
2122b4d8bb0SJiri Pirko 	devlink_sb = devlink_sb_get_from_info(devlink, info);
2132b4d8bb0SJiri Pirko 	if (IS_ERR(devlink_sb))
2142b4d8bb0SJiri Pirko 		return PTR_ERR(devlink_sb);
2152b4d8bb0SJiri Pirko 
2162b4d8bb0SJiri Pirko 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2172b4d8bb0SJiri Pirko 	if (!msg)
2182b4d8bb0SJiri Pirko 		return -ENOMEM;
2192b4d8bb0SJiri Pirko 
2202b4d8bb0SJiri Pirko 	err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
2212b4d8bb0SJiri Pirko 				 DEVLINK_CMD_SB_NEW,
2222b4d8bb0SJiri Pirko 				 info->snd_portid, info->snd_seq, 0);
2232b4d8bb0SJiri Pirko 	if (err) {
2242b4d8bb0SJiri Pirko 		nlmsg_free(msg);
2252b4d8bb0SJiri Pirko 		return err;
2262b4d8bb0SJiri Pirko 	}
2272b4d8bb0SJiri Pirko 
2282b4d8bb0SJiri Pirko 	return genlmsg_reply(msg, info);
2292b4d8bb0SJiri Pirko }
2302b4d8bb0SJiri Pirko 
2312b4d8bb0SJiri Pirko static int
devlink_nl_sb_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)2322b4d8bb0SJiri Pirko devlink_nl_sb_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
2332b4d8bb0SJiri Pirko 			   struct netlink_callback *cb, int flags)
2342b4d8bb0SJiri Pirko {
2352b4d8bb0SJiri Pirko 	struct devlink_nl_dump_state *state = devlink_dump_state(cb);
2362b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
2372b4d8bb0SJiri Pirko 	int idx = 0;
2382b4d8bb0SJiri Pirko 	int err = 0;
2392b4d8bb0SJiri Pirko 
2402b4d8bb0SJiri Pirko 	list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
2412b4d8bb0SJiri Pirko 		if (idx < state->idx) {
2422b4d8bb0SJiri Pirko 			idx++;
2432b4d8bb0SJiri Pirko 			continue;
2442b4d8bb0SJiri Pirko 		}
2452b4d8bb0SJiri Pirko 		err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
2462b4d8bb0SJiri Pirko 					 DEVLINK_CMD_SB_NEW,
2472b4d8bb0SJiri Pirko 					 NETLINK_CB(cb->skb).portid,
2482b4d8bb0SJiri Pirko 					 cb->nlh->nlmsg_seq, flags);
2492b4d8bb0SJiri Pirko 		if (err) {
2502b4d8bb0SJiri Pirko 			state->idx = idx;
2512b4d8bb0SJiri Pirko 			break;
2522b4d8bb0SJiri Pirko 		}
2532b4d8bb0SJiri Pirko 		idx++;
2542b4d8bb0SJiri Pirko 	}
2552b4d8bb0SJiri Pirko 
2562b4d8bb0SJiri Pirko 	return err;
2572b4d8bb0SJiri Pirko }
2582b4d8bb0SJiri Pirko 
devlink_nl_sb_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)2592b4d8bb0SJiri Pirko int devlink_nl_sb_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
2602b4d8bb0SJiri Pirko {
2612b4d8bb0SJiri Pirko 	return devlink_nl_dumpit(skb, cb, devlink_nl_sb_get_dump_one);
2622b4d8bb0SJiri Pirko }
2632b4d8bb0SJiri 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)2642b4d8bb0SJiri Pirko static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
2652b4d8bb0SJiri Pirko 				   struct devlink_sb *devlink_sb,
2662b4d8bb0SJiri Pirko 				   u16 pool_index, enum devlink_command cmd,
2672b4d8bb0SJiri Pirko 				   u32 portid, u32 seq, int flags)
2682b4d8bb0SJiri Pirko {
2692b4d8bb0SJiri Pirko 	struct devlink_sb_pool_info pool_info;
2702b4d8bb0SJiri Pirko 	void *hdr;
2712b4d8bb0SJiri Pirko 	int err;
2722b4d8bb0SJiri Pirko 
2732b4d8bb0SJiri Pirko 	err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
2742b4d8bb0SJiri Pirko 					pool_index, &pool_info);
2752b4d8bb0SJiri Pirko 	if (err)
2762b4d8bb0SJiri Pirko 		return err;
2772b4d8bb0SJiri Pirko 
2782b4d8bb0SJiri Pirko 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
2792b4d8bb0SJiri Pirko 	if (!hdr)
2802b4d8bb0SJiri Pirko 		return -EMSGSIZE;
2812b4d8bb0SJiri Pirko 
2822b4d8bb0SJiri Pirko 	if (devlink_nl_put_handle(msg, devlink))
2832b4d8bb0SJiri Pirko 		goto nla_put_failure;
2842b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
2852b4d8bb0SJiri Pirko 		goto nla_put_failure;
2862b4d8bb0SJiri Pirko 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
2872b4d8bb0SJiri Pirko 		goto nla_put_failure;
2882b4d8bb0SJiri Pirko 	if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
2892b4d8bb0SJiri Pirko 		goto nla_put_failure;
2902b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
2912b4d8bb0SJiri Pirko 		goto nla_put_failure;
2922b4d8bb0SJiri Pirko 	if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
2932b4d8bb0SJiri Pirko 		       pool_info.threshold_type))
2942b4d8bb0SJiri Pirko 		goto nla_put_failure;
2952b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE,
2962b4d8bb0SJiri Pirko 			pool_info.cell_size))
2972b4d8bb0SJiri Pirko 		goto nla_put_failure;
2982b4d8bb0SJiri Pirko 
2992b4d8bb0SJiri Pirko 	genlmsg_end(msg, hdr);
3002b4d8bb0SJiri Pirko 	return 0;
3012b4d8bb0SJiri Pirko 
3022b4d8bb0SJiri Pirko nla_put_failure:
3032b4d8bb0SJiri Pirko 	genlmsg_cancel(msg, hdr);
3042b4d8bb0SJiri Pirko 	return -EMSGSIZE;
3052b4d8bb0SJiri Pirko }
3062b4d8bb0SJiri Pirko 
devlink_nl_sb_pool_get_doit(struct sk_buff * skb,struct genl_info * info)3072b4d8bb0SJiri Pirko int devlink_nl_sb_pool_get_doit(struct sk_buff *skb, struct genl_info *info)
3082b4d8bb0SJiri Pirko {
3092b4d8bb0SJiri Pirko 	struct devlink *devlink = info->user_ptr[0];
3102b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
3112b4d8bb0SJiri Pirko 	struct sk_buff *msg;
3122b4d8bb0SJiri Pirko 	u16 pool_index;
3132b4d8bb0SJiri Pirko 	int err;
3142b4d8bb0SJiri Pirko 
3152b4d8bb0SJiri Pirko 	devlink_sb = devlink_sb_get_from_info(devlink, info);
3162b4d8bb0SJiri Pirko 	if (IS_ERR(devlink_sb))
3172b4d8bb0SJiri Pirko 		return PTR_ERR(devlink_sb);
3182b4d8bb0SJiri Pirko 
3192b4d8bb0SJiri Pirko 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
3202b4d8bb0SJiri Pirko 						  &pool_index);
3212b4d8bb0SJiri Pirko 	if (err)
3222b4d8bb0SJiri Pirko 		return err;
3232b4d8bb0SJiri Pirko 
3242b4d8bb0SJiri Pirko 	if (!devlink->ops->sb_pool_get)
3252b4d8bb0SJiri Pirko 		return -EOPNOTSUPP;
3262b4d8bb0SJiri Pirko 
3272b4d8bb0SJiri Pirko 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3282b4d8bb0SJiri Pirko 	if (!msg)
3292b4d8bb0SJiri Pirko 		return -ENOMEM;
3302b4d8bb0SJiri Pirko 
3312b4d8bb0SJiri Pirko 	err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
3322b4d8bb0SJiri Pirko 				      DEVLINK_CMD_SB_POOL_NEW,
3332b4d8bb0SJiri Pirko 				      info->snd_portid, info->snd_seq, 0);
3342b4d8bb0SJiri Pirko 	if (err) {
3352b4d8bb0SJiri Pirko 		nlmsg_free(msg);
3362b4d8bb0SJiri Pirko 		return err;
3372b4d8bb0SJiri Pirko 	}
3382b4d8bb0SJiri Pirko 
3392b4d8bb0SJiri Pirko 	return genlmsg_reply(msg, info);
3402b4d8bb0SJiri Pirko }
3412b4d8bb0SJiri 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)3422b4d8bb0SJiri Pirko static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
3432b4d8bb0SJiri Pirko 				struct devlink *devlink,
3442b4d8bb0SJiri Pirko 				struct devlink_sb *devlink_sb,
3452b4d8bb0SJiri Pirko 				u32 portid, u32 seq, int flags)
3462b4d8bb0SJiri Pirko {
3472b4d8bb0SJiri Pirko 	u16 pool_count = devlink_sb_pool_count(devlink_sb);
3482b4d8bb0SJiri Pirko 	u16 pool_index;
3492b4d8bb0SJiri Pirko 	int err;
3502b4d8bb0SJiri Pirko 
3512b4d8bb0SJiri Pirko 	for (pool_index = 0; pool_index < pool_count; pool_index++) {
3522b4d8bb0SJiri Pirko 		if (*p_idx < start) {
3532b4d8bb0SJiri Pirko 			(*p_idx)++;
3542b4d8bb0SJiri Pirko 			continue;
3552b4d8bb0SJiri Pirko 		}
3562b4d8bb0SJiri Pirko 		err = devlink_nl_sb_pool_fill(msg, devlink,
3572b4d8bb0SJiri Pirko 					      devlink_sb,
3582b4d8bb0SJiri Pirko 					      pool_index,
3592b4d8bb0SJiri Pirko 					      DEVLINK_CMD_SB_POOL_NEW,
3602b4d8bb0SJiri Pirko 					      portid, seq, flags);
3612b4d8bb0SJiri Pirko 		if (err)
3622b4d8bb0SJiri Pirko 			return err;
3632b4d8bb0SJiri Pirko 		(*p_idx)++;
3642b4d8bb0SJiri Pirko 	}
3652b4d8bb0SJiri Pirko 	return 0;
3662b4d8bb0SJiri Pirko }
3672b4d8bb0SJiri Pirko 
3682b4d8bb0SJiri Pirko static int
devlink_nl_sb_pool_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)3692b4d8bb0SJiri Pirko devlink_nl_sb_pool_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
3702b4d8bb0SJiri Pirko 				struct netlink_callback *cb, int flags)
3712b4d8bb0SJiri Pirko {
3722b4d8bb0SJiri Pirko 	struct devlink_nl_dump_state *state = devlink_dump_state(cb);
3732b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
3742b4d8bb0SJiri Pirko 	int err = 0;
3752b4d8bb0SJiri Pirko 	int idx = 0;
3762b4d8bb0SJiri Pirko 
3772b4d8bb0SJiri Pirko 	if (!devlink->ops->sb_pool_get)
3782b4d8bb0SJiri Pirko 		return 0;
3792b4d8bb0SJiri Pirko 
3802b4d8bb0SJiri Pirko 	list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
3812b4d8bb0SJiri Pirko 		err = __sb_pool_get_dumpit(msg, state->idx, &idx,
3822b4d8bb0SJiri Pirko 					   devlink, devlink_sb,
3832b4d8bb0SJiri Pirko 					   NETLINK_CB(cb->skb).portid,
3842b4d8bb0SJiri Pirko 					   cb->nlh->nlmsg_seq, flags);
3852b4d8bb0SJiri Pirko 		if (err == -EOPNOTSUPP) {
3862b4d8bb0SJiri Pirko 			err = 0;
3872b4d8bb0SJiri Pirko 		} else if (err) {
3882b4d8bb0SJiri Pirko 			state->idx = idx;
3892b4d8bb0SJiri Pirko 			break;
3902b4d8bb0SJiri Pirko 		}
3912b4d8bb0SJiri Pirko 	}
3922b4d8bb0SJiri Pirko 
3932b4d8bb0SJiri Pirko 	return err;
3942b4d8bb0SJiri Pirko }
3952b4d8bb0SJiri Pirko 
devlink_nl_sb_pool_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)3962b4d8bb0SJiri Pirko int devlink_nl_sb_pool_get_dumpit(struct sk_buff *skb,
3972b4d8bb0SJiri Pirko 				  struct netlink_callback *cb)
3982b4d8bb0SJiri Pirko {
3992b4d8bb0SJiri Pirko 	return devlink_nl_dumpit(skb, cb, devlink_nl_sb_pool_get_dump_one);
4002b4d8bb0SJiri Pirko }
4012b4d8bb0SJiri 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)4022b4d8bb0SJiri Pirko static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
4032b4d8bb0SJiri Pirko 			       u16 pool_index, u32 size,
4042b4d8bb0SJiri Pirko 			       enum devlink_sb_threshold_type threshold_type,
4052b4d8bb0SJiri Pirko 			       struct netlink_ext_ack *extack)
4062b4d8bb0SJiri Pirko 
4072b4d8bb0SJiri Pirko {
4082b4d8bb0SJiri Pirko 	const struct devlink_ops *ops = devlink->ops;
4092b4d8bb0SJiri Pirko 
4102b4d8bb0SJiri Pirko 	if (ops->sb_pool_set)
4112b4d8bb0SJiri Pirko 		return ops->sb_pool_set(devlink, sb_index, pool_index,
4122b4d8bb0SJiri Pirko 					size, threshold_type, extack);
4132b4d8bb0SJiri Pirko 	return -EOPNOTSUPP;
4142b4d8bb0SJiri Pirko }
4152b4d8bb0SJiri Pirko 
devlink_nl_sb_pool_set_doit(struct sk_buff * skb,struct genl_info * info)416*53590934SJiri Pirko int devlink_nl_sb_pool_set_doit(struct sk_buff *skb, struct genl_info *info)
4172b4d8bb0SJiri Pirko {
4182b4d8bb0SJiri Pirko 	struct devlink *devlink = info->user_ptr[0];
4192b4d8bb0SJiri Pirko 	enum devlink_sb_threshold_type threshold_type;
4202b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
4212b4d8bb0SJiri Pirko 	u16 pool_index;
4222b4d8bb0SJiri Pirko 	u32 size;
4232b4d8bb0SJiri Pirko 	int err;
4242b4d8bb0SJiri Pirko 
4252b4d8bb0SJiri Pirko 	devlink_sb = devlink_sb_get_from_info(devlink, info);
4262b4d8bb0SJiri Pirko 	if (IS_ERR(devlink_sb))
4272b4d8bb0SJiri Pirko 		return PTR_ERR(devlink_sb);
4282b4d8bb0SJiri Pirko 
4292b4d8bb0SJiri Pirko 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
4302b4d8bb0SJiri Pirko 						  &pool_index);
4312b4d8bb0SJiri Pirko 	if (err)
4322b4d8bb0SJiri Pirko 		return err;
4332b4d8bb0SJiri Pirko 
4342b4d8bb0SJiri Pirko 	err = devlink_sb_th_type_get_from_info(info, &threshold_type);
4352b4d8bb0SJiri Pirko 	if (err)
4362b4d8bb0SJiri Pirko 		return err;
4372b4d8bb0SJiri Pirko 
4382b4d8bb0SJiri Pirko 	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_POOL_SIZE))
4392b4d8bb0SJiri Pirko 		return -EINVAL;
4402b4d8bb0SJiri Pirko 
4412b4d8bb0SJiri Pirko 	size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
4422b4d8bb0SJiri Pirko 	return devlink_sb_pool_set(devlink, devlink_sb->index,
4432b4d8bb0SJiri Pirko 				   pool_index, size, threshold_type,
4442b4d8bb0SJiri Pirko 				   info->extack);
4452b4d8bb0SJiri Pirko }
4462b4d8bb0SJiri 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)4472b4d8bb0SJiri Pirko static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
4482b4d8bb0SJiri Pirko 					struct devlink *devlink,
4492b4d8bb0SJiri Pirko 					struct devlink_port *devlink_port,
4502b4d8bb0SJiri Pirko 					struct devlink_sb *devlink_sb,
4512b4d8bb0SJiri Pirko 					u16 pool_index,
4522b4d8bb0SJiri Pirko 					enum devlink_command cmd,
4532b4d8bb0SJiri Pirko 					u32 portid, u32 seq, int flags)
4542b4d8bb0SJiri Pirko {
4552b4d8bb0SJiri Pirko 	const struct devlink_ops *ops = devlink->ops;
4562b4d8bb0SJiri Pirko 	u32 threshold;
4572b4d8bb0SJiri Pirko 	void *hdr;
4582b4d8bb0SJiri Pirko 	int err;
4592b4d8bb0SJiri Pirko 
4602b4d8bb0SJiri Pirko 	err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
4612b4d8bb0SJiri Pirko 				    pool_index, &threshold);
4622b4d8bb0SJiri Pirko 	if (err)
4632b4d8bb0SJiri Pirko 		return err;
4642b4d8bb0SJiri Pirko 
4652b4d8bb0SJiri Pirko 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4662b4d8bb0SJiri Pirko 	if (!hdr)
4672b4d8bb0SJiri Pirko 		return -EMSGSIZE;
4682b4d8bb0SJiri Pirko 
4692b4d8bb0SJiri Pirko 	if (devlink_nl_put_handle(msg, devlink))
4702b4d8bb0SJiri Pirko 		goto nla_put_failure;
4712b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
4722b4d8bb0SJiri Pirko 		goto nla_put_failure;
4732b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
4742b4d8bb0SJiri Pirko 		goto nla_put_failure;
4752b4d8bb0SJiri Pirko 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
4762b4d8bb0SJiri Pirko 		goto nla_put_failure;
4772b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
4782b4d8bb0SJiri Pirko 		goto nla_put_failure;
4792b4d8bb0SJiri Pirko 
4802b4d8bb0SJiri Pirko 	if (ops->sb_occ_port_pool_get) {
4812b4d8bb0SJiri Pirko 		u32 cur;
4822b4d8bb0SJiri Pirko 		u32 max;
4832b4d8bb0SJiri Pirko 
4842b4d8bb0SJiri Pirko 		err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
4852b4d8bb0SJiri Pirko 						pool_index, &cur, &max);
4862b4d8bb0SJiri Pirko 		if (err && err != -EOPNOTSUPP)
4872b4d8bb0SJiri Pirko 			goto sb_occ_get_failure;
4882b4d8bb0SJiri Pirko 		if (!err) {
4892b4d8bb0SJiri Pirko 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
4902b4d8bb0SJiri Pirko 				goto nla_put_failure;
4912b4d8bb0SJiri Pirko 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
4922b4d8bb0SJiri Pirko 				goto nla_put_failure;
4932b4d8bb0SJiri Pirko 		}
4942b4d8bb0SJiri Pirko 	}
4952b4d8bb0SJiri Pirko 
4962b4d8bb0SJiri Pirko 	genlmsg_end(msg, hdr);
4972b4d8bb0SJiri Pirko 	return 0;
4982b4d8bb0SJiri Pirko 
4992b4d8bb0SJiri Pirko nla_put_failure:
5002b4d8bb0SJiri Pirko 	err = -EMSGSIZE;
5012b4d8bb0SJiri Pirko sb_occ_get_failure:
5022b4d8bb0SJiri Pirko 	genlmsg_cancel(msg, hdr);
5032b4d8bb0SJiri Pirko 	return err;
5042b4d8bb0SJiri Pirko }
5052b4d8bb0SJiri Pirko 
devlink_nl_sb_port_pool_get_doit(struct sk_buff * skb,struct genl_info * info)5062b4d8bb0SJiri Pirko int devlink_nl_sb_port_pool_get_doit(struct sk_buff *skb,
5072b4d8bb0SJiri Pirko 				     struct genl_info *info)
5082b4d8bb0SJiri Pirko {
5092b4d8bb0SJiri Pirko 	struct devlink_port *devlink_port = info->user_ptr[1];
5102b4d8bb0SJiri Pirko 	struct devlink *devlink = devlink_port->devlink;
5112b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
5122b4d8bb0SJiri Pirko 	struct sk_buff *msg;
5132b4d8bb0SJiri Pirko 	u16 pool_index;
5142b4d8bb0SJiri Pirko 	int err;
5152b4d8bb0SJiri Pirko 
5162b4d8bb0SJiri Pirko 	devlink_sb = devlink_sb_get_from_info(devlink, info);
5172b4d8bb0SJiri Pirko 	if (IS_ERR(devlink_sb))
5182b4d8bb0SJiri Pirko 		return PTR_ERR(devlink_sb);
5192b4d8bb0SJiri Pirko 
5202b4d8bb0SJiri Pirko 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
5212b4d8bb0SJiri Pirko 						  &pool_index);
5222b4d8bb0SJiri Pirko 	if (err)
5232b4d8bb0SJiri Pirko 		return err;
5242b4d8bb0SJiri Pirko 
5252b4d8bb0SJiri Pirko 	if (!devlink->ops->sb_port_pool_get)
5262b4d8bb0SJiri Pirko 		return -EOPNOTSUPP;
5272b4d8bb0SJiri Pirko 
5282b4d8bb0SJiri Pirko 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5292b4d8bb0SJiri Pirko 	if (!msg)
5302b4d8bb0SJiri Pirko 		return -ENOMEM;
5312b4d8bb0SJiri Pirko 
5322b4d8bb0SJiri Pirko 	err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
5332b4d8bb0SJiri Pirko 					   devlink_sb, pool_index,
5342b4d8bb0SJiri Pirko 					   DEVLINK_CMD_SB_PORT_POOL_NEW,
5352b4d8bb0SJiri Pirko 					   info->snd_portid, info->snd_seq, 0);
5362b4d8bb0SJiri Pirko 	if (err) {
5372b4d8bb0SJiri Pirko 		nlmsg_free(msg);
5382b4d8bb0SJiri Pirko 		return err;
5392b4d8bb0SJiri Pirko 	}
5402b4d8bb0SJiri Pirko 
5412b4d8bb0SJiri Pirko 	return genlmsg_reply(msg, info);
5422b4d8bb0SJiri Pirko }
5432b4d8bb0SJiri 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)5442b4d8bb0SJiri Pirko static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
5452b4d8bb0SJiri Pirko 				     struct devlink *devlink,
5462b4d8bb0SJiri Pirko 				     struct devlink_sb *devlink_sb,
5472b4d8bb0SJiri Pirko 				     u32 portid, u32 seq, int flags)
5482b4d8bb0SJiri Pirko {
5492b4d8bb0SJiri Pirko 	struct devlink_port *devlink_port;
5502b4d8bb0SJiri Pirko 	u16 pool_count = devlink_sb_pool_count(devlink_sb);
5512b4d8bb0SJiri Pirko 	unsigned long port_index;
5522b4d8bb0SJiri Pirko 	u16 pool_index;
5532b4d8bb0SJiri Pirko 	int err;
5542b4d8bb0SJiri Pirko 
5552b4d8bb0SJiri Pirko 	xa_for_each(&devlink->ports, port_index, devlink_port) {
5562b4d8bb0SJiri Pirko 		for (pool_index = 0; pool_index < pool_count; pool_index++) {
5572b4d8bb0SJiri Pirko 			if (*p_idx < start) {
5582b4d8bb0SJiri Pirko 				(*p_idx)++;
5592b4d8bb0SJiri Pirko 				continue;
5602b4d8bb0SJiri Pirko 			}
5612b4d8bb0SJiri Pirko 			err = devlink_nl_sb_port_pool_fill(msg, devlink,
5622b4d8bb0SJiri Pirko 							   devlink_port,
5632b4d8bb0SJiri Pirko 							   devlink_sb,
5642b4d8bb0SJiri Pirko 							   pool_index,
5652b4d8bb0SJiri Pirko 							   DEVLINK_CMD_SB_PORT_POOL_NEW,
5662b4d8bb0SJiri Pirko 							   portid, seq, flags);
5672b4d8bb0SJiri Pirko 			if (err)
5682b4d8bb0SJiri Pirko 				return err;
5692b4d8bb0SJiri Pirko 			(*p_idx)++;
5702b4d8bb0SJiri Pirko 		}
5712b4d8bb0SJiri Pirko 	}
5722b4d8bb0SJiri Pirko 	return 0;
5732b4d8bb0SJiri Pirko }
5742b4d8bb0SJiri Pirko 
5752b4d8bb0SJiri Pirko static int
devlink_nl_sb_port_pool_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)5762b4d8bb0SJiri Pirko devlink_nl_sb_port_pool_get_dump_one(struct sk_buff *msg,
5772b4d8bb0SJiri Pirko 				     struct devlink *devlink,
5782b4d8bb0SJiri Pirko 				     struct netlink_callback *cb, int flags)
5792b4d8bb0SJiri Pirko {
5802b4d8bb0SJiri Pirko 	struct devlink_nl_dump_state *state = devlink_dump_state(cb);
5812b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
5822b4d8bb0SJiri Pirko 	int idx = 0;
5832b4d8bb0SJiri Pirko 	int err = 0;
5842b4d8bb0SJiri Pirko 
5852b4d8bb0SJiri Pirko 	if (!devlink->ops->sb_port_pool_get)
5862b4d8bb0SJiri Pirko 		return 0;
5872b4d8bb0SJiri Pirko 
5882b4d8bb0SJiri Pirko 	list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
5892b4d8bb0SJiri Pirko 		err = __sb_port_pool_get_dumpit(msg, state->idx, &idx,
5902b4d8bb0SJiri Pirko 						devlink, devlink_sb,
5912b4d8bb0SJiri Pirko 						NETLINK_CB(cb->skb).portid,
5922b4d8bb0SJiri Pirko 						cb->nlh->nlmsg_seq, flags);
5932b4d8bb0SJiri Pirko 		if (err == -EOPNOTSUPP) {
5942b4d8bb0SJiri Pirko 			err = 0;
5952b4d8bb0SJiri Pirko 		} else if (err) {
5962b4d8bb0SJiri Pirko 			state->idx = idx;
5972b4d8bb0SJiri Pirko 			break;
5982b4d8bb0SJiri Pirko 		}
5992b4d8bb0SJiri Pirko 	}
6002b4d8bb0SJiri Pirko 
6012b4d8bb0SJiri Pirko 	return err;
6022b4d8bb0SJiri Pirko }
6032b4d8bb0SJiri Pirko 
devlink_nl_sb_port_pool_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)6042b4d8bb0SJiri Pirko int devlink_nl_sb_port_pool_get_dumpit(struct sk_buff *skb,
6052b4d8bb0SJiri Pirko 				       struct netlink_callback *cb)
6062b4d8bb0SJiri Pirko {
6072b4d8bb0SJiri Pirko 	return devlink_nl_dumpit(skb, cb, devlink_nl_sb_port_pool_get_dump_one);
6082b4d8bb0SJiri Pirko }
6092b4d8bb0SJiri 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)6102b4d8bb0SJiri Pirko static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
6112b4d8bb0SJiri Pirko 				    unsigned int sb_index, u16 pool_index,
6122b4d8bb0SJiri Pirko 				    u32 threshold,
6132b4d8bb0SJiri Pirko 				    struct netlink_ext_ack *extack)
6142b4d8bb0SJiri Pirko 
6152b4d8bb0SJiri Pirko {
6162b4d8bb0SJiri Pirko 	const struct devlink_ops *ops = devlink_port->devlink->ops;
6172b4d8bb0SJiri Pirko 
6182b4d8bb0SJiri Pirko 	if (ops->sb_port_pool_set)
6192b4d8bb0SJiri Pirko 		return ops->sb_port_pool_set(devlink_port, sb_index,
6202b4d8bb0SJiri Pirko 					     pool_index, threshold, extack);
6212b4d8bb0SJiri Pirko 	return -EOPNOTSUPP;
6222b4d8bb0SJiri Pirko }
6232b4d8bb0SJiri Pirko 
devlink_nl_sb_port_pool_set_doit(struct sk_buff * skb,struct genl_info * info)624*53590934SJiri Pirko int devlink_nl_sb_port_pool_set_doit(struct sk_buff *skb,
6252b4d8bb0SJiri Pirko 				     struct genl_info *info)
6262b4d8bb0SJiri Pirko {
6272b4d8bb0SJiri Pirko 	struct devlink_port *devlink_port = info->user_ptr[1];
6282b4d8bb0SJiri Pirko 	struct devlink *devlink = info->user_ptr[0];
6292b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
6302b4d8bb0SJiri Pirko 	u16 pool_index;
6312b4d8bb0SJiri Pirko 	u32 threshold;
6322b4d8bb0SJiri Pirko 	int err;
6332b4d8bb0SJiri Pirko 
6342b4d8bb0SJiri Pirko 	devlink_sb = devlink_sb_get_from_info(devlink, info);
6352b4d8bb0SJiri Pirko 	if (IS_ERR(devlink_sb))
6362b4d8bb0SJiri Pirko 		return PTR_ERR(devlink_sb);
6372b4d8bb0SJiri Pirko 
6382b4d8bb0SJiri Pirko 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
6392b4d8bb0SJiri Pirko 						  &pool_index);
6402b4d8bb0SJiri Pirko 	if (err)
6412b4d8bb0SJiri Pirko 		return err;
6422b4d8bb0SJiri Pirko 
6432b4d8bb0SJiri Pirko 	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD))
6442b4d8bb0SJiri Pirko 		return -EINVAL;
6452b4d8bb0SJiri Pirko 
6462b4d8bb0SJiri Pirko 	threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
6472b4d8bb0SJiri Pirko 	return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
6482b4d8bb0SJiri Pirko 					pool_index, threshold, info->extack);
6492b4d8bb0SJiri Pirko }
6502b4d8bb0SJiri Pirko 
6512b4d8bb0SJiri 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)6522b4d8bb0SJiri Pirko devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
6532b4d8bb0SJiri Pirko 				struct devlink_port *devlink_port,
6542b4d8bb0SJiri Pirko 				struct devlink_sb *devlink_sb, u16 tc_index,
6552b4d8bb0SJiri Pirko 				enum devlink_sb_pool_type pool_type,
6562b4d8bb0SJiri Pirko 				enum devlink_command cmd,
6572b4d8bb0SJiri Pirko 				u32 portid, u32 seq, int flags)
6582b4d8bb0SJiri Pirko {
6592b4d8bb0SJiri Pirko 	const struct devlink_ops *ops = devlink->ops;
6602b4d8bb0SJiri Pirko 	u16 pool_index;
6612b4d8bb0SJiri Pirko 	u32 threshold;
6622b4d8bb0SJiri Pirko 	void *hdr;
6632b4d8bb0SJiri Pirko 	int err;
6642b4d8bb0SJiri Pirko 
6652b4d8bb0SJiri Pirko 	err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
6662b4d8bb0SJiri Pirko 				       tc_index, pool_type,
6672b4d8bb0SJiri Pirko 				       &pool_index, &threshold);
6682b4d8bb0SJiri Pirko 	if (err)
6692b4d8bb0SJiri Pirko 		return err;
6702b4d8bb0SJiri Pirko 
6712b4d8bb0SJiri Pirko 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
6722b4d8bb0SJiri Pirko 	if (!hdr)
6732b4d8bb0SJiri Pirko 		return -EMSGSIZE;
6742b4d8bb0SJiri Pirko 
6752b4d8bb0SJiri Pirko 	if (devlink_nl_put_handle(msg, devlink))
6762b4d8bb0SJiri Pirko 		goto nla_put_failure;
6772b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
6782b4d8bb0SJiri Pirko 		goto nla_put_failure;
6792b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
6802b4d8bb0SJiri Pirko 		goto nla_put_failure;
6812b4d8bb0SJiri Pirko 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
6822b4d8bb0SJiri Pirko 		goto nla_put_failure;
6832b4d8bb0SJiri Pirko 	if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
6842b4d8bb0SJiri Pirko 		goto nla_put_failure;
6852b4d8bb0SJiri Pirko 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
6862b4d8bb0SJiri Pirko 		goto nla_put_failure;
6872b4d8bb0SJiri Pirko 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
6882b4d8bb0SJiri Pirko 		goto nla_put_failure;
6892b4d8bb0SJiri Pirko 
6902b4d8bb0SJiri Pirko 	if (ops->sb_occ_tc_port_bind_get) {
6912b4d8bb0SJiri Pirko 		u32 cur;
6922b4d8bb0SJiri Pirko 		u32 max;
6932b4d8bb0SJiri Pirko 
6942b4d8bb0SJiri Pirko 		err = ops->sb_occ_tc_port_bind_get(devlink_port,
6952b4d8bb0SJiri Pirko 						   devlink_sb->index,
6962b4d8bb0SJiri Pirko 						   tc_index, pool_type,
6972b4d8bb0SJiri Pirko 						   &cur, &max);
6982b4d8bb0SJiri Pirko 		if (err && err != -EOPNOTSUPP)
6992b4d8bb0SJiri Pirko 			return err;
7002b4d8bb0SJiri Pirko 		if (!err) {
7012b4d8bb0SJiri Pirko 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
7022b4d8bb0SJiri Pirko 				goto nla_put_failure;
7032b4d8bb0SJiri Pirko 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
7042b4d8bb0SJiri Pirko 				goto nla_put_failure;
7052b4d8bb0SJiri Pirko 		}
7062b4d8bb0SJiri Pirko 	}
7072b4d8bb0SJiri Pirko 
7082b4d8bb0SJiri Pirko 	genlmsg_end(msg, hdr);
7092b4d8bb0SJiri Pirko 	return 0;
7102b4d8bb0SJiri Pirko 
7112b4d8bb0SJiri Pirko nla_put_failure:
7122b4d8bb0SJiri Pirko 	genlmsg_cancel(msg, hdr);
7132b4d8bb0SJiri Pirko 	return -EMSGSIZE;
7142b4d8bb0SJiri Pirko }
7152b4d8bb0SJiri Pirko 
devlink_nl_sb_tc_pool_bind_get_doit(struct sk_buff * skb,struct genl_info * info)7162b4d8bb0SJiri Pirko int devlink_nl_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
7172b4d8bb0SJiri Pirko 					struct genl_info *info)
7182b4d8bb0SJiri Pirko {
7192b4d8bb0SJiri Pirko 	struct devlink_port *devlink_port = info->user_ptr[1];
7202b4d8bb0SJiri Pirko 	struct devlink *devlink = devlink_port->devlink;
7212b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
7222b4d8bb0SJiri Pirko 	struct sk_buff *msg;
7232b4d8bb0SJiri Pirko 	enum devlink_sb_pool_type pool_type;
7242b4d8bb0SJiri Pirko 	u16 tc_index;
7252b4d8bb0SJiri Pirko 	int err;
7262b4d8bb0SJiri Pirko 
7272b4d8bb0SJiri Pirko 	devlink_sb = devlink_sb_get_from_info(devlink, info);
7282b4d8bb0SJiri Pirko 	if (IS_ERR(devlink_sb))
7292b4d8bb0SJiri Pirko 		return PTR_ERR(devlink_sb);
7302b4d8bb0SJiri Pirko 
7312b4d8bb0SJiri Pirko 	err = devlink_sb_pool_type_get_from_info(info, &pool_type);
7322b4d8bb0SJiri Pirko 	if (err)
7332b4d8bb0SJiri Pirko 		return err;
7342b4d8bb0SJiri Pirko 
7352b4d8bb0SJiri Pirko 	err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
7362b4d8bb0SJiri Pirko 						pool_type, &tc_index);
7372b4d8bb0SJiri Pirko 	if (err)
7382b4d8bb0SJiri Pirko 		return err;
7392b4d8bb0SJiri Pirko 
7402b4d8bb0SJiri Pirko 	if (!devlink->ops->sb_tc_pool_bind_get)
7412b4d8bb0SJiri Pirko 		return -EOPNOTSUPP;
7422b4d8bb0SJiri Pirko 
7432b4d8bb0SJiri Pirko 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7442b4d8bb0SJiri Pirko 	if (!msg)
7452b4d8bb0SJiri Pirko 		return -ENOMEM;
7462b4d8bb0SJiri Pirko 
7472b4d8bb0SJiri Pirko 	err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
7482b4d8bb0SJiri Pirko 					      devlink_sb, tc_index, pool_type,
7492b4d8bb0SJiri Pirko 					      DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
7502b4d8bb0SJiri Pirko 					      info->snd_portid,
7512b4d8bb0SJiri Pirko 					      info->snd_seq, 0);
7522b4d8bb0SJiri Pirko 	if (err) {
7532b4d8bb0SJiri Pirko 		nlmsg_free(msg);
7542b4d8bb0SJiri Pirko 		return err;
7552b4d8bb0SJiri Pirko 	}
7562b4d8bb0SJiri Pirko 
7572b4d8bb0SJiri Pirko 	return genlmsg_reply(msg, info);
7582b4d8bb0SJiri Pirko }
7592b4d8bb0SJiri 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)7602b4d8bb0SJiri Pirko static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
7612b4d8bb0SJiri Pirko 					int start, int *p_idx,
7622b4d8bb0SJiri Pirko 					struct devlink *devlink,
7632b4d8bb0SJiri Pirko 					struct devlink_sb *devlink_sb,
7642b4d8bb0SJiri Pirko 					u32 portid, u32 seq, int flags)
7652b4d8bb0SJiri Pirko {
7662b4d8bb0SJiri Pirko 	struct devlink_port *devlink_port;
7672b4d8bb0SJiri Pirko 	unsigned long port_index;
7682b4d8bb0SJiri Pirko 	u16 tc_index;
7692b4d8bb0SJiri Pirko 	int err;
7702b4d8bb0SJiri Pirko 
7712b4d8bb0SJiri Pirko 	xa_for_each(&devlink->ports, port_index, devlink_port) {
7722b4d8bb0SJiri Pirko 		for (tc_index = 0;
7732b4d8bb0SJiri Pirko 		     tc_index < devlink_sb->ingress_tc_count; tc_index++) {
7742b4d8bb0SJiri Pirko 			if (*p_idx < start) {
7752b4d8bb0SJiri Pirko 				(*p_idx)++;
7762b4d8bb0SJiri Pirko 				continue;
7772b4d8bb0SJiri Pirko 			}
7782b4d8bb0SJiri Pirko 			err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
7792b4d8bb0SJiri Pirko 							      devlink_port,
7802b4d8bb0SJiri Pirko 							      devlink_sb,
7812b4d8bb0SJiri Pirko 							      tc_index,
7822b4d8bb0SJiri Pirko 							      DEVLINK_SB_POOL_TYPE_INGRESS,
7832b4d8bb0SJiri Pirko 							      DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
7842b4d8bb0SJiri Pirko 							      portid, seq,
7852b4d8bb0SJiri Pirko 							      flags);
7862b4d8bb0SJiri Pirko 			if (err)
7872b4d8bb0SJiri Pirko 				return err;
7882b4d8bb0SJiri Pirko 			(*p_idx)++;
7892b4d8bb0SJiri Pirko 		}
7902b4d8bb0SJiri Pirko 		for (tc_index = 0;
7912b4d8bb0SJiri Pirko 		     tc_index < devlink_sb->egress_tc_count; tc_index++) {
7922b4d8bb0SJiri Pirko 			if (*p_idx < start) {
7932b4d8bb0SJiri Pirko 				(*p_idx)++;
7942b4d8bb0SJiri Pirko 				continue;
7952b4d8bb0SJiri Pirko 			}
7962b4d8bb0SJiri Pirko 			err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
7972b4d8bb0SJiri Pirko 							      devlink_port,
7982b4d8bb0SJiri Pirko 							      devlink_sb,
7992b4d8bb0SJiri Pirko 							      tc_index,
8002b4d8bb0SJiri Pirko 							      DEVLINK_SB_POOL_TYPE_EGRESS,
8012b4d8bb0SJiri Pirko 							      DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
8022b4d8bb0SJiri Pirko 							      portid, seq,
8032b4d8bb0SJiri Pirko 							      flags);
8042b4d8bb0SJiri Pirko 			if (err)
8052b4d8bb0SJiri Pirko 				return err;
8062b4d8bb0SJiri Pirko 			(*p_idx)++;
8072b4d8bb0SJiri Pirko 		}
8082b4d8bb0SJiri Pirko 	}
8092b4d8bb0SJiri Pirko 	return 0;
8102b4d8bb0SJiri Pirko }
8112b4d8bb0SJiri Pirko 
devlink_nl_sb_tc_pool_bind_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)8122b4d8bb0SJiri Pirko static int devlink_nl_sb_tc_pool_bind_get_dump_one(struct sk_buff *msg,
8132b4d8bb0SJiri Pirko 						   struct devlink *devlink,
8142b4d8bb0SJiri Pirko 						   struct netlink_callback *cb,
8152b4d8bb0SJiri Pirko 						   int flags)
8162b4d8bb0SJiri Pirko {
8172b4d8bb0SJiri Pirko 	struct devlink_nl_dump_state *state = devlink_dump_state(cb);
8182b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
8192b4d8bb0SJiri Pirko 	int idx = 0;
8202b4d8bb0SJiri Pirko 	int err = 0;
8212b4d8bb0SJiri Pirko 
8222b4d8bb0SJiri Pirko 	if (!devlink->ops->sb_tc_pool_bind_get)
8232b4d8bb0SJiri Pirko 		return 0;
8242b4d8bb0SJiri Pirko 
8252b4d8bb0SJiri Pirko 	list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
8262b4d8bb0SJiri Pirko 		err = __sb_tc_pool_bind_get_dumpit(msg, state->idx, &idx,
8272b4d8bb0SJiri Pirko 						   devlink, devlink_sb,
8282b4d8bb0SJiri Pirko 						   NETLINK_CB(cb->skb).portid,
8292b4d8bb0SJiri Pirko 						   cb->nlh->nlmsg_seq, flags);
8302b4d8bb0SJiri Pirko 		if (err == -EOPNOTSUPP) {
8312b4d8bb0SJiri Pirko 			err = 0;
8322b4d8bb0SJiri Pirko 		} else if (err) {
8332b4d8bb0SJiri Pirko 			state->idx = idx;
8342b4d8bb0SJiri Pirko 			break;
8352b4d8bb0SJiri Pirko 		}
8362b4d8bb0SJiri Pirko 	}
8372b4d8bb0SJiri Pirko 
8382b4d8bb0SJiri Pirko 	return err;
8392b4d8bb0SJiri Pirko }
8402b4d8bb0SJiri Pirko 
devlink_nl_sb_tc_pool_bind_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)8412b4d8bb0SJiri Pirko int devlink_nl_sb_tc_pool_bind_get_dumpit(struct sk_buff *skb,
8422b4d8bb0SJiri Pirko 					  struct netlink_callback *cb)
8432b4d8bb0SJiri Pirko {
8442b4d8bb0SJiri Pirko 	return devlink_nl_dumpit(skb, cb,
8452b4d8bb0SJiri Pirko 				 devlink_nl_sb_tc_pool_bind_get_dump_one);
8462b4d8bb0SJiri Pirko }
8472b4d8bb0SJiri 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)8482b4d8bb0SJiri Pirko static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
8492b4d8bb0SJiri Pirko 				       unsigned int sb_index, u16 tc_index,
8502b4d8bb0SJiri Pirko 				       enum devlink_sb_pool_type pool_type,
8512b4d8bb0SJiri Pirko 				       u16 pool_index, u32 threshold,
8522b4d8bb0SJiri Pirko 				       struct netlink_ext_ack *extack)
8532b4d8bb0SJiri Pirko 
8542b4d8bb0SJiri Pirko {
8552b4d8bb0SJiri Pirko 	const struct devlink_ops *ops = devlink_port->devlink->ops;
8562b4d8bb0SJiri Pirko 
8572b4d8bb0SJiri Pirko 	if (ops->sb_tc_pool_bind_set)
8582b4d8bb0SJiri Pirko 		return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
8592b4d8bb0SJiri Pirko 						tc_index, pool_type,
8602b4d8bb0SJiri Pirko 						pool_index, threshold, extack);
8612b4d8bb0SJiri Pirko 	return -EOPNOTSUPP;
8622b4d8bb0SJiri Pirko }
8632b4d8bb0SJiri Pirko 
devlink_nl_sb_tc_pool_bind_set_doit(struct sk_buff * skb,struct genl_info * info)864*53590934SJiri Pirko int devlink_nl_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
8652b4d8bb0SJiri Pirko 					struct genl_info *info)
8662b4d8bb0SJiri Pirko {
8672b4d8bb0SJiri Pirko 	struct devlink_port *devlink_port = info->user_ptr[1];
8682b4d8bb0SJiri Pirko 	struct devlink *devlink = info->user_ptr[0];
8692b4d8bb0SJiri Pirko 	enum devlink_sb_pool_type pool_type;
8702b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
8712b4d8bb0SJiri Pirko 	u16 tc_index;
8722b4d8bb0SJiri Pirko 	u16 pool_index;
8732b4d8bb0SJiri Pirko 	u32 threshold;
8742b4d8bb0SJiri Pirko 	int err;
8752b4d8bb0SJiri Pirko 
8762b4d8bb0SJiri Pirko 	devlink_sb = devlink_sb_get_from_info(devlink, info);
8772b4d8bb0SJiri Pirko 	if (IS_ERR(devlink_sb))
8782b4d8bb0SJiri Pirko 		return PTR_ERR(devlink_sb);
8792b4d8bb0SJiri Pirko 
8802b4d8bb0SJiri Pirko 	err = devlink_sb_pool_type_get_from_info(info, &pool_type);
8812b4d8bb0SJiri Pirko 	if (err)
8822b4d8bb0SJiri Pirko 		return err;
8832b4d8bb0SJiri Pirko 
8842b4d8bb0SJiri Pirko 	err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
8852b4d8bb0SJiri Pirko 						pool_type, &tc_index);
8862b4d8bb0SJiri Pirko 	if (err)
8872b4d8bb0SJiri Pirko 		return err;
8882b4d8bb0SJiri Pirko 
8892b4d8bb0SJiri Pirko 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
8902b4d8bb0SJiri Pirko 						  &pool_index);
8912b4d8bb0SJiri Pirko 	if (err)
8922b4d8bb0SJiri Pirko 		return err;
8932b4d8bb0SJiri Pirko 
8942b4d8bb0SJiri Pirko 	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD))
8952b4d8bb0SJiri Pirko 		return -EINVAL;
8962b4d8bb0SJiri Pirko 
8972b4d8bb0SJiri Pirko 	threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
8982b4d8bb0SJiri Pirko 	return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
8992b4d8bb0SJiri Pirko 					   tc_index, pool_type,
9002b4d8bb0SJiri Pirko 					   pool_index, threshold, info->extack);
9012b4d8bb0SJiri Pirko }
9022b4d8bb0SJiri Pirko 
devlink_nl_sb_occ_snapshot_doit(struct sk_buff * skb,struct genl_info * info)903*53590934SJiri Pirko int devlink_nl_sb_occ_snapshot_doit(struct sk_buff *skb, struct genl_info *info)
9042b4d8bb0SJiri Pirko {
9052b4d8bb0SJiri Pirko 	struct devlink *devlink = info->user_ptr[0];
9062b4d8bb0SJiri Pirko 	const struct devlink_ops *ops = devlink->ops;
9072b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
9082b4d8bb0SJiri Pirko 
9092b4d8bb0SJiri Pirko 	devlink_sb = devlink_sb_get_from_info(devlink, info);
9102b4d8bb0SJiri Pirko 	if (IS_ERR(devlink_sb))
9112b4d8bb0SJiri Pirko 		return PTR_ERR(devlink_sb);
9122b4d8bb0SJiri Pirko 
9132b4d8bb0SJiri Pirko 	if (ops->sb_occ_snapshot)
9142b4d8bb0SJiri Pirko 		return ops->sb_occ_snapshot(devlink, devlink_sb->index);
9152b4d8bb0SJiri Pirko 	return -EOPNOTSUPP;
9162b4d8bb0SJiri Pirko }
9172b4d8bb0SJiri Pirko 
devlink_nl_sb_occ_max_clear_doit(struct sk_buff * skb,struct genl_info * info)918*53590934SJiri Pirko int devlink_nl_sb_occ_max_clear_doit(struct sk_buff *skb,
9192b4d8bb0SJiri Pirko 				     struct genl_info *info)
9202b4d8bb0SJiri Pirko {
9212b4d8bb0SJiri Pirko 	struct devlink *devlink = info->user_ptr[0];
9222b4d8bb0SJiri Pirko 	const struct devlink_ops *ops = devlink->ops;
9232b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
9242b4d8bb0SJiri Pirko 
9252b4d8bb0SJiri Pirko 	devlink_sb = devlink_sb_get_from_info(devlink, info);
9262b4d8bb0SJiri Pirko 	if (IS_ERR(devlink_sb))
9272b4d8bb0SJiri Pirko 		return PTR_ERR(devlink_sb);
9282b4d8bb0SJiri Pirko 
9292b4d8bb0SJiri Pirko 	if (ops->sb_occ_max_clear)
9302b4d8bb0SJiri Pirko 		return ops->sb_occ_max_clear(devlink, devlink_sb->index);
9312b4d8bb0SJiri Pirko 	return -EOPNOTSUPP;
9322b4d8bb0SJiri Pirko }
9332b4d8bb0SJiri 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)9342b4d8bb0SJiri Pirko int devl_sb_register(struct devlink *devlink, unsigned int sb_index,
9352b4d8bb0SJiri Pirko 		     u32 size, u16 ingress_pools_count,
9362b4d8bb0SJiri Pirko 		     u16 egress_pools_count, u16 ingress_tc_count,
9372b4d8bb0SJiri Pirko 		     u16 egress_tc_count)
9382b4d8bb0SJiri Pirko {
9392b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
9402b4d8bb0SJiri Pirko 
9412b4d8bb0SJiri Pirko 	lockdep_assert_held(&devlink->lock);
9422b4d8bb0SJiri Pirko 
9432b4d8bb0SJiri Pirko 	if (devlink_sb_index_exists(devlink, sb_index))
9442b4d8bb0SJiri Pirko 		return -EEXIST;
9452b4d8bb0SJiri Pirko 
9462b4d8bb0SJiri Pirko 	devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
9472b4d8bb0SJiri Pirko 	if (!devlink_sb)
9482b4d8bb0SJiri Pirko 		return -ENOMEM;
9492b4d8bb0SJiri Pirko 	devlink_sb->index = sb_index;
9502b4d8bb0SJiri Pirko 	devlink_sb->size = size;
9512b4d8bb0SJiri Pirko 	devlink_sb->ingress_pools_count = ingress_pools_count;
9522b4d8bb0SJiri Pirko 	devlink_sb->egress_pools_count = egress_pools_count;
9532b4d8bb0SJiri Pirko 	devlink_sb->ingress_tc_count = ingress_tc_count;
9542b4d8bb0SJiri Pirko 	devlink_sb->egress_tc_count = egress_tc_count;
9552b4d8bb0SJiri Pirko 	list_add_tail(&devlink_sb->list, &devlink->sb_list);
9562b4d8bb0SJiri Pirko 	return 0;
9572b4d8bb0SJiri Pirko }
9582b4d8bb0SJiri Pirko EXPORT_SYMBOL_GPL(devl_sb_register);
9592b4d8bb0SJiri 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)9602b4d8bb0SJiri Pirko int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
9612b4d8bb0SJiri Pirko 			u32 size, u16 ingress_pools_count,
9622b4d8bb0SJiri Pirko 			u16 egress_pools_count, u16 ingress_tc_count,
9632b4d8bb0SJiri Pirko 			u16 egress_tc_count)
9642b4d8bb0SJiri Pirko {
9652b4d8bb0SJiri Pirko 	int err;
9662b4d8bb0SJiri Pirko 
9672b4d8bb0SJiri Pirko 	devl_lock(devlink);
9682b4d8bb0SJiri Pirko 	err = devl_sb_register(devlink, sb_index, size, ingress_pools_count,
9692b4d8bb0SJiri Pirko 			       egress_pools_count, ingress_tc_count,
9702b4d8bb0SJiri Pirko 			       egress_tc_count);
9712b4d8bb0SJiri Pirko 	devl_unlock(devlink);
9722b4d8bb0SJiri Pirko 	return err;
9732b4d8bb0SJiri Pirko }
9742b4d8bb0SJiri Pirko EXPORT_SYMBOL_GPL(devlink_sb_register);
9752b4d8bb0SJiri Pirko 
devl_sb_unregister(struct devlink * devlink,unsigned int sb_index)9762b4d8bb0SJiri Pirko void devl_sb_unregister(struct devlink *devlink, unsigned int sb_index)
9772b4d8bb0SJiri Pirko {
9782b4d8bb0SJiri Pirko 	struct devlink_sb *devlink_sb;
9792b4d8bb0SJiri Pirko 
9802b4d8bb0SJiri Pirko 	lockdep_assert_held(&devlink->lock);
9812b4d8bb0SJiri Pirko 
9822b4d8bb0SJiri Pirko 	devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
9832b4d8bb0SJiri Pirko 	WARN_ON(!devlink_sb);
9842b4d8bb0SJiri Pirko 	list_del(&devlink_sb->list);
9852b4d8bb0SJiri Pirko 	kfree(devlink_sb);
9862b4d8bb0SJiri Pirko }
9872b4d8bb0SJiri Pirko EXPORT_SYMBOL_GPL(devl_sb_unregister);
9882b4d8bb0SJiri Pirko 
devlink_sb_unregister(struct devlink * devlink,unsigned int sb_index)9892b4d8bb0SJiri Pirko void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
9902b4d8bb0SJiri Pirko {
9912b4d8bb0SJiri Pirko 	devl_lock(devlink);
9922b4d8bb0SJiri Pirko 	devl_sb_unregister(devlink, sb_index);
9932b4d8bb0SJiri Pirko 	devl_unlock(devlink);
9942b4d8bb0SJiri Pirko }
9952b4d8bb0SJiri Pirko EXPORT_SYMBOL_GPL(devlink_sb_unregister);
996