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