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