~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/devlink/sb.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /net/devlink/sb.c (Architecture alpha) and /net/devlink/sb.c (Architecture i386)


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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php