@@ -342,6 +342,51 @@ dpll_msg_add_pin_freq(struct sk_buff *msg, struct dpll_pin *pin,
342
342
return 0 ;
343
343
}
344
344
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
+
345
390
static bool dpll_pin_is_freq_supported (struct dpll_pin * pin , u32 freq )
346
391
{
347
392
int fs ;
@@ -481,6 +526,9 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
481
526
if (ret )
482
527
return ret ;
483
528
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 );
484
532
if (ret )
485
533
return ret ;
486
534
if (xa_empty (& pin -> parent_refs ))
@@ -738,6 +786,83 @@ dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
738
786
return ret ;
739
787
}
740
788
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
+
741
866
static int
742
867
dpll_pin_on_pin_state_set (struct dpll_pin * pin , u32 parent_idx ,
743
868
enum dpll_pin_state state ,
@@ -1039,6 +1164,11 @@ dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
1039
1164
if (ret )
1040
1165
return ret ;
1041
1166
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 ;
1042
1172
}
1043
1173
}
1044
1174
0 commit comments