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