Skip to content

Commit d0cb324

Browse files
committed
Merge branch 'add-embedded-sync-feature-for-a-dpll-s-pin'
Arkadiusz Kubalewski says: ==================== Add Embedded SYNC feature for a dpll's pin Introduce and allow DPLL subsystem users to get/set capabilities of Embedded SYNC on a dpll's pin. Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> ==================== Link: https://patch.msgid.link/20240822222513.255179-1-arkadiusz.kubalewski@intel.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 2c16392 + 87abc56 commit d0cb324

File tree

8 files changed

+417
-5
lines changed

8 files changed

+417
-5
lines changed

Documentation/driver-api/dpll.rst

+21
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,27 @@ offset values are fractional with 3-digit decimal places and shell be
214214
divided with ``DPLL_PIN_PHASE_OFFSET_DIVIDER`` to get integer part and
215215
modulo divided to get fractional part.
216216

217+
Embedded SYNC
218+
=============
219+
220+
Device may provide ability to use Embedded SYNC feature. It allows
221+
to embed additional SYNC signal into the base frequency of a pin - a one
222+
special pulse of base frequency signal every time SYNC signal pulse
223+
happens. The user can configure the frequency of Embedded SYNC.
224+
The Embedded SYNC capability is always related to a given base frequency
225+
and HW capabilities. The user is provided a range of Embedded SYNC
226+
frequencies supported, depending on current base frequency configured for
227+
the pin.
228+
229+
========================================= =================================
230+
``DPLL_A_PIN_ESYNC_FREQUENCY`` current Embedded SYNC frequency
231+
``DPLL_A_PIN_ESYNC_FREQUENCY_SUPPORTED`` nest available Embedded SYNC
232+
frequency ranges
233+
``DPLL_A_PIN_FREQUENCY_MIN`` attr minimum value of frequency
234+
``DPLL_A_PIN_FREQUENCY_MAX`` attr maximum value of frequency
235+
``DPLL_A_PIN_ESYNC_PULSE`` pulse type of Embedded SYNC
236+
========================================= =================================
237+
217238
Configuration commands group
218239
============================
219240

Documentation/netlink/specs/dpll.yaml

+24
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,26 @@ attribute-sets:
345345
Value is in PPM (parts per million).
346346
This may be implemented for example for pin of type
347347
PIN_TYPE_SYNCE_ETH_PORT.
348+
-
349+
name: esync-frequency
350+
type: u64
351+
doc: |
352+
Frequency of Embedded SYNC signal. If provided, the pin is configured
353+
with a SYNC signal embedded into its base clock frequency.
354+
-
355+
name: esync-frequency-supported
356+
type: nest
357+
multi-attr: true
358+
nested-attributes: frequency-range
359+
doc: |
360+
If provided a pin is capable of embedding a SYNC signal (within given
361+
range) into its base frequency signal.
362+
-
363+
name: esync-pulse
364+
type: u32
365+
doc: |
366+
A ratio of high to low state of a SYNC signal pulse embedded
367+
into base clock frequency. Value is in percents.
348368
-
349369
name: pin-parent-device
350370
subset-of: pin
@@ -510,6 +530,9 @@ operations:
510530
- phase-adjust-max
511531
- phase-adjust
512532
- fractional-frequency-offset
533+
- esync-frequency
534+
- esync-frequency-supported
535+
- esync-pulse
513536

514537
dump:
515538
request:
@@ -536,6 +559,7 @@ operations:
536559
- parent-device
537560
- parent-pin
538561
- phase-adjust
562+
- esync-frequency
539563
-
540564
name: pin-create-ntf
541565
doc: Notification about pin appearing

drivers/dpll/dpll_netlink.c

+130
Original file line numberDiff line numberDiff line change
@@ -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+
345390
static 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+
741866
static int
742867
dpll_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

drivers/dpll/dpll_nl.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ static const struct nla_policy dpll_pin_get_dump_nl_policy[DPLL_A_PIN_ID + 1] =
6262
};
6363

6464
/* DPLL_CMD_PIN_SET - do */
65-
static const struct nla_policy dpll_pin_set_nl_policy[DPLL_A_PIN_PHASE_ADJUST + 1] = {
65+
static const struct nla_policy dpll_pin_set_nl_policy[DPLL_A_PIN_ESYNC_FREQUENCY + 1] = {
6666
[DPLL_A_PIN_ID] = { .type = NLA_U32, },
6767
[DPLL_A_PIN_FREQUENCY] = { .type = NLA_U64, },
6868
[DPLL_A_PIN_DIRECTION] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
@@ -71,6 +71,7 @@ static const struct nla_policy dpll_pin_set_nl_policy[DPLL_A_PIN_PHASE_ADJUST +
7171
[DPLL_A_PIN_PARENT_DEVICE] = NLA_POLICY_NESTED(dpll_pin_parent_device_nl_policy),
7272
[DPLL_A_PIN_PARENT_PIN] = NLA_POLICY_NESTED(dpll_pin_parent_pin_nl_policy),
7373
[DPLL_A_PIN_PHASE_ADJUST] = { .type = NLA_S32, },
74+
[DPLL_A_PIN_ESYNC_FREQUENCY] = { .type = NLA_U64, },
7475
};
7576

7677
/* Ops table for dpll */
@@ -138,7 +139,7 @@ static const struct genl_split_ops dpll_nl_ops[] = {
138139
.doit = dpll_nl_pin_set_doit,
139140
.post_doit = dpll_pin_post_doit,
140141
.policy = dpll_pin_set_nl_policy,
141-
.maxattr = DPLL_A_PIN_PHASE_ADJUST,
142+
.maxattr = DPLL_A_PIN_ESYNC_FREQUENCY,
142143
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
143144
},
144145
};

0 commit comments

Comments
 (0)