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