Linux Audio

Check our new training course

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