1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Generic netlink for DPLL management framework 4 * 5 * Copyright (c) 2023 Meta Platforms, Inc. and affiliates 6 * Copyright (c) 2023 Intel and affiliates 7 * 8 */ 9 #include <linux/module.h> 10 #include <linux/kernel.h> 11 #include <net/genetlink.h> 12 #include "dpll_core.h" 13 #include "dpll_netlink.h" 14 #include "dpll_nl.h" 15 #include <uapi/linux/dpll.h> 16 17 #define ASSERT_NOT_NULL(ptr) (WARN_ON(!ptr)) 18 19 #define xa_for_each_marked_start(xa, index, entry, filter, start) \ 20 for (index = start, entry = xa_find(xa, &index, ULONG_MAX, filter); \ 21 entry; entry = xa_find_after(xa, &index, ULONG_MAX, filter)) 22 23 struct dpll_dump_ctx { 24 unsigned long idx; 25 }; 26 27 static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb) 28 { 29 return (struct dpll_dump_ctx *)cb->ctx; 30 } 31 32 static int 33 dpll_msg_add_dev_handle(struct sk_buff *msg, struct dpll_device *dpll) 34 { 35 if (nla_put_u32(msg, DPLL_A_ID, dpll->id)) 36 return -EMSGSIZE; 37 38 return 0; 39 } 40 41 static int 42 dpll_msg_add_dev_parent_handle(struct sk_buff *msg, u32 id) 43 { 44 if (nla_put_u32(msg, DPLL_A_PIN_PARENT_ID, id)) 45 return -EMSGSIZE; 46 47 return 0; 48 } 49 50 /** 51 * dpll_msg_pin_handle_size - get size of pin handle attribute for given pin 52 * @pin: pin pointer 53 * 54 * Return: byte size of pin handle attribute for given pin. 55 */ 56 size_t dpll_msg_pin_handle_size(struct dpll_pin *pin) 57 { 58 return pin ? nla_total_size(4) : 0; /* DPLL_A_PIN_ID */ 59 } 60 EXPORT_SYMBOL_GPL(dpll_msg_pin_handle_size); 61 62 /** 63 * dpll_msg_add_pin_handle - attach pin handle attribute to a given message 64 * @msg: pointer to sk_buff message to attach a pin handle 65 * @pin: pin pointer 66 * 67 * Return: 68 * * 0 - success 69 * * -EMSGSIZE - no space in message to attach pin handle 70 */ 71 int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin) 72 { 73 if (!pin) 74 return 0; 75 if (nla_put_u32(msg, DPLL_A_PIN_ID, pin->id)) 76 return -EMSGSIZE; 77 return 0; 78 } 79 EXPORT_SYMBOL_GPL(dpll_msg_add_pin_handle); 80 81 static int 82 dpll_msg_add_mode(struct sk_buff *msg, struct dpll_device *dpll, 83 struct netlink_ext_ack *extack) 84 { 85 const struct dpll_device_ops *ops = dpll_device_ops(dpll); 86 enum dpll_mode mode; 87 int ret; 88 89 ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack); 90 if (ret) 91 return ret; 92 if (nla_put_u32(msg, DPLL_A_MODE, mode)) 93 return -EMSGSIZE; 94 95 return 0; 96 } 97 98 static int 99 dpll_msg_add_mode_supported(struct sk_buff *msg, struct dpll_device *dpll, 100 struct netlink_ext_ack *extack) 101 { 102 const struct dpll_device_ops *ops = dpll_device_ops(dpll); 103 enum dpll_mode mode; 104 105 if (!ops->mode_supported) 106 return 0; 107 for (mode = DPLL_MODE_MANUAL; mode <= DPLL_MODE_MAX; mode++) 108 if (ops->mode_supported(dpll, dpll_priv(dpll), mode, extack)) 109 if (nla_put_u32(msg, DPLL_A_MODE_SUPPORTED, mode)) 110 return -EMSGSIZE; 111 112 return 0; 113 } 114 115 static int 116 dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll, 117 struct netlink_ext_ack *extack) 118 { 119 const struct dpll_device_ops *ops = dpll_device_ops(dpll); 120 enum dpll_lock_status status; 121 int ret; 122 123 ret = ops->lock_status_get(dpll, dpll_priv(dpll), &status, extack); 124 if (ret) 125 return ret; 126 if (nla_put_u32(msg, DPLL_A_LOCK_STATUS, status)) 127 return -EMSGSIZE; 128 129 return 0; 130 } 131 132 static int 133 dpll_msg_add_temp(struct sk_buff *msg, struct dpll_device *dpll, 134 struct netlink_ext_ack *extack) 135 { 136 const struct dpll_device_ops *ops = dpll_device_ops(dpll); 137 s32 temp; 138 int ret; 139 140 if (!ops->temp_get) 141 return 0; 142 ret = ops->temp_get(dpll, dpll_priv(dpll), &temp, extack); 143 if (ret) 144 return ret; 145 if (nla_put_s32(msg, DPLL_A_TEMP, temp)) 146 return -EMSGSIZE; 147 148 return 0; 149 } 150 151 static int 152 dpll_msg_add_pin_prio(struct sk_buff *msg, struct dpll_pin *pin, 153 struct dpll_pin_ref *ref, 154 struct netlink_ext_ack *extack) 155 { 156 const struct dpll_pin_ops *ops = dpll_pin_ops(ref); 157 struct dpll_device *dpll = ref->dpll; 158 u32 prio; 159 int ret; 160 161 if (!ops->prio_get) 162 return 0; 163 ret = ops->prio_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll, 164 dpll_priv(dpll), &prio, extack); 165 if (ret) 166 return ret; 167 if (nla_put_u32(msg, DPLL_A_PIN_PRIO, prio)) 168 return -EMSGSIZE; 169 170 return 0; 171 } 172 173 static int 174 dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, struct dpll_pin *pin, 175 struct dpll_pin_ref *ref, 176 struct netlink_ext_ack *extack) 177 { 178 const struct dpll_pin_ops *ops = dpll_pin_ops(ref); 179 struct dpll_device *dpll = ref->dpll; 180 enum dpll_pin_state state; 181 int ret; 182 183 if (!ops->state_on_dpll_get) 184 return 0; 185 ret = ops->state_on_dpll_get(pin, dpll_pin_on_dpll_priv(dpll, pin), 186 dpll, dpll_priv(dpll), &state, extack); 187 if (ret) 188 return ret; 189 if (nla_put_u32(msg, DPLL_A_PIN_STATE, state)) 190 return -EMSGSIZE; 191 192 return 0; 193 } 194 195 static int 196 dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin, 197 struct dpll_pin_ref *ref, 198 struct netlink_ext_ack *extack) 199 { 200 const struct dpll_pin_ops *ops = dpll_pin_ops(ref); 201 struct dpll_device *dpll = ref->dpll; 202 enum dpll_pin_direction direction; 203 int ret; 204 205 ret = ops->direction_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll, 206 dpll_priv(dpll), &direction, extack); 207 if (ret) 208 return ret; 209 if (nla_put_u32(msg, DPLL_A_PIN_DIRECTION, direction)) 210 return -EMSGSIZE; 211 212 return 0; 213 } 214 215 static int 216 dpll_msg_add_pin_phase_adjust(struct sk_buff *msg, struct dpll_pin *pin, 217 struct dpll_pin_ref *ref, 218 struct netlink_ext_ack *extack) 219 { 220 const struct dpll_pin_ops *ops = dpll_pin_ops(ref); 221 struct dpll_device *dpll = ref->dpll; 222 s32 phase_adjust; 223 int ret; 224 225 if (!ops->phase_adjust_get) 226 return 0; 227 ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin), 228 dpll, dpll_priv(dpll), 229 &phase_adjust, extack); 230 if (ret) 231 return ret; 232 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST, phase_adjust)) 233 return -EMSGSIZE; 234 235 return 0; 236 } 237 238 static int 239 dpll_msg_add_phase_offset(struct sk_buff *msg, struct dpll_pin *pin, 240 struct dpll_pin_ref *ref, 241 struct netlink_ext_ack *extack) 242 { 243 const struct dpll_pin_ops *ops = dpll_pin_ops(ref); 244 struct dpll_device *dpll = ref->dpll; 245 s64 phase_offset; 246 int ret; 247 248 if (!ops->phase_offset_get) 249 return 0; 250 ret = ops->phase_offset_get(pin, dpll_pin_on_dpll_priv(dpll, pin), 251 dpll, dpll_priv(dpll), &phase_offset, 252 extack); 253 if (ret) 254 return ret; 255 if (nla_put_64bit(msg, DPLL_A_PIN_PHASE_OFFSET, sizeof(phase_offset), 256 &phase_offset, DPLL_A_PIN_PAD)) 257 return -EMSGSIZE; 258 259 return 0; 260 } 261 262 static int 263 dpll_msg_add_pin_freq(struct sk_buff *msg, struct dpll_pin *pin, 264 struct dpll_pin_ref *ref, struct netlink_ext_ack *extack) 265 { 266 const struct dpll_pin_ops *ops = dpll_pin_ops(ref); 267 struct dpll_device *dpll = ref->dpll; 268 struct nlattr *nest; 269 int fs, ret; 270 u64 freq; 271 272 if (!ops->frequency_get) 273 return 0; 274 ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll, 275 dpll_priv(dpll), &freq, extack); 276 if (ret) 277 return ret; 278 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY, sizeof(freq), &freq, 279 DPLL_A_PIN_PAD)) 280 return -EMSGSIZE; 281 for (fs = 0; fs < pin->prop->freq_supported_num; fs++) { 282 nest = nla_nest_start(msg, DPLL_A_PIN_FREQUENCY_SUPPORTED); 283 if (!nest) 284 return -EMSGSIZE; 285 freq = pin->prop->freq_supported[fs].min; 286 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MIN, sizeof(freq), 287 &freq, DPLL_A_PIN_PAD)) { 288 nla_nest_cancel(msg, nest); 289 return -EMSGSIZE; 290 } 291 freq = pin->prop->freq_supported[fs].max; 292 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MAX, sizeof(freq), 293 &freq, DPLL_A_PIN_PAD)) { 294 nla_nest_cancel(msg, nest); 295 return -EMSGSIZE; 296 } 297 nla_nest_end(msg, nest); 298 } 299 300 return 0; 301 } 302 303 static bool dpll_pin_is_freq_supported(struct dpll_pin *pin, u32 freq) 304 { 305 int fs; 306 307 for (fs = 0; fs < pin->prop->freq_supported_num; fs++) 308 if (freq >= pin->prop->freq_supported[fs].min && 309 freq <= pin->prop->freq_supported[fs].max) 310 return true; 311 return false; 312 } 313 314 static int 315 dpll_msg_add_pin_parents(struct sk_buff *msg, struct dpll_pin *pin, 316 struct dpll_pin_ref *dpll_ref, 317 struct netlink_ext_ack *extack) 318 { 319 enum dpll_pin_state state; 320 struct dpll_pin_ref *ref; 321 struct dpll_pin *ppin; 322 struct nlattr *nest; 323 unsigned long index; 324 int ret; 325 326 xa_for_each(&pin->parent_refs, index, ref) { 327 const struct dpll_pin_ops *ops = dpll_pin_ops(ref); 328 void *parent_priv; 329 330 ppin = ref->pin; 331 parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, ppin); 332 ret = ops->state_on_pin_get(pin, 333 dpll_pin_on_pin_priv(ppin, pin), 334 ppin, parent_priv, &state, extack); 335 if (ret) 336 return ret; 337 nest = nla_nest_start(msg, DPLL_A_PIN_PARENT_PIN); 338 if (!nest) 339 return -EMSGSIZE; 340 ret = dpll_msg_add_dev_parent_handle(msg, ppin->id); 341 if (ret) 342 goto nest_cancel; 343 if (nla_put_u32(msg, DPLL_A_PIN_STATE, state)) { 344 ret = -EMSGSIZE; 345 goto nest_cancel; 346 } 347 nla_nest_end(msg, nest); 348 } 349 350 return 0; 351 352 nest_cancel: 353 nla_nest_cancel(msg, nest); 354 return ret; 355 } 356 357 static int 358 dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin, 359 struct netlink_ext_ack *extack) 360 { 361 struct dpll_pin_ref *ref; 362 struct nlattr *attr; 363 unsigned long index; 364 int ret; 365 366 xa_for_each(&pin->dpll_refs, index, ref) { 367 attr = nla_nest_start(msg, DPLL_A_PIN_PARENT_DEVICE); 368 if (!attr) 369 return -EMSGSIZE; 370 ret = dpll_msg_add_dev_parent_handle(msg, ref->dpll->id); 371 if (ret) 372 goto nest_cancel; 373 ret = dpll_msg_add_pin_on_dpll_state(msg, pin, ref, extack); 374 if (ret) 375 goto nest_cancel; 376 ret = dpll_msg_add_pin_prio(msg, pin, ref, extack); 377 if (ret) 378 goto nest_cancel; 379 ret = dpll_msg_add_pin_direction(msg, pin, ref, extack); 380 if (ret) 381 goto nest_cancel; 382 ret = dpll_msg_add_phase_offset(msg, pin, ref, extack); 383 if (ret) 384 goto nest_cancel; 385 nla_nest_end(msg, attr); 386 } 387 388 return 0; 389 390 nest_cancel: 391 nla_nest_end(msg, attr); 392 return ret; 393 } 394 395 static int 396 dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin, 397 struct netlink_ext_ack *extack) 398 { 399 const struct dpll_pin_properties *prop = pin->prop; 400 struct dpll_pin_ref *ref; 401 int ret; 402 403 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); 404 ASSERT_NOT_NULL(ref); 405 406 ret = dpll_msg_add_pin_handle(msg, pin); 407 if (ret) 408 return ret; 409 if (nla_put_string(msg, DPLL_A_PIN_MODULE_NAME, 410 module_name(pin->module))) 411 return -EMSGSIZE; 412 if (nla_put_64bit(msg, DPLL_A_PIN_CLOCK_ID, sizeof(pin->clock_id), 413 &pin->clock_id, DPLL_A_PIN_PAD)) 414 return -EMSGSIZE; 415 if (prop->board_label && 416 nla_put_string(msg, DPLL_A_PIN_BOARD_LABEL, prop->board_label)) 417 return -EMSGSIZE; 418 if (prop->panel_label && 419 nla_put_string(msg, DPLL_A_PIN_PANEL_LABEL, prop->panel_label)) 420 return -EMSGSIZE; 421 if (prop->package_label && 422 nla_put_string(msg, DPLL_A_PIN_PACKAGE_LABEL, 423 prop->package_label)) 424 return -EMSGSIZE; 425 if (nla_put_u32(msg, DPLL_A_PIN_TYPE, prop->type)) 426 return -EMSGSIZE; 427 if (nla_put_u32(msg, DPLL_A_PIN_CAPABILITIES, prop->capabilities)) 428 return -EMSGSIZE; 429 ret = dpll_msg_add_pin_freq(msg, pin, ref, extack); 430 if (ret) 431 return ret; 432 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MIN, 433 prop->phase_range.min)) 434 return -EMSGSIZE; 435 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MAX, 436 prop->phase_range.max)) 437 return -EMSGSIZE; 438 ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack); 439 if (ret) 440 return ret; 441 if (xa_empty(&pin->parent_refs)) 442 ret = dpll_msg_add_pin_dplls(msg, pin, extack); 443 else 444 ret = dpll_msg_add_pin_parents(msg, pin, ref, extack); 445 446 return ret; 447 } 448 449 static int 450 dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg, 451 struct netlink_ext_ack *extack) 452 { 453 int ret; 454 455 ret = dpll_msg_add_dev_handle(msg, dpll); 456 if (ret) 457 return ret; 458 if (nla_put_string(msg, DPLL_A_MODULE_NAME, module_name(dpll->module))) 459 return -EMSGSIZE; 460 if (nla_put_64bit(msg, DPLL_A_CLOCK_ID, sizeof(dpll->clock_id), 461 &dpll->clock_id, DPLL_A_PAD)) 462 return -EMSGSIZE; 463 ret = dpll_msg_add_temp(msg, dpll, extack); 464 if (ret) 465 return ret; 466 ret = dpll_msg_add_lock_status(msg, dpll, extack); 467 if (ret) 468 return ret; 469 ret = dpll_msg_add_mode(msg, dpll, extack); 470 if (ret) 471 return ret; 472 ret = dpll_msg_add_mode_supported(msg, dpll, extack); 473 if (ret) 474 return ret; 475 if (nla_put_u32(msg, DPLL_A_TYPE, dpll->type)) 476 return -EMSGSIZE; 477 478 return 0; 479 } 480 481 static int 482 dpll_device_event_send(enum dpll_cmd event, struct dpll_device *dpll) 483 { 484 struct sk_buff *msg; 485 int ret = -ENOMEM; 486 void *hdr; 487 488 if (WARN_ON(!xa_get_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED))) 489 return -ENODEV; 490 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 491 if (!msg) 492 return -ENOMEM; 493 hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event); 494 if (!hdr) 495 goto err_free_msg; 496 ret = dpll_device_get_one(dpll, msg, NULL); 497 if (ret) 498 goto err_cancel_msg; 499 genlmsg_end(msg, hdr); 500 genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL); 501 502 return 0; 503 504 err_cancel_msg: 505 genlmsg_cancel(msg, hdr); 506 err_free_msg: 507 nlmsg_free(msg); 508 509 return ret; 510 } 511 512 int dpll_device_create_ntf(struct dpll_device *dpll) 513 { 514 return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF, dpll); 515 } 516 517 int dpll_device_delete_ntf(struct dpll_device *dpll) 518 { 519 return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll); 520 } 521 522 static int 523 __dpll_device_change_ntf(struct dpll_device *dpll) 524 { 525 return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll); 526 } 527 528 /** 529 * dpll_device_change_ntf - notify that the dpll device has been changed 530 * @dpll: registered dpll pointer 531 * 532 * Context: acquires and holds a dpll_lock. 533 * Return: 0 if succeeds, error code otherwise. 534 */ 535 int dpll_device_change_ntf(struct dpll_device *dpll) 536 { 537 int ret; 538 539 mutex_lock(&dpll_lock); 540 ret = __dpll_device_change_ntf(dpll); 541 mutex_unlock(&dpll_lock); 542 543 return ret; 544 } 545 EXPORT_SYMBOL_GPL(dpll_device_change_ntf); 546 547 static int 548 dpll_pin_event_send(enum dpll_cmd event, struct dpll_pin *pin) 549 { 550 struct sk_buff *msg; 551 int ret = -ENOMEM; 552 void *hdr; 553 554 if (WARN_ON(!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED))) 555 return -ENODEV; 556 557 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 558 if (!msg) 559 return -ENOMEM; 560 561 hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event); 562 if (!hdr) 563 goto err_free_msg; 564 ret = dpll_cmd_pin_get_one(msg, pin, NULL); 565 if (ret) 566 goto err_cancel_msg; 567 genlmsg_end(msg, hdr); 568 genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL); 569 570 return 0; 571 572 err_cancel_msg: 573 genlmsg_cancel(msg, hdr); 574 err_free_msg: 575 nlmsg_free(msg); 576 577 return ret; 578 } 579 580 int dpll_pin_create_ntf(struct dpll_pin *pin) 581 { 582 return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF, pin); 583 } 584 585 int dpll_pin_delete_ntf(struct dpll_pin *pin) 586 { 587 return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin); 588 } 589 590 static int __dpll_pin_change_ntf(struct dpll_pin *pin) 591 { 592 return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin); 593 } 594 595 /** 596 * dpll_pin_change_ntf - notify that the pin has been changed 597 * @pin: registered pin pointer 598 * 599 * Context: acquires and holds a dpll_lock. 600 * Return: 0 if succeeds, error code otherwise. 601 */ 602 int dpll_pin_change_ntf(struct dpll_pin *pin) 603 { 604 int ret; 605 606 mutex_lock(&dpll_lock); 607 ret = __dpll_pin_change_ntf(pin); 608 mutex_unlock(&dpll_lock); 609 610 return ret; 611 } 612 EXPORT_SYMBOL_GPL(dpll_pin_change_ntf); 613 614 static int 615 dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a, 616 struct netlink_ext_ack *extack) 617 { 618 u64 freq = nla_get_u64(a), old_freq; 619 struct dpll_pin_ref *ref, *failed; 620 const struct dpll_pin_ops *ops; 621 struct dpll_device *dpll; 622 unsigned long i; 623 int ret; 624 625 if (!dpll_pin_is_freq_supported(pin, freq)) { 626 NL_SET_ERR_MSG_ATTR(extack, a, "frequency is not supported by the device"); 627 return -EINVAL; 628 } 629 630 xa_for_each(&pin->dpll_refs, i, ref) { 631 ops = dpll_pin_ops(ref); 632 if (!ops->frequency_set || !ops->frequency_get) { 633 NL_SET_ERR_MSG(extack, "frequency set not supported by the device"); 634 return -EOPNOTSUPP; 635 } 636 } 637 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); 638 ops = dpll_pin_ops(ref); 639 dpll = ref->dpll; 640 ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll, 641 dpll_priv(dpll), &old_freq, extack); 642 if (ret) { 643 NL_SET_ERR_MSG(extack, "unable to get old frequency value"); 644 return ret; 645 } 646 if (freq == old_freq) 647 return 0; 648 649 xa_for_each(&pin->dpll_refs, i, ref) { 650 ops = dpll_pin_ops(ref); 651 dpll = ref->dpll; 652 ret = ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin), 653 dpll, dpll_priv(dpll), freq, extack); 654 if (ret) { 655 failed = ref; 656 NL_SET_ERR_MSG_FMT(extack, "frequency set failed for dpll_id:%u", 657 dpll->id); 658 goto rollback; 659 } 660 } 661 __dpll_pin_change_ntf(pin); 662 663 return 0; 664 665 rollback: 666 xa_for_each(&pin->dpll_refs, i, ref) { 667 if (ref == failed) 668 break; 669 ops = dpll_pin_ops(ref); 670 dpll = ref->dpll; 671 if (ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin), 672 dpll, dpll_priv(dpll), old_freq, extack)) 673 NL_SET_ERR_MSG(extack, "set frequency rollback failed"); 674 } 675 return ret; 676 } 677 678 static int 679 dpll_pin_on_pin_state_set(struct dpll_pin *pin, u32 parent_idx, 680 enum dpll_pin_state state, 681 struct netlink_ext_ack *extack) 682 { 683 struct dpll_pin_ref *parent_ref; 684 const struct dpll_pin_ops *ops; 685 struct dpll_pin_ref *dpll_ref; 686 void *pin_priv, *parent_priv; 687 struct dpll_pin *parent; 688 unsigned long i; 689 int ret; 690 691 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE & 692 pin->prop->capabilities)) { 693 NL_SET_ERR_MSG(extack, "state changing is not allowed"); 694 return -EOPNOTSUPP; 695 } 696 parent = xa_load(&dpll_pin_xa, parent_idx); 697 if (!parent) 698 return -EINVAL; 699 parent_ref = xa_load(&pin->parent_refs, parent->pin_idx); 700 if (!parent_ref) 701 return -EINVAL; 702 xa_for_each(&parent->dpll_refs, i, dpll_ref) { 703 ops = dpll_pin_ops(parent_ref); 704 if (!ops->state_on_pin_set) 705 return -EOPNOTSUPP; 706 pin_priv = dpll_pin_on_pin_priv(parent, pin); 707 parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, parent); 708 ret = ops->state_on_pin_set(pin, pin_priv, parent, parent_priv, 709 state, extack); 710 if (ret) 711 return ret; 712 } 713 __dpll_pin_change_ntf(pin); 714 715 return 0; 716 } 717 718 static int 719 dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin, 720 enum dpll_pin_state state, 721 struct netlink_ext_ack *extack) 722 { 723 const struct dpll_pin_ops *ops; 724 struct dpll_pin_ref *ref; 725 int ret; 726 727 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE & 728 pin->prop->capabilities)) { 729 NL_SET_ERR_MSG(extack, "state changing is not allowed"); 730 return -EOPNOTSUPP; 731 } 732 ref = xa_load(&pin->dpll_refs, dpll->id); 733 ASSERT_NOT_NULL(ref); 734 ops = dpll_pin_ops(ref); 735 if (!ops->state_on_dpll_set) 736 return -EOPNOTSUPP; 737 ret = ops->state_on_dpll_set(pin, dpll_pin_on_dpll_priv(dpll, pin), 738 dpll, dpll_priv(dpll), state, extack); 739 if (ret) 740 return ret; 741 __dpll_pin_change_ntf(pin); 742 743 return 0; 744 } 745 746 static int 747 dpll_pin_prio_set(struct dpll_device *dpll, struct dpll_pin *pin, 748 u32 prio, struct netlink_ext_ack *extack) 749 { 750 const struct dpll_pin_ops *ops; 751 struct dpll_pin_ref *ref; 752 int ret; 753 754 if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE & 755 pin->prop->capabilities)) { 756 NL_SET_ERR_MSG(extack, "prio changing is not allowed"); 757 return -EOPNOTSUPP; 758 } 759 ref = xa_load(&pin->dpll_refs, dpll->id); 760 ASSERT_NOT_NULL(ref); 761 ops = dpll_pin_ops(ref); 762 if (!ops->prio_set) 763 return -EOPNOTSUPP; 764 ret = ops->prio_set(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll, 765 dpll_priv(dpll), prio, extack); 766 if (ret) 767 return ret; 768 __dpll_pin_change_ntf(pin); 769 770 return 0; 771 } 772 773 static int 774 dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll, 775 enum dpll_pin_direction direction, 776 struct netlink_ext_ack *extack) 777 { 778 const struct dpll_pin_ops *ops; 779 struct dpll_pin_ref *ref; 780 int ret; 781 782 if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE & 783 pin->prop->capabilities)) { 784 NL_SET_ERR_MSG(extack, "direction changing is not allowed"); 785 return -EOPNOTSUPP; 786 } 787 ref = xa_load(&pin->dpll_refs, dpll->id); 788 ASSERT_NOT_NULL(ref); 789 ops = dpll_pin_ops(ref); 790 if (!ops->direction_set) 791 return -EOPNOTSUPP; 792 ret = ops->direction_set(pin, dpll_pin_on_dpll_priv(dpll, pin), 793 dpll, dpll_priv(dpll), direction, extack); 794 if (ret) 795 return ret; 796 __dpll_pin_change_ntf(pin); 797 798 return 0; 799 } 800 801 static int 802 dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr, 803 struct netlink_ext_ack *extack) 804 { 805 struct dpll_pin_ref *ref, *failed; 806 const struct dpll_pin_ops *ops; 807 s32 phase_adj, old_phase_adj; 808 struct dpll_device *dpll; 809 unsigned long i; 810 int ret; 811 812 phase_adj = nla_get_s32(phase_adj_attr); 813 if (phase_adj > pin->prop->phase_range.max || 814 phase_adj < pin->prop->phase_range.min) { 815 NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr, 816 "phase adjust value not supported"); 817 return -EINVAL; 818 } 819 820 xa_for_each(&pin->dpll_refs, i, ref) { 821 ops = dpll_pin_ops(ref); 822 if (!ops->phase_adjust_set || !ops->phase_adjust_get) { 823 NL_SET_ERR_MSG(extack, "phase adjust not supported"); 824 return -EOPNOTSUPP; 825 } 826 } 827 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); 828 ops = dpll_pin_ops(ref); 829 dpll = ref->dpll; 830 ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin), 831 dpll, dpll_priv(dpll), &old_phase_adj, 832 extack); 833 if (ret) { 834 NL_SET_ERR_MSG(extack, "unable to get old phase adjust value"); 835 return ret; 836 } 837 if (phase_adj == old_phase_adj) 838 return 0; 839 840 xa_for_each(&pin->dpll_refs, i, ref) { 841 ops = dpll_pin_ops(ref); 842 dpll = ref->dpll; 843 ret = ops->phase_adjust_set(pin, 844 dpll_pin_on_dpll_priv(dpll, pin), 845 dpll, dpll_priv(dpll), phase_adj, 846 extack); 847 if (ret) { 848 failed = ref; 849 NL_SET_ERR_MSG_FMT(extack, 850 "phase adjust set failed for dpll_id:%u", 851 dpll->id); 852 goto rollback; 853 } 854 } 855 __dpll_pin_change_ntf(pin); 856 857 return 0; 858 859 rollback: 860 xa_for_each(&pin->dpll_refs, i, ref) { 861 if (ref == failed) 862 break; 863 ops = dpll_pin_ops(ref); 864 dpll = ref->dpll; 865 if (ops->phase_adjust_set(pin, dpll_pin_on_dpll_priv(dpll, pin), 866 dpll, dpll_priv(dpll), old_phase_adj, 867 extack)) 868 NL_SET_ERR_MSG(extack, "set phase adjust rollback failed"); 869 } 870 return ret; 871 } 872 873 static int 874 dpll_pin_parent_device_set(struct dpll_pin *pin, struct nlattr *parent_nest, 875 struct netlink_ext_ack *extack) 876 { 877 struct nlattr *tb[DPLL_A_PIN_MAX + 1]; 878 enum dpll_pin_direction direction; 879 enum dpll_pin_state state; 880 struct dpll_pin_ref *ref; 881 struct dpll_device *dpll; 882 u32 pdpll_idx, prio; 883 int ret; 884 885 nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest, 886 dpll_pin_parent_device_nl_policy, extack); 887 if (!tb[DPLL_A_PIN_PARENT_ID]) { 888 NL_SET_ERR_MSG(extack, "device parent id expected"); 889 return -EINVAL; 890 } 891 pdpll_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]); 892 dpll = xa_load(&dpll_device_xa, pdpll_idx); 893 if (!dpll) { 894 NL_SET_ERR_MSG(extack, "parent device not found"); 895 return -EINVAL; 896 } 897 ref = xa_load(&pin->dpll_refs, dpll->id); 898 if (!ref) { 899 NL_SET_ERR_MSG(extack, "pin not connected to given parent device"); 900 return -EINVAL; 901 } 902 if (tb[DPLL_A_PIN_STATE]) { 903 state = nla_get_u32(tb[DPLL_A_PIN_STATE]); 904 ret = dpll_pin_state_set(dpll, pin, state, extack); 905 if (ret) 906 return ret; 907 } 908 if (tb[DPLL_A_PIN_PRIO]) { 909 prio = nla_get_u32(tb[DPLL_A_PIN_PRIO]); 910 ret = dpll_pin_prio_set(dpll, pin, prio, extack); 911 if (ret) 912 return ret; 913 } 914 if (tb[DPLL_A_PIN_DIRECTION]) { 915 direction = nla_get_u32(tb[DPLL_A_PIN_DIRECTION]); 916 ret = dpll_pin_direction_set(pin, dpll, direction, extack); 917 if (ret) 918 return ret; 919 } 920 return 0; 921 } 922 923 static int 924 dpll_pin_parent_pin_set(struct dpll_pin *pin, struct nlattr *parent_nest, 925 struct netlink_ext_ack *extack) 926 { 927 struct nlattr *tb[DPLL_A_PIN_MAX + 1]; 928 enum dpll_pin_state state; 929 u32 ppin_idx; 930 int ret; 931 932 nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest, 933 dpll_pin_parent_pin_nl_policy, extack); 934 if (!tb[DPLL_A_PIN_PARENT_ID]) { 935 NL_SET_ERR_MSG(extack, "device parent id expected"); 936 return -EINVAL; 937 } 938 ppin_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]); 939 state = nla_get_u32(tb[DPLL_A_PIN_STATE]); 940 ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack); 941 if (ret) 942 return ret; 943 944 return 0; 945 } 946 947 static int 948 dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info) 949 { 950 struct nlattr *a; 951 int rem, ret; 952 953 nla_for_each_attr(a, genlmsg_data(info->genlhdr), 954 genlmsg_len(info->genlhdr), rem) { 955 switch (nla_type(a)) { 956 case DPLL_A_PIN_FREQUENCY: 957 ret = dpll_pin_freq_set(pin, a, info->extack); 958 if (ret) 959 return ret; 960 break; 961 case DPLL_A_PIN_PHASE_ADJUST: 962 ret = dpll_pin_phase_adj_set(pin, a, info->extack); 963 if (ret) 964 return ret; 965 break; 966 case DPLL_A_PIN_PARENT_DEVICE: 967 ret = dpll_pin_parent_device_set(pin, a, info->extack); 968 if (ret) 969 return ret; 970 break; 971 case DPLL_A_PIN_PARENT_PIN: 972 ret = dpll_pin_parent_pin_set(pin, a, info->extack); 973 if (ret) 974 return ret; 975 break; 976 } 977 } 978 979 return 0; 980 } 981 982 static struct dpll_pin * 983 dpll_pin_find(u64 clock_id, struct nlattr *mod_name_attr, 984 enum dpll_pin_type type, struct nlattr *board_label, 985 struct nlattr *panel_label, struct nlattr *package_label, 986 struct netlink_ext_ack *extack) 987 { 988 bool board_match, panel_match, package_match; 989 struct dpll_pin *pin_match = NULL, *pin; 990 const struct dpll_pin_properties *prop; 991 bool cid_match, mod_match, type_match; 992 unsigned long i; 993 994 xa_for_each_marked(&dpll_pin_xa, i, pin, DPLL_REGISTERED) { 995 prop = pin->prop; 996 cid_match = clock_id ? pin->clock_id == clock_id : true; 997 mod_match = mod_name_attr && module_name(pin->module) ? 998 !nla_strcmp(mod_name_attr, 999 module_name(pin->module)) : true; 1000 type_match = type ? prop->type == type : true; 1001 board_match = board_label ? (prop->board_label ? 1002 !nla_strcmp(board_label, prop->board_label) : false) : 1003 true; 1004 panel_match = panel_label ? (prop->panel_label ? 1005 !nla_strcmp(panel_label, prop->panel_label) : false) : 1006 true; 1007 package_match = package_label ? (prop->package_label ? 1008 !nla_strcmp(package_label, prop->package_label) : 1009 false) : true; 1010 if (cid_match && mod_match && type_match && board_match && 1011 panel_match && package_match) { 1012 if (pin_match) { 1013 NL_SET_ERR_MSG(extack, "multiple matches"); 1014 return ERR_PTR(-EINVAL); 1015 } 1016 pin_match = pin; 1017 } 1018 } 1019 if (!pin_match) { 1020 NL_SET_ERR_MSG(extack, "not found"); 1021 return ERR_PTR(-ENODEV); 1022 } 1023 return pin_match; 1024 } 1025 1026 static struct dpll_pin *dpll_pin_find_from_nlattr(struct genl_info *info) 1027 { 1028 struct nlattr *attr, *mod_name_attr = NULL, *board_label_attr = NULL, 1029 *panel_label_attr = NULL, *package_label_attr = NULL; 1030 enum dpll_pin_type type = 0; 1031 u64 clock_id = 0; 1032 int rem = 0; 1033 1034 nla_for_each_attr(attr, genlmsg_data(info->genlhdr), 1035 genlmsg_len(info->genlhdr), rem) { 1036 switch (nla_type(attr)) { 1037 case DPLL_A_PIN_CLOCK_ID: 1038 if (clock_id) 1039 goto duplicated_attr; 1040 clock_id = nla_get_u64(attr); 1041 break; 1042 case DPLL_A_PIN_MODULE_NAME: 1043 if (mod_name_attr) 1044 goto duplicated_attr; 1045 mod_name_attr = attr; 1046 break; 1047 case DPLL_A_PIN_TYPE: 1048 if (type) 1049 goto duplicated_attr; 1050 type = nla_get_u32(attr); 1051 break; 1052 case DPLL_A_PIN_BOARD_LABEL: 1053 if (board_label_attr) 1054 goto duplicated_attr; 1055 board_label_attr = attr; 1056 break; 1057 case DPLL_A_PIN_PANEL_LABEL: 1058 if (panel_label_attr) 1059 goto duplicated_attr; 1060 panel_label_attr = attr; 1061 break; 1062 case DPLL_A_PIN_PACKAGE_LABEL: 1063 if (package_label_attr) 1064 goto duplicated_attr; 1065 package_label_attr = attr; 1066 break; 1067 default: 1068 break; 1069 } 1070 } 1071 if (!(clock_id || mod_name_attr || board_label_attr || 1072 panel_label_attr || package_label_attr)) { 1073 NL_SET_ERR_MSG(info->extack, "missing attributes"); 1074 return ERR_PTR(-EINVAL); 1075 } 1076 return dpll_pin_find(clock_id, mod_name_attr, type, board_label_attr, 1077 panel_label_attr, package_label_attr, 1078 info->extack); 1079 duplicated_attr: 1080 NL_SET_ERR_MSG(info->extack, "duplicated attribute"); 1081 return ERR_PTR(-EINVAL); 1082 } 1083 1084 int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info) 1085 { 1086 struct dpll_pin *pin; 1087 struct sk_buff *msg; 1088 struct nlattr *hdr; 1089 int ret; 1090 1091 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1092 if (!msg) 1093 return -ENOMEM; 1094 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0, 1095 DPLL_CMD_PIN_ID_GET); 1096 if (!hdr) 1097 return -EMSGSIZE; 1098 1099 pin = dpll_pin_find_from_nlattr(info); 1100 if (!IS_ERR(pin)) { 1101 ret = dpll_msg_add_pin_handle(msg, pin); 1102 if (ret) { 1103 nlmsg_free(msg); 1104 return ret; 1105 } 1106 } 1107 genlmsg_end(msg, hdr); 1108 1109 return genlmsg_reply(msg, info); 1110 } 1111 1112 int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info) 1113 { 1114 struct dpll_pin *pin = info->user_ptr[0]; 1115 struct sk_buff *msg; 1116 struct nlattr *hdr; 1117 int ret; 1118 1119 if (!pin) 1120 return -ENODEV; 1121 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1122 if (!msg) 1123 return -ENOMEM; 1124 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0, 1125 DPLL_CMD_PIN_GET); 1126 if (!hdr) 1127 return -EMSGSIZE; 1128 ret = dpll_cmd_pin_get_one(msg, pin, info->extack); 1129 if (ret) { 1130 nlmsg_free(msg); 1131 return ret; 1132 } 1133 genlmsg_end(msg, hdr); 1134 1135 return genlmsg_reply(msg, info); 1136 } 1137 1138 int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 1139 { 1140 struct dpll_dump_ctx *ctx = dpll_dump_context(cb); 1141 struct dpll_pin *pin; 1142 struct nlattr *hdr; 1143 unsigned long i; 1144 int ret = 0; 1145 1146 xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED, 1147 ctx->idx) { 1148 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, 1149 cb->nlh->nlmsg_seq, 1150 &dpll_nl_family, NLM_F_MULTI, 1151 DPLL_CMD_PIN_GET); 1152 if (!hdr) { 1153 ret = -EMSGSIZE; 1154 break; 1155 } 1156 ret = dpll_cmd_pin_get_one(skb, pin, cb->extack); 1157 if (ret) { 1158 genlmsg_cancel(skb, hdr); 1159 break; 1160 } 1161 genlmsg_end(skb, hdr); 1162 } 1163 if (ret == -EMSGSIZE) { 1164 ctx->idx = i; 1165 return skb->len; 1166 } 1167 return ret; 1168 } 1169 1170 int dpll_nl_pin_set_doit(struct sk_buff *skb, struct genl_info *info) 1171 { 1172 struct dpll_pin *pin = info->user_ptr[0]; 1173 1174 return dpll_pin_set_from_nlattr(pin, info); 1175 } 1176 1177 static struct dpll_device * 1178 dpll_device_find(u64 clock_id, struct nlattr *mod_name_attr, 1179 enum dpll_type type, struct netlink_ext_ack *extack) 1180 { 1181 struct dpll_device *dpll_match = NULL, *dpll; 1182 bool cid_match, mod_match, type_match; 1183 unsigned long i; 1184 1185 xa_for_each_marked(&dpll_device_xa, i, dpll, DPLL_REGISTERED) { 1186 cid_match = clock_id ? dpll->clock_id == clock_id : true; 1187 mod_match = mod_name_attr ? (module_name(dpll->module) ? 1188 !nla_strcmp(mod_name_attr, 1189 module_name(dpll->module)) : false) : true; 1190 type_match = type ? dpll->type == type : true; 1191 if (cid_match && mod_match && type_match) { 1192 if (dpll_match) { 1193 NL_SET_ERR_MSG(extack, "multiple matches"); 1194 return ERR_PTR(-EINVAL); 1195 } 1196 dpll_match = dpll; 1197 } 1198 } 1199 if (!dpll_match) { 1200 NL_SET_ERR_MSG(extack, "not found"); 1201 return ERR_PTR(-ENODEV); 1202 } 1203 1204 return dpll_match; 1205 } 1206 1207 static struct dpll_device * 1208 dpll_device_find_from_nlattr(struct genl_info *info) 1209 { 1210 struct nlattr *attr, *mod_name_attr = NULL; 1211 enum dpll_type type = 0; 1212 u64 clock_id = 0; 1213 int rem = 0; 1214 1215 nla_for_each_attr(attr, genlmsg_data(info->genlhdr), 1216 genlmsg_len(info->genlhdr), rem) { 1217 switch (nla_type(attr)) { 1218 case DPLL_A_CLOCK_ID: 1219 if (clock_id) 1220 goto duplicated_attr; 1221 clock_id = nla_get_u64(attr); 1222 break; 1223 case DPLL_A_MODULE_NAME: 1224 if (mod_name_attr) 1225 goto duplicated_attr; 1226 mod_name_attr = attr; 1227 break; 1228 case DPLL_A_TYPE: 1229 if (type) 1230 goto duplicated_attr; 1231 type = nla_get_u32(attr); 1232 break; 1233 default: 1234 break; 1235 } 1236 } 1237 if (!clock_id && !mod_name_attr && !type) { 1238 NL_SET_ERR_MSG(info->extack, "missing attributes"); 1239 return ERR_PTR(-EINVAL); 1240 } 1241 return dpll_device_find(clock_id, mod_name_attr, type, info->extack); 1242 duplicated_attr: 1243 NL_SET_ERR_MSG(info->extack, "duplicated attribute"); 1244 return ERR_PTR(-EINVAL); 1245 } 1246 1247 int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info) 1248 { 1249 struct dpll_device *dpll; 1250 struct sk_buff *msg; 1251 struct nlattr *hdr; 1252 int ret; 1253 1254 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1255 if (!msg) 1256 return -ENOMEM; 1257 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0, 1258 DPLL_CMD_DEVICE_ID_GET); 1259 if (!hdr) 1260 return -EMSGSIZE; 1261 1262 dpll = dpll_device_find_from_nlattr(info); 1263 if (!IS_ERR(dpll)) { 1264 ret = dpll_msg_add_dev_handle(msg, dpll); 1265 if (ret) { 1266 nlmsg_free(msg); 1267 return ret; 1268 } 1269 } 1270 genlmsg_end(msg, hdr); 1271 1272 return genlmsg_reply(msg, info); 1273 } 1274 1275 int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info) 1276 { 1277 struct dpll_device *dpll = info->user_ptr[0]; 1278 struct sk_buff *msg; 1279 struct nlattr *hdr; 1280 int ret; 1281 1282 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1283 if (!msg) 1284 return -ENOMEM; 1285 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0, 1286 DPLL_CMD_DEVICE_GET); 1287 if (!hdr) 1288 return -EMSGSIZE; 1289 1290 ret = dpll_device_get_one(dpll, msg, info->extack); 1291 if (ret) { 1292 nlmsg_free(msg); 1293 return ret; 1294 } 1295 genlmsg_end(msg, hdr); 1296 1297 return genlmsg_reply(msg, info); 1298 } 1299 1300 int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info) 1301 { 1302 /* placeholder for set command */ 1303 return 0; 1304 } 1305 1306 int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 1307 { 1308 struct dpll_dump_ctx *ctx = dpll_dump_context(cb); 1309 struct dpll_device *dpll; 1310 struct nlattr *hdr; 1311 unsigned long i; 1312 int ret = 0; 1313 1314 xa_for_each_marked_start(&dpll_device_xa, i, dpll, DPLL_REGISTERED, 1315 ctx->idx) { 1316 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, 1317 cb->nlh->nlmsg_seq, &dpll_nl_family, 1318 NLM_F_MULTI, DPLL_CMD_DEVICE_GET); 1319 if (!hdr) { 1320 ret = -EMSGSIZE; 1321 break; 1322 } 1323 ret = dpll_device_get_one(dpll, skb, cb->extack); 1324 if (ret) { 1325 genlmsg_cancel(skb, hdr); 1326 break; 1327 } 1328 genlmsg_end(skb, hdr); 1329 } 1330 if (ret == -EMSGSIZE) { 1331 ctx->idx = i; 1332 return skb->len; 1333 } 1334 return ret; 1335 } 1336 1337 int dpll_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1338 struct genl_info *info) 1339 { 1340 u32 id; 1341 1342 if (GENL_REQ_ATTR_CHECK(info, DPLL_A_ID)) 1343 return -EINVAL; 1344 1345 mutex_lock(&dpll_lock); 1346 id = nla_get_u32(info->attrs[DPLL_A_ID]); 1347 info->user_ptr[0] = dpll_device_get_by_id(id); 1348 if (!info->user_ptr[0]) { 1349 NL_SET_ERR_MSG(info->extack, "device not found"); 1350 goto unlock; 1351 } 1352 return 0; 1353 unlock: 1354 mutex_unlock(&dpll_lock); 1355 return -ENODEV; 1356 } 1357 1358 void dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1359 struct genl_info *info) 1360 { 1361 mutex_unlock(&dpll_lock); 1362 } 1363 1364 int 1365 dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1366 struct genl_info *info) 1367 { 1368 mutex_lock(&dpll_lock); 1369 1370 return 0; 1371 } 1372 1373 void 1374 dpll_unlock_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1375 struct genl_info *info) 1376 { 1377 mutex_unlock(&dpll_lock); 1378 } 1379 1380 int dpll_lock_dumpit(struct netlink_callback *cb) 1381 { 1382 mutex_lock(&dpll_lock); 1383 1384 return 0; 1385 } 1386 1387 int dpll_unlock_dumpit(struct netlink_callback *cb) 1388 { 1389 mutex_unlock(&dpll_lock); 1390 1391 return 0; 1392 } 1393 1394 int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1395 struct genl_info *info) 1396 { 1397 int ret; 1398 1399 mutex_lock(&dpll_lock); 1400 if (GENL_REQ_ATTR_CHECK(info, DPLL_A_PIN_ID)) { 1401 ret = -EINVAL; 1402 goto unlock_dev; 1403 } 1404 info->user_ptr[0] = xa_load(&dpll_pin_xa, 1405 nla_get_u32(info->attrs[DPLL_A_PIN_ID])); 1406 if (!info->user_ptr[0]) { 1407 NL_SET_ERR_MSG(info->extack, "pin not found"); 1408 ret = -ENODEV; 1409 goto unlock_dev; 1410 } 1411 1412 return 0; 1413 1414 unlock_dev: 1415 mutex_unlock(&dpll_lock); 1416 return ret; 1417 } 1418 1419 void dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1420 struct genl_info *info) 1421 { 1422 mutex_unlock(&dpll_lock); 1423 } 1424