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