@@ -212,6 +212,53 @@ dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin,
212
212
return 0 ;
213
213
}
214
214
215
+ static int
216
+ dpll_msg_add_pin_phase_adjust (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
+ s32 phase_adjust ;
223
+ int ret ;
224
+
225
+ if (!ops -> phase_adjust_get )
226
+ return 0 ;
227
+ ret = ops -> phase_adjust_get (pin , dpll_pin_on_dpll_priv (dpll , pin ),
228
+ dpll , dpll_priv (dpll ),
229
+ & phase_adjust , extack );
230
+ if (ret )
231
+ return ret ;
232
+ if (nla_put_s32 (msg , DPLL_A_PIN_PHASE_ADJUST , phase_adjust ))
233
+ return - EMSGSIZE ;
234
+
235
+ return 0 ;
236
+ }
237
+
238
+ static int
239
+ dpll_msg_add_phase_offset (struct sk_buff * msg , struct dpll_pin * pin ,
240
+ struct dpll_pin_ref * ref ,
241
+ struct netlink_ext_ack * extack )
242
+ {
243
+ const struct dpll_pin_ops * ops = dpll_pin_ops (ref );
244
+ struct dpll_device * dpll = ref -> dpll ;
245
+ s64 phase_offset ;
246
+ int ret ;
247
+
248
+ if (!ops -> phase_offset_get )
249
+ return 0 ;
250
+ ret = ops -> phase_offset_get (pin , dpll_pin_on_dpll_priv (dpll , pin ),
251
+ dpll , dpll_priv (dpll ), & phase_offset ,
252
+ extack );
253
+ if (ret )
254
+ return ret ;
255
+ if (nla_put_64bit (msg , DPLL_A_PIN_PHASE_OFFSET , sizeof (phase_offset ),
256
+ & phase_offset , DPLL_A_PIN_PAD ))
257
+ return - EMSGSIZE ;
258
+
259
+ return 0 ;
260
+ }
261
+
215
262
static int
216
263
dpll_msg_add_pin_freq (struct sk_buff * msg , struct dpll_pin * pin ,
217
264
struct dpll_pin_ref * ref , struct netlink_ext_ack * extack )
@@ -330,6 +377,9 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
330
377
if (ret )
331
378
goto nest_cancel ;
332
379
ret = dpll_msg_add_pin_direction (msg , pin , ref , extack );
380
+ if (ret )
381
+ goto nest_cancel ;
382
+ ret = dpll_msg_add_phase_offset (msg , pin , ref , extack );
333
383
if (ret )
334
384
goto nest_cancel ;
335
385
nla_nest_end (msg , attr );
@@ -377,6 +427,15 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
377
427
if (nla_put_u32 (msg , DPLL_A_PIN_CAPABILITIES , prop -> capabilities ))
378
428
return - EMSGSIZE ;
379
429
ret = dpll_msg_add_pin_freq (msg , pin , ref , extack );
430
+ if (ret )
431
+ return ret ;
432
+ if (nla_put_s32 (msg , DPLL_A_PIN_PHASE_ADJUST_MIN ,
433
+ prop -> phase_range .min ))
434
+ return - EMSGSIZE ;
435
+ if (nla_put_s32 (msg , DPLL_A_PIN_PHASE_ADJUST_MAX ,
436
+ prop -> phase_range .max ))
437
+ return - EMSGSIZE ;
438
+ ret = dpll_msg_add_pin_phase_adjust (msg , pin , ref , extack );
380
439
if (ret )
381
440
return ret ;
382
441
if (xa_empty (& pin -> parent_refs ))
@@ -416,7 +475,7 @@ dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
416
475
if (nla_put_u32 (msg , DPLL_A_TYPE , dpll -> type ))
417
476
return - EMSGSIZE ;
418
477
419
- return ret ;
478
+ return 0 ;
420
479
}
421
480
422
481
static int
@@ -556,8 +615,10 @@ static int
556
615
dpll_pin_freq_set (struct dpll_pin * pin , struct nlattr * a ,
557
616
struct netlink_ext_ack * extack )
558
617
{
559
- u64 freq = nla_get_u64 (a );
560
- struct dpll_pin_ref * ref ;
618
+ u64 freq = nla_get_u64 (a ), old_freq ;
619
+ struct dpll_pin_ref * ref , * failed ;
620
+ const struct dpll_pin_ops * ops ;
621
+ struct dpll_device * dpll ;
561
622
unsigned long i ;
562
623
int ret ;
563
624
@@ -567,19 +628,51 @@ dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
567
628
}
568
629
569
630
xa_for_each (& pin -> dpll_refs , i , ref ) {
570
- const struct dpll_pin_ops * ops = dpll_pin_ops (ref );
571
- struct dpll_device * dpll = ref -> dpll ;
572
-
573
- if (!ops -> frequency_set )
631
+ ops = dpll_pin_ops (ref );
632
+ if (!ops -> frequency_set || !ops -> frequency_get ) {
633
+ NL_SET_ERR_MSG (extack , "frequency set not supported by the device" );
574
634
return - EOPNOTSUPP ;
635
+ }
636
+ }
637
+ ref = dpll_xa_ref_dpll_first (& pin -> dpll_refs );
638
+ ops = dpll_pin_ops (ref );
639
+ dpll = ref -> dpll ;
640
+ ret = ops -> frequency_get (pin , dpll_pin_on_dpll_priv (dpll , pin ), dpll ,
641
+ dpll_priv (dpll ), & old_freq , extack );
642
+ if (ret ) {
643
+ NL_SET_ERR_MSG (extack , "unable to get old frequency value" );
644
+ return ret ;
645
+ }
646
+ if (freq == old_freq )
647
+ return 0 ;
648
+
649
+ xa_for_each (& pin -> dpll_refs , i , ref ) {
650
+ ops = dpll_pin_ops (ref );
651
+ dpll = ref -> dpll ;
575
652
ret = ops -> frequency_set (pin , dpll_pin_on_dpll_priv (dpll , pin ),
576
653
dpll , dpll_priv (dpll ), freq , extack );
577
- if (ret )
578
- return ret ;
654
+ if (ret ) {
655
+ failed = ref ;
656
+ NL_SET_ERR_MSG_FMT (extack , "frequency set failed for dpll_id:%u" ,
657
+ dpll -> id );
658
+ goto rollback ;
659
+ }
579
660
}
580
661
__dpll_pin_change_ntf (pin );
581
662
582
663
return 0 ;
664
+
665
+ rollback :
666
+ xa_for_each (& pin -> dpll_refs , i , ref ) {
667
+ if (ref == failed )
668
+ break ;
669
+ ops = dpll_pin_ops (ref );
670
+ dpll = ref -> dpll ;
671
+ if (ops -> frequency_set (pin , dpll_pin_on_dpll_priv (dpll , pin ),
672
+ dpll , dpll_priv (dpll ), old_freq , extack ))
673
+ NL_SET_ERR_MSG (extack , "set frequency rollback failed" );
674
+ }
675
+ return ret ;
583
676
}
584
677
585
678
static int
@@ -705,6 +798,78 @@ dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll,
705
798
return 0 ;
706
799
}
707
800
801
+ static int
802
+ dpll_pin_phase_adj_set (struct dpll_pin * pin , struct nlattr * phase_adj_attr ,
803
+ struct netlink_ext_ack * extack )
804
+ {
805
+ struct dpll_pin_ref * ref , * failed ;
806
+ const struct dpll_pin_ops * ops ;
807
+ s32 phase_adj , old_phase_adj ;
808
+ struct dpll_device * dpll ;
809
+ unsigned long i ;
810
+ int ret ;
811
+
812
+ phase_adj = nla_get_s32 (phase_adj_attr );
813
+ if (phase_adj > pin -> prop -> phase_range .max ||
814
+ phase_adj < pin -> prop -> phase_range .min ) {
815
+ NL_SET_ERR_MSG_ATTR (extack , phase_adj_attr ,
816
+ "phase adjust value not supported" );
817
+ return - EINVAL ;
818
+ }
819
+
820
+ xa_for_each (& pin -> dpll_refs , i , ref ) {
821
+ ops = dpll_pin_ops (ref );
822
+ if (!ops -> phase_adjust_set || !ops -> phase_adjust_get ) {
823
+ NL_SET_ERR_MSG (extack , "phase adjust not supported" );
824
+ return - EOPNOTSUPP ;
825
+ }
826
+ }
827
+ ref = dpll_xa_ref_dpll_first (& pin -> dpll_refs );
828
+ ops = dpll_pin_ops (ref );
829
+ dpll = ref -> dpll ;
830
+ ret = ops -> phase_adjust_get (pin , dpll_pin_on_dpll_priv (dpll , pin ),
831
+ dpll , dpll_priv (dpll ), & old_phase_adj ,
832
+ extack );
833
+ if (ret ) {
834
+ NL_SET_ERR_MSG (extack , "unable to get old phase adjust value" );
835
+ return ret ;
836
+ }
837
+ if (phase_adj == old_phase_adj )
838
+ return 0 ;
839
+
840
+ xa_for_each (& pin -> dpll_refs , i , ref ) {
841
+ ops = dpll_pin_ops (ref );
842
+ dpll = ref -> dpll ;
843
+ ret = ops -> phase_adjust_set (pin ,
844
+ dpll_pin_on_dpll_priv (dpll , pin ),
845
+ dpll , dpll_priv (dpll ), phase_adj ,
846
+ extack );
847
+ if (ret ) {
848
+ failed = ref ;
849
+ NL_SET_ERR_MSG_FMT (extack ,
850
+ "phase adjust set failed for dpll_id:%u" ,
851
+ dpll -> id );
852
+ goto rollback ;
853
+ }
854
+ }
855
+ __dpll_pin_change_ntf (pin );
856
+
857
+ return 0 ;
858
+
859
+ rollback :
860
+ xa_for_each (& pin -> dpll_refs , i , ref ) {
861
+ if (ref == failed )
862
+ break ;
863
+ ops = dpll_pin_ops (ref );
864
+ dpll = ref -> dpll ;
865
+ if (ops -> phase_adjust_set (pin , dpll_pin_on_dpll_priv (dpll , pin ),
866
+ dpll , dpll_priv (dpll ), old_phase_adj ,
867
+ extack ))
868
+ NL_SET_ERR_MSG (extack , "set phase adjust rollback failed" );
869
+ }
870
+ return ret ;
871
+ }
872
+
708
873
static int
709
874
dpll_pin_parent_device_set (struct dpll_pin * pin , struct nlattr * parent_nest ,
710
875
struct netlink_ext_ack * extack )
@@ -793,6 +958,11 @@ dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
793
958
if (ret )
794
959
return ret ;
795
960
break ;
961
+ case DPLL_A_PIN_PHASE_ADJUST :
962
+ ret = dpll_pin_phase_adj_set (pin , a , info -> extack );
963
+ if (ret )
964
+ return ret ;
965
+ break ;
796
966
case DPLL_A_PIN_PARENT_DEVICE :
797
967
ret = dpll_pin_parent_device_set (pin , a , info -> extack );
798
968
if (ret )
0 commit comments