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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.