@@ -342,6 +342,51 @@ dpll_msg_add_pin_freq(struct sk_buff *msg, struct dpll_pin *pin,
342342	return  0 ;
343343}
344344
345+ static  int 
346+ dpll_msg_add_pin_esync (struct  sk_buff  * msg , struct  dpll_pin  * pin ,
347+ 		       struct  dpll_pin_ref  * ref , struct  netlink_ext_ack  * extack )
348+ {
349+ 	const  struct  dpll_pin_ops  * ops  =  dpll_pin_ops (ref );
350+ 	struct  dpll_device  * dpll  =  ref -> dpll ;
351+ 	struct  dpll_pin_esync  esync ;
352+ 	struct  nlattr  * nest ;
353+ 	int  ret , i ;
354+ 
355+ 	if  (!ops -> esync_get )
356+ 		return  0 ;
357+ 	ret  =  ops -> esync_get (pin , dpll_pin_on_dpll_priv (dpll , pin ), dpll ,
358+ 			     dpll_priv (dpll ), & esync , extack );
359+ 	if  (ret  ==  - EOPNOTSUPP )
360+ 		return  0 ;
361+ 	else  if  (ret )
362+ 		return  ret ;
363+ 	if  (nla_put_64bit (msg , DPLL_A_PIN_ESYNC_FREQUENCY , sizeof (esync .freq ),
364+ 			  & esync .freq , DPLL_A_PIN_PAD ))
365+ 		return  - EMSGSIZE ;
366+ 	if  (nla_put_u32 (msg , DPLL_A_PIN_ESYNC_PULSE , esync .pulse ))
367+ 		return  - EMSGSIZE ;
368+ 	for  (i  =  0 ; i  <  esync .range_num ; i ++ ) {
369+ 		nest  =  nla_nest_start (msg ,
370+ 				      DPLL_A_PIN_ESYNC_FREQUENCY_SUPPORTED );
371+ 		if  (!nest )
372+ 			return  - EMSGSIZE ;
373+ 		if  (nla_put_64bit (msg , DPLL_A_PIN_FREQUENCY_MIN ,
374+ 				  sizeof (esync .range [i ].min ),
375+ 				  & esync .range [i ].min , DPLL_A_PIN_PAD ))
376+ 			goto nest_cancel ;
377+ 		if  (nla_put_64bit (msg , DPLL_A_PIN_FREQUENCY_MAX ,
378+ 				  sizeof (esync .range [i ].max ),
379+ 				  & esync .range [i ].max , DPLL_A_PIN_PAD ))
380+ 			goto nest_cancel ;
381+ 		nla_nest_end (msg , nest );
382+ 	}
383+ 	return  0 ;
384+ 
385+ nest_cancel :
386+ 	nla_nest_cancel (msg , nest );
387+ 	return  - EMSGSIZE ;
388+ }
389+ 
345390static  bool  dpll_pin_is_freq_supported (struct  dpll_pin  * pin , u32  freq )
346391{
347392	int  fs ;
@@ -481,6 +526,9 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
481526	if  (ret )
482527		return  ret ;
483528	ret  =  dpll_msg_add_ffo (msg , pin , ref , extack );
529+ 	if  (ret )
530+ 		return  ret ;
531+ 	ret  =  dpll_msg_add_pin_esync (msg , pin , ref , extack );
484532	if  (ret )
485533		return  ret ;
486534	if  (xa_empty (& pin -> parent_refs ))
@@ -738,6 +786,83 @@ dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
738786	return  ret ;
739787}
740788
789+ static  int 
790+ dpll_pin_esync_set (struct  dpll_pin  * pin , struct  nlattr  * a ,
791+ 		   struct  netlink_ext_ack  * extack )
792+ {
793+ 	struct  dpll_pin_ref  * ref , * failed ;
794+ 	const  struct  dpll_pin_ops  * ops ;
795+ 	struct  dpll_pin_esync  esync ;
796+ 	u64  freq  =  nla_get_u64 (a );
797+ 	struct  dpll_device  * dpll ;
798+ 	bool  supported  =  false;
799+ 	unsigned long  i ;
800+ 	int  ret ;
801+ 
802+ 	xa_for_each (& pin -> dpll_refs , i , ref ) {
803+ 		ops  =  dpll_pin_ops (ref );
804+ 		if  (!ops -> esync_set  ||  !ops -> esync_get ) {
805+ 			NL_SET_ERR_MSG (extack ,
806+ 				       "embedded sync feature is not supported by this device" );
807+ 			return  - EOPNOTSUPP ;
808+ 		}
809+ 	}
810+ 	ref  =  dpll_xa_ref_dpll_first (& pin -> dpll_refs );
811+ 	ops  =  dpll_pin_ops (ref );
812+ 	dpll  =  ref -> dpll ;
813+ 	ret  =  ops -> esync_get (pin , dpll_pin_on_dpll_priv (dpll , pin ), dpll ,
814+ 			     dpll_priv (dpll ), & esync , extack );
815+ 	if  (ret ) {
816+ 		NL_SET_ERR_MSG (extack , "unable to get current embedded sync frequency value" );
817+ 		return  ret ;
818+ 	}
819+ 	if  (freq  ==  esync .freq )
820+ 		return  0 ;
821+ 	for  (i  =  0 ; i  <  esync .range_num ; i ++ )
822+ 		if  (freq  <= esync .range [i ].max  &&  freq  >= esync .range [i ].min )
823+ 			supported  =  true;
824+ 	if  (!supported ) {
825+ 		NL_SET_ERR_MSG_ATTR (extack , a ,
826+ 				    "requested embedded sync frequency value is not supported by this device" );
827+ 		return  - EINVAL ;
828+ 	}
829+ 
830+ 	xa_for_each (& pin -> dpll_refs , i , ref ) {
831+ 		void  * pin_dpll_priv ;
832+ 
833+ 		ops  =  dpll_pin_ops (ref );
834+ 		dpll  =  ref -> dpll ;
835+ 		pin_dpll_priv  =  dpll_pin_on_dpll_priv (dpll , pin );
836+ 		ret  =  ops -> esync_set (pin , pin_dpll_priv , dpll , dpll_priv (dpll ),
837+ 				      freq , extack );
838+ 		if  (ret ) {
839+ 			failed  =  ref ;
840+ 			NL_SET_ERR_MSG_FMT (extack ,
841+ 					   "embedded sync frequency set failed for dpll_id: %u" ,
842+ 					   dpll -> id );
843+ 			goto rollback ;
844+ 		}
845+ 	}
846+ 	__dpll_pin_change_ntf (pin );
847+ 
848+ 	return  0 ;
849+ 
850+ rollback :
851+ 	xa_for_each (& pin -> dpll_refs , i , ref ) {
852+ 		void  * pin_dpll_priv ;
853+ 
854+ 		if  (ref  ==  failed )
855+ 			break ;
856+ 		ops  =  dpll_pin_ops (ref );
857+ 		dpll  =  ref -> dpll ;
858+ 		pin_dpll_priv  =  dpll_pin_on_dpll_priv (dpll , pin );
859+ 		if  (ops -> esync_set (pin , pin_dpll_priv , dpll , dpll_priv (dpll ),
860+ 				   esync .freq , extack ))
861+ 			NL_SET_ERR_MSG (extack , "set embedded sync frequency rollback failed" );
862+ 	}
863+ 	return  ret ;
864+ }
865+ 
741866static  int 
742867dpll_pin_on_pin_state_set (struct  dpll_pin  * pin , u32  parent_idx ,
743868			  enum  dpll_pin_state  state ,
@@ -1039,6 +1164,11 @@ dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
10391164			if  (ret )
10401165				return  ret ;
10411166			break ;
1167+ 		case  DPLL_A_PIN_ESYNC_FREQUENCY :
1168+ 			ret  =  dpll_pin_esync_set (pin , a , info -> extack );
1169+ 			if  (ret )
1170+ 				return  ret ;
1171+ 			break ;
10421172		}
10431173	}
10441174
0 commit comments