@@ -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
@@ -705,6 +764,78 @@ dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll,
705
764
return 0 ;
706
765
}
707
766
767
+ static int
768
+ dpll_pin_phase_adj_set (struct dpll_pin * pin , struct nlattr * phase_adj_attr ,
769
+ struct netlink_ext_ack * extack )
770
+ {
771
+ struct dpll_pin_ref * ref , * failed ;
772
+ const struct dpll_pin_ops * ops ;
773
+ s32 phase_adj , old_phase_adj ;
774
+ struct dpll_device * dpll ;
775
+ unsigned long i ;
776
+ int ret ;
777
+
778
+ phase_adj = nla_get_s32 (phase_adj_attr );
779
+ if (phase_adj > pin -> prop -> phase_range .max ||
780
+ phase_adj < pin -> prop -> phase_range .min ) {
781
+ NL_SET_ERR_MSG_ATTR (extack , phase_adj_attr ,
782
+ "phase adjust value not supported" );
783
+ return - EINVAL ;
784
+ }
785
+
786
+ xa_for_each (& pin -> dpll_refs , i , ref ) {
787
+ ops = dpll_pin_ops (ref );
788
+ if (!ops -> phase_adjust_set || !ops -> phase_adjust_get ) {
789
+ NL_SET_ERR_MSG (extack , "phase adjust not supported" );
790
+ return - EOPNOTSUPP ;
791
+ }
792
+ }
793
+ ref = dpll_xa_ref_dpll_first (& pin -> dpll_refs );
794
+ ops = dpll_pin_ops (ref );
795
+ dpll = ref -> dpll ;
796
+ ret = ops -> phase_adjust_get (pin , dpll_pin_on_dpll_priv (dpll , pin ),
797
+ dpll , dpll_priv (dpll ), & old_phase_adj ,
798
+ extack );
799
+ if (ret ) {
800
+ NL_SET_ERR_MSG (extack , "unable to get old phase adjust value" );
801
+ return ret ;
802
+ }
803
+ if (phase_adj == old_phase_adj )
804
+ return 0 ;
805
+
806
+ xa_for_each (& pin -> dpll_refs , i , ref ) {
807
+ ops = dpll_pin_ops (ref );
808
+ dpll = ref -> dpll ;
809
+ ret = ops -> phase_adjust_set (pin ,
810
+ dpll_pin_on_dpll_priv (dpll , pin ),
811
+ dpll , dpll_priv (dpll ), phase_adj ,
812
+ extack );
813
+ if (ret ) {
814
+ failed = ref ;
815
+ NL_SET_ERR_MSG_FMT (extack ,
816
+ "phase adjust set failed for dpll_id:%u" ,
817
+ dpll -> id );
818
+ goto rollback ;
819
+ }
820
+ }
821
+ __dpll_pin_change_ntf (pin );
822
+
823
+ return 0 ;
824
+
825
+ rollback :
826
+ xa_for_each (& pin -> dpll_refs , i , ref ) {
827
+ if (ref == failed )
828
+ break ;
829
+ ops = dpll_pin_ops (ref );
830
+ dpll = ref -> dpll ;
831
+ if (ops -> phase_adjust_set (pin , dpll_pin_on_dpll_priv (dpll , pin ),
832
+ dpll , dpll_priv (dpll ), old_phase_adj ,
833
+ extack ))
834
+ NL_SET_ERR_MSG (extack , "set phase adjust rollback failed" );
835
+ }
836
+ return ret ;
837
+ }
838
+
708
839
static int
709
840
dpll_pin_parent_device_set (struct dpll_pin * pin , struct nlattr * parent_nest ,
710
841
struct netlink_ext_ack * extack )
@@ -793,6 +924,11 @@ dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
793
924
if (ret )
794
925
return ret ;
795
926
break ;
927
+ case DPLL_A_PIN_PHASE_ADJUST :
928
+ ret = dpll_pin_phase_adj_set (pin , a , info -> extack );
929
+ if (ret )
930
+ return ret ;
931
+ break ;
796
932
case DPLL_A_PIN_PARENT_DEVICE :
797
933
ret = dpll_pin_parent_device_set (pin , a , info -> extack );
798
934
if (ret )
0 commit comments