Linux Audio

Check our new training course

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