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 mutex_lock(&dpll_lock); 1210 xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED, 1211 ctx->idx) { 1212 if (!dpll_pin_available(pin)) 1213 continue; 1214 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, 1215 cb->nlh->nlmsg_seq, 1216 &dpll_nl_family, NLM_F_MULTI, 1217 DPLL_CMD_PIN_GET); 1218 if (!hdr) { 1219 ret = -EMSGSIZE; 1220 break; 1221 } 1222 ret = dpll_cmd_pin_get_one(skb, pin, cb->extack); 1223 if (ret) { 1224 genlmsg_cancel(skb, hdr); 1225 break; 1226 } 1227 genlmsg_end(skb, hdr); 1228 } 1229 mutex_unlock(&dpll_lock); 1230 1231 if (ret == -EMSGSIZE) { 1232 ctx->idx = i; 1233 return skb->len; 1234 } 1235 return ret; 1236 } 1237 1238 int dpll_nl_pin_set_doit(struct sk_buff *skb, struct genl_info *info) 1239 { 1240 struct dpll_pin *pin = info->user_ptr[0]; 1241 1242 return dpll_pin_set_from_nlattr(pin, info); 1243 } 1244 1245 static struct dpll_device * 1246 dpll_device_find(u64 clock_id, struct nlattr *mod_name_attr, 1247 enum dpll_type type, struct netlink_ext_ack *extack) 1248 { 1249 struct dpll_device *dpll_match = NULL, *dpll; 1250 bool cid_match, mod_match, type_match; 1251 unsigned long i; 1252 1253 xa_for_each_marked(&dpll_device_xa, i, dpll, DPLL_REGISTERED) { 1254 cid_match = clock_id ? dpll->clock_id == clock_id : true; 1255 mod_match = mod_name_attr ? (module_name(dpll->module) ? 1256 !nla_strcmp(mod_name_attr, 1257 module_name(dpll->module)) : false) : true; 1258 type_match = type ? dpll->type == type : true; 1259 if (cid_match && mod_match && type_match) { 1260 if (dpll_match) { 1261 NL_SET_ERR_MSG(extack, "multiple matches"); 1262 return ERR_PTR(-EINVAL); 1263 } 1264 dpll_match = dpll; 1265 } 1266 } 1267 if (!dpll_match) { 1268 NL_SET_ERR_MSG(extack, "not found"); 1269 return ERR_PTR(-ENODEV); 1270 } 1271 1272 return dpll_match; 1273 } 1274 1275 static struct dpll_device * 1276 dpll_device_find_from_nlattr(struct genl_info *info) 1277 { 1278 struct nlattr *attr, *mod_name_attr = NULL; 1279 enum dpll_type type = 0; 1280 u64 clock_id = 0; 1281 int rem = 0; 1282 1283 nla_for_each_attr(attr, genlmsg_data(info->genlhdr), 1284 genlmsg_len(info->genlhdr), rem) { 1285 switch (nla_type(attr)) { 1286 case DPLL_A_CLOCK_ID: 1287 if (clock_id) 1288 goto duplicated_attr; 1289 clock_id = nla_get_u64(attr); 1290 break; 1291 case DPLL_A_MODULE_NAME: 1292 if (mod_name_attr) 1293 goto duplicated_attr; 1294 mod_name_attr = attr; 1295 break; 1296 case DPLL_A_TYPE: 1297 if (type) 1298 goto duplicated_attr; 1299 type = nla_get_u32(attr); 1300 break; 1301 default: 1302 break; 1303 } 1304 } 1305 if (!clock_id && !mod_name_attr && !type) { 1306 NL_SET_ERR_MSG(info->extack, "missing attributes"); 1307 return ERR_PTR(-EINVAL); 1308 } 1309 return dpll_device_find(clock_id, mod_name_attr, type, info->extack); 1310 duplicated_attr: 1311 NL_SET_ERR_MSG(info->extack, "duplicated attribute"); 1312 return ERR_PTR(-EINVAL); 1313 } 1314 1315 int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info) 1316 { 1317 struct dpll_device *dpll; 1318 struct sk_buff *msg; 1319 struct nlattr *hdr; 1320 int ret; 1321 1322 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1323 if (!msg) 1324 return -ENOMEM; 1325 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0, 1326 DPLL_CMD_DEVICE_ID_GET); 1327 if (!hdr) { 1328 nlmsg_free(msg); 1329 return -EMSGSIZE; 1330 } 1331 1332 dpll = dpll_device_find_from_nlattr(info); 1333 if (!IS_ERR(dpll)) { 1334 ret = dpll_msg_add_dev_handle(msg, dpll); 1335 if (ret) { 1336 nlmsg_free(msg); 1337 return ret; 1338 } 1339 } 1340 genlmsg_end(msg, hdr); 1341 1342 return genlmsg_reply(msg, info); 1343 } 1344 1345 int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info) 1346 { 1347 struct dpll_device *dpll = info->user_ptr[0]; 1348 struct sk_buff *msg; 1349 struct nlattr *hdr; 1350 int ret; 1351 1352 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1353 if (!msg) 1354 return -ENOMEM; 1355 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0, 1356 DPLL_CMD_DEVICE_GET); 1357 if (!hdr) { 1358 nlmsg_free(msg); 1359 return -EMSGSIZE; 1360 } 1361 1362 ret = dpll_device_get_one(dpll, msg, info->extack); 1363 if (ret) { 1364 nlmsg_free(msg); 1365 return ret; 1366 } 1367 genlmsg_end(msg, hdr); 1368 1369 return genlmsg_reply(msg, info); 1370 } 1371 1372 int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info) 1373 { 1374 /* placeholder for set command */ 1375 return 0; 1376 } 1377 1378 int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 1379 { 1380 struct dpll_dump_ctx *ctx = dpll_dump_context(cb); 1381 struct dpll_device *dpll; 1382 struct nlattr *hdr; 1383 unsigned long i; 1384 int ret = 0; 1385 1386 mutex_lock(&dpll_lock); 1387 xa_for_each_marked_start(&dpll_device_xa, i, dpll, DPLL_REGISTERED, 1388 ctx->idx) { 1389 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, 1390 cb->nlh->nlmsg_seq, &dpll_nl_family, 1391 NLM_F_MULTI, DPLL_CMD_DEVICE_GET); 1392 if (!hdr) { 1393 ret = -EMSGSIZE; 1394 break; 1395 } 1396 ret = dpll_device_get_one(dpll, skb, cb->extack); 1397 if (ret) { 1398 genlmsg_cancel(skb, hdr); 1399 break; 1400 } 1401 genlmsg_end(skb, hdr); 1402 } 1403 mutex_unlock(&dpll_lock); 1404 1405 if (ret == -EMSGSIZE) { 1406 ctx->idx = i; 1407 return skb->len; 1408 } 1409 return ret; 1410 } 1411 1412 int dpll_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1413 struct genl_info *info) 1414 { 1415 u32 id; 1416 1417 if (GENL_REQ_ATTR_CHECK(info, DPLL_A_ID)) 1418 return -EINVAL; 1419 1420 mutex_lock(&dpll_lock); 1421 id = nla_get_u32(info->attrs[DPLL_A_ID]); 1422 info->user_ptr[0] = dpll_device_get_by_id(id); 1423 if (!info->user_ptr[0]) { 1424 NL_SET_ERR_MSG(info->extack, "device not found"); 1425 goto unlock; 1426 } 1427 return 0; 1428 unlock: 1429 mutex_unlock(&dpll_lock); 1430 return -ENODEV; 1431 } 1432 1433 void dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1434 struct genl_info *info) 1435 { 1436 mutex_unlock(&dpll_lock); 1437 } 1438 1439 int 1440 dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1441 struct genl_info *info) 1442 { 1443 mutex_lock(&dpll_lock); 1444 1445 return 0; 1446 } 1447 1448 void 1449 dpll_unlock_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1450 struct genl_info *info) 1451 { 1452 mutex_unlock(&dpll_lock); 1453 } 1454 1455 int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1456 struct genl_info *info) 1457 { 1458 int ret; 1459 1460 mutex_lock(&dpll_lock); 1461 if (GENL_REQ_ATTR_CHECK(info, DPLL_A_PIN_ID)) { 1462 ret = -EINVAL; 1463 goto unlock_dev; 1464 } 1465 info->user_ptr[0] = xa_load(&dpll_pin_xa, 1466 nla_get_u32(info->attrs[DPLL_A_PIN_ID])); 1467 if (!info->user_ptr[0] || 1468 !dpll_pin_available(info->user_ptr[0])) { 1469 NL_SET_ERR_MSG(info->extack, "pin not found"); 1470 ret = -ENODEV; 1471 goto unlock_dev; 1472 } 1473 1474 return 0; 1475 1476 unlock_dev: 1477 mutex_unlock(&dpll_lock); 1478 return ret; 1479 } 1480 1481 void dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, 1482 struct genl_info *info) 1483 { 1484 mutex_unlock(&dpll_lock); 1485 } 1486