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 .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 117 static 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 130 static 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 144 static struct devlink_param_item * 145 devlink_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 157 static struct devlink_param_item * 158 devlink_param_find_by_id(struct xarray *params, u32 param_id) 159 { 160 return xa_load(params, param_id); 161 } 162 163 static bool 164 devlink_param_cmode_is_supported(const struct devlink_param *param, 165 enum devlink_param_cmode cmode) 166 { 167 return test_bit(cmode, ¶m->supported_cmodes); 168 } 169 170 static 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 179 static 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 189 static int 190 devlink_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 238 value_nest_cancel: 239 nla_nest_cancel(msg, param_value_attr); 240 nla_put_failure: 241 return -EMSGSIZE; 242 } 243 244 static 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 323 values_list_nest_cancel: 324 nla_nest_end(msg, param_values_list); 325 param_nest_cancel: 326 nla_nest_cancel(msg, param_attr); 327 genlmsg_cancel: 328 genlmsg_cancel(msg, hdr); 329 return -EMSGSIZE; 330 } 331 332 static 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 364 static 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 374 void devlink_params_notify_register(struct devlink *devlink) 375 { 376 devlink_params_notify(devlink, DEVLINK_CMD_PARAM_NEW); 377 } 378 379 void devlink_params_notify_unregister(struct devlink *devlink) 380 { 381 devlink_params_notify(devlink, DEVLINK_CMD_PARAM_DEL); 382 } 383 384 static 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 410 int 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 416 static int 417 devlink_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 428 static int 429 devlink_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 478 static struct devlink_param_item * 479 devlink_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 490 int 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 517 static 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, ¶m_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 572 int 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 580 int 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 587 int 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 594 int 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 601 static 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 611 static 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 638 err_xa_insert: 639 kfree(param_item); 640 return err; 641 } 642 643 static 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 */ 665 int 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 681 rollback: 682 if (!i) 683 return err; 684 685 for (param--; i > 0; i--, param--) 686 devlink_param_unregister(devlink, param); 687 return err; 688 } 689 EXPORT_SYMBOL_GPL(devl_params_register); 690 691 int 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 } 702 EXPORT_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 */ 710 void 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 } 722 EXPORT_SYMBOL_GPL(devl_params_unregister); 723 724 void 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 } 732 EXPORT_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 */ 757 int 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 } 780 EXPORT_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 */ 794 void 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 } 814 EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set); 815 816 void 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 */ 844 void 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 } 853 EXPORT_SYMBOL_GPL(devl_param_value_changed); 854