@@ -212,6 +212,53 @@ dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin,
212212 return 0 ;
213213}
214214
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+
215262static int
216263dpll_msg_add_pin_freq (struct sk_buff * msg , struct dpll_pin * pin ,
217264 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,
330377 if (ret )
331378 goto nest_cancel ;
332379 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 );
333383 if (ret )
334384 goto nest_cancel ;
335385 nla_nest_end (msg , attr );
@@ -377,6 +427,15 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
377427 if (nla_put_u32 (msg , DPLL_A_PIN_CAPABILITIES , prop -> capabilities ))
378428 return - EMSGSIZE ;
379429 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 );
380439 if (ret )
381440 return ret ;
382441 if (xa_empty (& pin -> parent_refs ))
@@ -416,7 +475,7 @@ dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
416475 if (nla_put_u32 (msg , DPLL_A_TYPE , dpll -> type ))
417476 return - EMSGSIZE ;
418477
419- return ret ;
478+ return 0 ;
420479}
421480
422481static int
@@ -705,6 +764,78 @@ dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll,
705764 return 0 ;
706765}
707766
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+
708839static int
709840dpll_pin_parent_device_set (struct dpll_pin * pin , struct nlattr * parent_nest ,
710841 struct netlink_ext_ack * extack )
@@ -793,6 +924,11 @@ dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
793924 if (ret )
794925 return ret ;
795926 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 ;
796932 case DPLL_A_PIN_PARENT_DEVICE :
797933 ret = dpll_pin_parent_device_set (pin , a , info -> extack );
798934 if (ret )
0 commit comments