@@ -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