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