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 struct netlink_ext_ack *extack) 163 { 164 if (!param->set) 165 return -EOPNOTSUPP; 166 return param->set(devlink, param->id, ctx, extack); 167 } 168 169 static int 170 devlink_param_type_to_nla_type(enum devlink_param_type param_type) 171 { 172 switch (param_type) { 173 case DEVLINK_PARAM_TYPE_U8: 174 return NLA_U8; 175 case DEVLINK_PARAM_TYPE_U16: 176 return NLA_U16; 177 case DEVLINK_PARAM_TYPE_U32: 178 return NLA_U32; 179 case DEVLINK_PARAM_TYPE_STRING: 180 return NLA_STRING; 181 case DEVLINK_PARAM_TYPE_BOOL: 182 return NLA_FLAG; 183 default: 184 return -EINVAL; 185 } 186 } 187 188 static int 189 devlink_nl_param_value_fill_one(struct sk_buff *msg, 190 enum devlink_param_type type, 191 enum devlink_param_cmode cmode, 192 union devlink_param_value val) 193 { 194 struct nlattr *param_value_attr; 195 196 param_value_attr = nla_nest_start_noflag(msg, 197 DEVLINK_ATTR_PARAM_VALUE); 198 if (!param_value_attr) 199 goto nla_put_failure; 200 201 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode)) 202 goto value_nest_cancel; 203 204 switch (type) { 205 case DEVLINK_PARAM_TYPE_U8: 206 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8)) 207 goto value_nest_cancel; 208 break; 209 case DEVLINK_PARAM_TYPE_U16: 210 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16)) 211 goto value_nest_cancel; 212 break; 213 case DEVLINK_PARAM_TYPE_U32: 214 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32)) 215 goto value_nest_cancel; 216 break; 217 case DEVLINK_PARAM_TYPE_STRING: 218 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 219 val.vstr)) 220 goto value_nest_cancel; 221 break; 222 case DEVLINK_PARAM_TYPE_BOOL: 223 if (val.vbool && 224 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA)) 225 goto value_nest_cancel; 226 break; 227 } 228 229 nla_nest_end(msg, param_value_attr); 230 return 0; 231 232 value_nest_cancel: 233 nla_nest_cancel(msg, param_value_attr); 234 nla_put_failure: 235 return -EMSGSIZE; 236 } 237 238 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, 239 unsigned int port_index, 240 struct devlink_param_item *param_item, 241 enum devlink_command cmd, 242 u32 portid, u32 seq, int flags) 243 { 244 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1]; 245 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {}; 246 const struct devlink_param *param = param_item->param; 247 struct devlink_param_gset_ctx ctx; 248 struct nlattr *param_values_list; 249 struct nlattr *param_attr; 250 int nla_type; 251 void *hdr; 252 int err; 253 int i; 254 255 /* Get value from driver part to driverinit configuration mode */ 256 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 257 if (!devlink_param_cmode_is_supported(param, i)) 258 continue; 259 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) { 260 if (param_item->driverinit_value_new_valid) 261 param_value[i] = param_item->driverinit_value_new; 262 else if (param_item->driverinit_value_valid) 263 param_value[i] = param_item->driverinit_value; 264 else 265 return -EOPNOTSUPP; 266 } else { 267 ctx.cmode = i; 268 err = devlink_param_get(devlink, param, &ctx); 269 if (err) 270 return err; 271 param_value[i] = ctx.val; 272 } 273 param_value_set[i] = true; 274 } 275 276 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 277 if (!hdr) 278 return -EMSGSIZE; 279 280 if (devlink_nl_put_handle(msg, devlink)) 281 goto genlmsg_cancel; 282 283 if (cmd == DEVLINK_CMD_PORT_PARAM_GET || 284 cmd == DEVLINK_CMD_PORT_PARAM_NEW || 285 cmd == DEVLINK_CMD_PORT_PARAM_DEL) 286 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index)) 287 goto genlmsg_cancel; 288 289 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM); 290 if (!param_attr) 291 goto genlmsg_cancel; 292 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name)) 293 goto param_nest_cancel; 294 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) 295 goto param_nest_cancel; 296 297 nla_type = devlink_param_type_to_nla_type(param->type); 298 if (nla_type < 0) 299 goto param_nest_cancel; 300 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type)) 301 goto param_nest_cancel; 302 303 param_values_list = nla_nest_start_noflag(msg, 304 DEVLINK_ATTR_PARAM_VALUES_LIST); 305 if (!param_values_list) 306 goto param_nest_cancel; 307 308 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 309 if (!param_value_set[i]) 310 continue; 311 err = devlink_nl_param_value_fill_one(msg, param->type, 312 i, param_value[i]); 313 if (err) 314 goto values_list_nest_cancel; 315 } 316 317 nla_nest_end(msg, param_values_list); 318 nla_nest_end(msg, param_attr); 319 genlmsg_end(msg, hdr); 320 return 0; 321 322 values_list_nest_cancel: 323 nla_nest_end(msg, param_values_list); 324 param_nest_cancel: 325 nla_nest_cancel(msg, param_attr); 326 genlmsg_cancel: 327 genlmsg_cancel(msg, hdr); 328 return -EMSGSIZE; 329 } 330 331 static void devlink_param_notify(struct devlink *devlink, 332 unsigned int port_index, 333 struct devlink_param_item *param_item, 334 enum devlink_command cmd) 335 { 336 struct sk_buff *msg; 337 int err; 338 339 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL && 340 cmd != DEVLINK_CMD_PORT_PARAM_NEW && 341 cmd != DEVLINK_CMD_PORT_PARAM_DEL); 342 343 /* devlink_notify_register() / devlink_notify_unregister() 344 * will replay the notifications if the params are added/removed 345 * outside of the lifetime of the instance. 346 */ 347 if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink)) 348 return; 349 350 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 351 if (!msg) 352 return; 353 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd, 354 0, 0, 0); 355 if (err) { 356 nlmsg_free(msg); 357 return; 358 } 359 360 devlink_nl_notify_send(devlink, msg); 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, info->extack); 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_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_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_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_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