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