at v6.18 24 kB view raw
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 */ 6 7#include "devl_internal.h" 8 9static const struct devlink_param devlink_param_generic[] = { 10 { 11 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET, 12 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME, 13 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE, 14 }, 15 { 16 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS, 17 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME, 18 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE, 19 }, 20 { 21 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, 22 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME, 23 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE, 24 }, 25 { 26 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT, 27 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME, 28 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE, 29 }, 30 { 31 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, 32 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME, 33 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE, 34 }, 35 { 36 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, 37 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME, 38 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE, 39 }, 40 { 41 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, 42 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME, 43 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE, 44 }, 45 { 46 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, 47 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME, 48 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE, 49 }, 50 { 51 .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE, 52 .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME, 53 .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE, 54 }, 55 { 56 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, 57 .name = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_NAME, 58 .type = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_TYPE, 59 }, 60 { 61 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_REMOTE_DEV_RESET, 62 .name = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_NAME, 63 .type = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_TYPE, 64 }, 65 { 66 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH, 67 .name = DEVLINK_PARAM_GENERIC_ENABLE_ETH_NAME, 68 .type = DEVLINK_PARAM_GENERIC_ENABLE_ETH_TYPE, 69 }, 70 { 71 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA, 72 .name = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_NAME, 73 .type = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_TYPE, 74 }, 75 { 76 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET, 77 .name = DEVLINK_PARAM_GENERIC_ENABLE_VNET_NAME, 78 .type = DEVLINK_PARAM_GENERIC_ENABLE_VNET_TYPE, 79 }, 80 { 81 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_IWARP, 82 .name = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_NAME, 83 .type = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_TYPE, 84 }, 85 { 86 .id = DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE, 87 .name = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_NAME, 88 .type = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_TYPE, 89 }, 90 { 91 .id = DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE, 92 .name = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_NAME, 93 .type = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_TYPE, 94 }, 95 { 96 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC, 97 .name = DEVLINK_PARAM_GENERIC_ENABLE_PHC_NAME, 98 .type = DEVLINK_PARAM_GENERIC_ENABLE_PHC_TYPE, 99 }, 100 { 101 .id = DEVLINK_PARAM_GENERIC_ID_CLOCK_ID, 102 .name = DEVLINK_PARAM_GENERIC_CLOCK_ID_NAME, 103 .type = DEVLINK_PARAM_GENERIC_CLOCK_ID_TYPE, 104 }, 105 { 106 .id = DEVLINK_PARAM_GENERIC_ID_TOTAL_VFS, 107 .name = DEVLINK_PARAM_GENERIC_TOTAL_VFS_NAME, 108 .type = DEVLINK_PARAM_GENERIC_TOTAL_VFS_TYPE, 109 }, 110 { 111 .id = DEVLINK_PARAM_GENERIC_ID_NUM_DOORBELLS, 112 .name = DEVLINK_PARAM_GENERIC_NUM_DOORBELLS_NAME, 113 .type = DEVLINK_PARAM_GENERIC_NUM_DOORBELLS_TYPE, 114 }, 115}; 116 117static int devlink_param_generic_verify(const struct devlink_param *param) 118{ 119 /* verify it match generic parameter by id and name */ 120 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX) 121 return -EINVAL; 122 if (strcmp(param->name, devlink_param_generic[param->id].name)) 123 return -ENOENT; 124 125 WARN_ON(param->type != devlink_param_generic[param->id].type); 126 127 return 0; 128} 129 130static int devlink_param_driver_verify(const struct devlink_param *param) 131{ 132 int i; 133 134 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX) 135 return -EINVAL; 136 /* verify no such name in generic params */ 137 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++) 138 if (!strcmp(param->name, devlink_param_generic[i].name)) 139 return -EEXIST; 140 141 return 0; 142} 143 144static struct devlink_param_item * 145devlink_param_find_by_name(struct xarray *params, const char *param_name) 146{ 147 struct devlink_param_item *param_item; 148 unsigned long param_id; 149 150 xa_for_each(params, param_id, param_item) { 151 if (!strcmp(param_item->param->name, param_name)) 152 return param_item; 153 } 154 return NULL; 155} 156 157static struct devlink_param_item * 158devlink_param_find_by_id(struct xarray *params, u32 param_id) 159{ 160 return xa_load(params, param_id); 161} 162 163static bool 164devlink_param_cmode_is_supported(const struct devlink_param *param, 165 enum devlink_param_cmode cmode) 166{ 167 return test_bit(cmode, &param->supported_cmodes); 168} 169 170static int devlink_param_get(struct devlink *devlink, 171 const struct devlink_param *param, 172 struct devlink_param_gset_ctx *ctx) 173{ 174 if (!param->get) 175 return -EOPNOTSUPP; 176 return param->get(devlink, param->id, ctx); 177} 178 179static int devlink_param_set(struct devlink *devlink, 180 const struct devlink_param *param, 181 struct devlink_param_gset_ctx *ctx, 182 struct netlink_ext_ack *extack) 183{ 184 if (!param->set) 185 return -EOPNOTSUPP; 186 return param->set(devlink, param->id, ctx, extack); 187} 188 189static int 190devlink_nl_param_value_fill_one(struct sk_buff *msg, 191 enum devlink_param_type type, 192 enum devlink_param_cmode cmode, 193 union devlink_param_value val) 194{ 195 struct nlattr *param_value_attr; 196 197 param_value_attr = nla_nest_start_noflag(msg, 198 DEVLINK_ATTR_PARAM_VALUE); 199 if (!param_value_attr) 200 goto nla_put_failure; 201 202 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode)) 203 goto value_nest_cancel; 204 205 switch (type) { 206 case DEVLINK_PARAM_TYPE_U8: 207 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8)) 208 goto value_nest_cancel; 209 break; 210 case DEVLINK_PARAM_TYPE_U16: 211 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16)) 212 goto value_nest_cancel; 213 break; 214 case DEVLINK_PARAM_TYPE_U32: 215 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32)) 216 goto value_nest_cancel; 217 break; 218 case DEVLINK_PARAM_TYPE_U64: 219 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 220 val.vu64)) 221 goto value_nest_cancel; 222 break; 223 case DEVLINK_PARAM_TYPE_STRING: 224 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 225 val.vstr)) 226 goto value_nest_cancel; 227 break; 228 case DEVLINK_PARAM_TYPE_BOOL: 229 if (val.vbool && 230 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA)) 231 goto value_nest_cancel; 232 break; 233 } 234 235 nla_nest_end(msg, param_value_attr); 236 return 0; 237 238value_nest_cancel: 239 nla_nest_cancel(msg, param_value_attr); 240nla_put_failure: 241 return -EMSGSIZE; 242} 243 244static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, 245 unsigned int port_index, 246 struct devlink_param_item *param_item, 247 enum devlink_command cmd, 248 u32 portid, u32 seq, int flags) 249{ 250 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1]; 251 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {}; 252 const struct devlink_param *param = param_item->param; 253 struct devlink_param_gset_ctx ctx; 254 struct nlattr *param_values_list; 255 struct nlattr *param_attr; 256 void *hdr; 257 int err; 258 int i; 259 260 /* Get value from driver part to driverinit configuration mode */ 261 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 262 if (!devlink_param_cmode_is_supported(param, i)) 263 continue; 264 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) { 265 if (param_item->driverinit_value_new_valid) 266 param_value[i] = param_item->driverinit_value_new; 267 else if (param_item->driverinit_value_valid) 268 param_value[i] = param_item->driverinit_value; 269 else 270 return -EOPNOTSUPP; 271 } else { 272 ctx.cmode = i; 273 err = devlink_param_get(devlink, param, &ctx); 274 if (err) 275 return err; 276 param_value[i] = ctx.val; 277 } 278 param_value_set[i] = true; 279 } 280 281 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 282 if (!hdr) 283 return -EMSGSIZE; 284 285 if (devlink_nl_put_handle(msg, devlink)) 286 goto genlmsg_cancel; 287 288 if (cmd == DEVLINK_CMD_PORT_PARAM_GET || 289 cmd == DEVLINK_CMD_PORT_PARAM_NEW || 290 cmd == DEVLINK_CMD_PORT_PARAM_DEL) 291 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index)) 292 goto genlmsg_cancel; 293 294 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM); 295 if (!param_attr) 296 goto genlmsg_cancel; 297 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name)) 298 goto param_nest_cancel; 299 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) 300 goto param_nest_cancel; 301 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, param->type)) 302 goto param_nest_cancel; 303 304 param_values_list = nla_nest_start_noflag(msg, 305 DEVLINK_ATTR_PARAM_VALUES_LIST); 306 if (!param_values_list) 307 goto param_nest_cancel; 308 309 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 310 if (!param_value_set[i]) 311 continue; 312 err = devlink_nl_param_value_fill_one(msg, param->type, 313 i, param_value[i]); 314 if (err) 315 goto values_list_nest_cancel; 316 } 317 318 nla_nest_end(msg, param_values_list); 319 nla_nest_end(msg, param_attr); 320 genlmsg_end(msg, hdr); 321 return 0; 322 323values_list_nest_cancel: 324 nla_nest_end(msg, param_values_list); 325param_nest_cancel: 326 nla_nest_cancel(msg, param_attr); 327genlmsg_cancel: 328 genlmsg_cancel(msg, hdr); 329 return -EMSGSIZE; 330} 331 332static void devlink_param_notify(struct devlink *devlink, 333 unsigned int port_index, 334 struct devlink_param_item *param_item, 335 enum devlink_command cmd) 336{ 337 struct sk_buff *msg; 338 int err; 339 340 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL && 341 cmd != DEVLINK_CMD_PORT_PARAM_NEW && 342 cmd != DEVLINK_CMD_PORT_PARAM_DEL); 343 344 /* devlink_notify_register() / devlink_notify_unregister() 345 * will replay the notifications if the params are added/removed 346 * outside of the lifetime of the instance. 347 */ 348 if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink)) 349 return; 350 351 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 352 if (!msg) 353 return; 354 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd, 355 0, 0, 0); 356 if (err) { 357 nlmsg_free(msg); 358 return; 359 } 360 361 devlink_nl_notify_send(devlink, msg); 362} 363 364static void devlink_params_notify(struct devlink *devlink, 365 enum devlink_command cmd) 366{ 367 struct devlink_param_item *param_item; 368 unsigned long param_id; 369 370 xa_for_each(&devlink->params, param_id, param_item) 371 devlink_param_notify(devlink, 0, param_item, cmd); 372} 373 374void devlink_params_notify_register(struct devlink *devlink) 375{ 376 devlink_params_notify(devlink, DEVLINK_CMD_PARAM_NEW); 377} 378 379void devlink_params_notify_unregister(struct devlink *devlink) 380{ 381 devlink_params_notify(devlink, DEVLINK_CMD_PARAM_DEL); 382} 383 384static int devlink_nl_param_get_dump_one(struct sk_buff *msg, 385 struct devlink *devlink, 386 struct netlink_callback *cb, 387 int flags) 388{ 389 struct devlink_nl_dump_state *state = devlink_dump_state(cb); 390 struct devlink_param_item *param_item; 391 unsigned long param_id; 392 int err = 0; 393 394 xa_for_each_start(&devlink->params, param_id, param_item, state->idx) { 395 err = devlink_nl_param_fill(msg, devlink, 0, param_item, 396 DEVLINK_CMD_PARAM_GET, 397 NETLINK_CB(cb->skb).portid, 398 cb->nlh->nlmsg_seq, flags); 399 if (err == -EOPNOTSUPP) { 400 err = 0; 401 } else if (err) { 402 state->idx = param_id; 403 break; 404 } 405 } 406 407 return err; 408} 409 410int devlink_nl_param_get_dumpit(struct sk_buff *skb, 411 struct netlink_callback *cb) 412{ 413 return devlink_nl_dumpit(skb, cb, devlink_nl_param_get_dump_one); 414} 415 416static int 417devlink_param_type_get_from_info(struct genl_info *info, 418 enum devlink_param_type *param_type) 419{ 420 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE)) 421 return -EINVAL; 422 423 *param_type = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE]); 424 425 return 0; 426} 427 428static int 429devlink_param_value_get_from_info(const struct devlink_param *param, 430 struct genl_info *info, 431 union devlink_param_value *value) 432{ 433 struct nlattr *param_data; 434 int len; 435 436 param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]; 437 438 if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data) 439 return -EINVAL; 440 441 switch (param->type) { 442 case DEVLINK_PARAM_TYPE_U8: 443 if (nla_len(param_data) != sizeof(u8)) 444 return -EINVAL; 445 value->vu8 = nla_get_u8(param_data); 446 break; 447 case DEVLINK_PARAM_TYPE_U16: 448 if (nla_len(param_data) != sizeof(u16)) 449 return -EINVAL; 450 value->vu16 = nla_get_u16(param_data); 451 break; 452 case DEVLINK_PARAM_TYPE_U32: 453 if (nla_len(param_data) != sizeof(u32)) 454 return -EINVAL; 455 value->vu32 = nla_get_u32(param_data); 456 break; 457 case DEVLINK_PARAM_TYPE_U64: 458 if (nla_len(param_data) != sizeof(u64)) 459 return -EINVAL; 460 value->vu64 = nla_get_u64(param_data); 461 break; 462 case DEVLINK_PARAM_TYPE_STRING: 463 len = strnlen(nla_data(param_data), nla_len(param_data)); 464 if (len == nla_len(param_data) || 465 len >= __DEVLINK_PARAM_MAX_STRING_VALUE) 466 return -EINVAL; 467 strcpy(value->vstr, nla_data(param_data)); 468 break; 469 case DEVLINK_PARAM_TYPE_BOOL: 470 if (param_data && nla_len(param_data)) 471 return -EINVAL; 472 value->vbool = nla_get_flag(param_data); 473 break; 474 } 475 return 0; 476} 477 478static struct devlink_param_item * 479devlink_param_get_from_info(struct xarray *params, struct genl_info *info) 480{ 481 char *param_name; 482 483 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME)) 484 return NULL; 485 486 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]); 487 return devlink_param_find_by_name(params, param_name); 488} 489 490int devlink_nl_param_get_doit(struct sk_buff *skb, 491 struct genl_info *info) 492{ 493 struct devlink *devlink = info->user_ptr[0]; 494 struct devlink_param_item *param_item; 495 struct sk_buff *msg; 496 int err; 497 498 param_item = devlink_param_get_from_info(&devlink->params, info); 499 if (!param_item) 500 return -EINVAL; 501 502 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 503 if (!msg) 504 return -ENOMEM; 505 506 err = devlink_nl_param_fill(msg, devlink, 0, param_item, 507 DEVLINK_CMD_PARAM_GET, 508 info->snd_portid, info->snd_seq, 0); 509 if (err) { 510 nlmsg_free(msg); 511 return err; 512 } 513 514 return genlmsg_reply(msg, info); 515} 516 517static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink, 518 unsigned int port_index, 519 struct xarray *params, 520 struct genl_info *info, 521 enum devlink_command cmd) 522{ 523 enum devlink_param_type param_type; 524 struct devlink_param_gset_ctx ctx; 525 enum devlink_param_cmode cmode; 526 struct devlink_param_item *param_item; 527 const struct devlink_param *param; 528 union devlink_param_value value; 529 int err = 0; 530 531 param_item = devlink_param_get_from_info(params, info); 532 if (!param_item) 533 return -EINVAL; 534 param = param_item->param; 535 err = devlink_param_type_get_from_info(info, &param_type); 536 if (err) 537 return err; 538 if (param_type != param->type) 539 return -EINVAL; 540 err = devlink_param_value_get_from_info(param, info, &value); 541 if (err) 542 return err; 543 if (param->validate) { 544 err = param->validate(devlink, param->id, value, info->extack); 545 if (err) 546 return err; 547 } 548 549 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE)) 550 return -EINVAL; 551 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]); 552 if (!devlink_param_cmode_is_supported(param, cmode)) 553 return -EOPNOTSUPP; 554 555 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) { 556 param_item->driverinit_value_new = value; 557 param_item->driverinit_value_new_valid = true; 558 } else { 559 if (!param->set) 560 return -EOPNOTSUPP; 561 ctx.val = value; 562 ctx.cmode = cmode; 563 err = devlink_param_set(devlink, param, &ctx, info->extack); 564 if (err) 565 return err; 566 } 567 568 devlink_param_notify(devlink, port_index, param_item, cmd); 569 return 0; 570} 571 572int devlink_nl_param_set_doit(struct sk_buff *skb, struct genl_info *info) 573{ 574 struct devlink *devlink = info->user_ptr[0]; 575 576 return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->params, 577 info, DEVLINK_CMD_PARAM_NEW); 578} 579 580int devlink_nl_port_param_get_dumpit(struct sk_buff *msg, 581 struct netlink_callback *cb) 582{ 583 NL_SET_ERR_MSG(cb->extack, "Port params are not supported"); 584 return msg->len; 585} 586 587int devlink_nl_port_param_get_doit(struct sk_buff *skb, 588 struct genl_info *info) 589{ 590 NL_SET_ERR_MSG(info->extack, "Port params are not supported"); 591 return -EINVAL; 592} 593 594int devlink_nl_port_param_set_doit(struct sk_buff *skb, 595 struct genl_info *info) 596{ 597 NL_SET_ERR_MSG(info->extack, "Port params are not supported"); 598 return -EINVAL; 599} 600 601static int devlink_param_verify(const struct devlink_param *param) 602{ 603 if (!param || !param->name || !param->supported_cmodes) 604 return -EINVAL; 605 if (param->generic) 606 return devlink_param_generic_verify(param); 607 else 608 return devlink_param_driver_verify(param); 609} 610 611static int devlink_param_register(struct devlink *devlink, 612 const struct devlink_param *param) 613{ 614 struct devlink_param_item *param_item; 615 int err; 616 617 WARN_ON(devlink_param_verify(param)); 618 WARN_ON(devlink_param_find_by_name(&devlink->params, param->name)); 619 620 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT)) 621 WARN_ON(param->get || param->set); 622 else 623 WARN_ON(!param->get || !param->set); 624 625 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL); 626 if (!param_item) 627 return -ENOMEM; 628 629 param_item->param = param; 630 631 err = xa_insert(&devlink->params, param->id, param_item, GFP_KERNEL); 632 if (err) 633 goto err_xa_insert; 634 635 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 636 return 0; 637 638err_xa_insert: 639 kfree(param_item); 640 return err; 641} 642 643static void devlink_param_unregister(struct devlink *devlink, 644 const struct devlink_param *param) 645{ 646 struct devlink_param_item *param_item; 647 648 param_item = devlink_param_find_by_id(&devlink->params, param->id); 649 if (WARN_ON(!param_item)) 650 return; 651 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_DEL); 652 xa_erase(&devlink->params, param->id); 653 kfree(param_item); 654} 655 656/** 657 * devl_params_register - register configuration parameters 658 * 659 * @devlink: devlink 660 * @params: configuration parameters array 661 * @params_count: number of parameters provided 662 * 663 * Register the configuration parameters supported by the driver. 664 */ 665int devl_params_register(struct devlink *devlink, 666 const struct devlink_param *params, 667 size_t params_count) 668{ 669 const struct devlink_param *param = params; 670 int i, err; 671 672 lockdep_assert_held(&devlink->lock); 673 674 for (i = 0; i < params_count; i++, param++) { 675 err = devlink_param_register(devlink, param); 676 if (err) 677 goto rollback; 678 } 679 return 0; 680 681rollback: 682 if (!i) 683 return err; 684 685 for (param--; i > 0; i--, param--) 686 devlink_param_unregister(devlink, param); 687 return err; 688} 689EXPORT_SYMBOL_GPL(devl_params_register); 690 691int devlink_params_register(struct devlink *devlink, 692 const struct devlink_param *params, 693 size_t params_count) 694{ 695 int err; 696 697 devl_lock(devlink); 698 err = devl_params_register(devlink, params, params_count); 699 devl_unlock(devlink); 700 return err; 701} 702EXPORT_SYMBOL_GPL(devlink_params_register); 703 704/** 705 * devl_params_unregister - unregister configuration parameters 706 * @devlink: devlink 707 * @params: configuration parameters to unregister 708 * @params_count: number of parameters provided 709 */ 710void devl_params_unregister(struct devlink *devlink, 711 const struct devlink_param *params, 712 size_t params_count) 713{ 714 const struct devlink_param *param = params; 715 int i; 716 717 lockdep_assert_held(&devlink->lock); 718 719 for (i = 0; i < params_count; i++, param++) 720 devlink_param_unregister(devlink, param); 721} 722EXPORT_SYMBOL_GPL(devl_params_unregister); 723 724void devlink_params_unregister(struct devlink *devlink, 725 const struct devlink_param *params, 726 size_t params_count) 727{ 728 devl_lock(devlink); 729 devl_params_unregister(devlink, params, params_count); 730 devl_unlock(devlink); 731} 732EXPORT_SYMBOL_GPL(devlink_params_unregister); 733 734/** 735 * devl_param_driverinit_value_get - get configuration parameter 736 * value for driver initializing 737 * 738 * @devlink: devlink 739 * @param_id: parameter ID 740 * @val: pointer to store the value of parameter in driverinit 741 * configuration mode 742 * 743 * This function should be used by the driver to get driverinit 744 * configuration for initialization after reload command. 745 * 746 * Note that lockless call of this function relies on the 747 * driver to maintain following basic sane behavior: 748 * 1) Driver ensures a call to this function cannot race with 749 * registering/unregistering the parameter with the same parameter ID. 750 * 2) Driver ensures a call to this function cannot race with 751 * devl_param_driverinit_value_set() call with the same parameter ID. 752 * 3) Driver ensures a call to this function cannot race with 753 * reload operation. 754 * If the driver is not able to comply, it has to take the devlink->lock 755 * while calling this. 756 */ 757int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id, 758 union devlink_param_value *val) 759{ 760 struct devlink_param_item *param_item; 761 762 if (WARN_ON(!devlink_reload_supported(devlink->ops))) 763 return -EOPNOTSUPP; 764 765 param_item = devlink_param_find_by_id(&devlink->params, param_id); 766 if (!param_item) 767 return -EINVAL; 768 769 if (!param_item->driverinit_value_valid) 770 return -EOPNOTSUPP; 771 772 if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param, 773 DEVLINK_PARAM_CMODE_DRIVERINIT))) 774 return -EOPNOTSUPP; 775 776 *val = param_item->driverinit_value; 777 778 return 0; 779} 780EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get); 781 782/** 783 * devl_param_driverinit_value_set - set value of configuration 784 * parameter for driverinit 785 * configuration mode 786 * 787 * @devlink: devlink 788 * @param_id: parameter ID 789 * @init_val: value of parameter to set for driverinit configuration mode 790 * 791 * This function should be used by the driver to set driverinit 792 * configuration mode default value. 793 */ 794void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 795 union devlink_param_value init_val) 796{ 797 struct devlink_param_item *param_item; 798 799 devl_assert_locked(devlink); 800 801 param_item = devlink_param_find_by_id(&devlink->params, param_id); 802 if (WARN_ON(!param_item)) 803 return; 804 805 if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param, 806 DEVLINK_PARAM_CMODE_DRIVERINIT))) 807 return; 808 809 param_item->driverinit_value = init_val; 810 param_item->driverinit_value_valid = true; 811 812 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 813} 814EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set); 815 816void devlink_params_driverinit_load_new(struct devlink *devlink) 817{ 818 struct devlink_param_item *param_item; 819 unsigned long param_id; 820 821 xa_for_each(&devlink->params, param_id, param_item) { 822 if (!devlink_param_cmode_is_supported(param_item->param, 823 DEVLINK_PARAM_CMODE_DRIVERINIT) || 824 !param_item->driverinit_value_new_valid) 825 continue; 826 param_item->driverinit_value = param_item->driverinit_value_new; 827 param_item->driverinit_value_valid = true; 828 param_item->driverinit_value_new_valid = false; 829 } 830} 831 832/** 833 * devl_param_value_changed - notify devlink on a parameter's value 834 * change. Should be called by the driver 835 * right after the change. 836 * 837 * @devlink: devlink 838 * @param_id: parameter ID 839 * 840 * This function should be used by the driver to notify devlink on value 841 * change, excluding driverinit configuration mode. 842 * For driverinit configuration mode driver should use the function 843 */ 844void devl_param_value_changed(struct devlink *devlink, u32 param_id) 845{ 846 struct devlink_param_item *param_item; 847 848 param_item = devlink_param_find_by_id(&devlink->params, param_id); 849 WARN_ON(!param_item); 850 851 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 852} 853EXPORT_SYMBOL_GPL(devl_param_value_changed);