mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 23:23:03 +00:00
Merge branch 'dpll-expose-fractional-frequency-offset-value-to-user'
Jiri Pirko says: ==================== dpll: expose fractional frequency offset value to user Allow to expose pin fractional frequency offset value over new DPLL generic netlink attribute. Add an op to get the value from the driver. Implement this new op in mlx5 driver. ==================== Link: https://lore.kernel.org/r/20240103132838.1501801-1-jiri@resnulli.us Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
aa537fee61
@ -296,6 +296,16 @@ attribute-sets:
|
||||
-
|
||||
name: phase-offset
|
||||
type: s64
|
||||
-
|
||||
name: fractional-frequency-offset
|
||||
type: sint
|
||||
doc: |
|
||||
The FFO (Fractional Frequency Offset) between the RX and TX
|
||||
symbol rate on the media associated with the pin:
|
||||
(rx_frequency-tx_frequency)/rx_frequency
|
||||
Value is in PPM (parts per million).
|
||||
This may be implemented for example for pin of type
|
||||
PIN_TYPE_SYNCE_ETH_PORT.
|
||||
-
|
||||
name: pin-parent-device
|
||||
subset-of: pin
|
||||
@ -460,6 +470,7 @@ operations:
|
||||
- phase-adjust-min
|
||||
- phase-adjust-max
|
||||
- phase-adjust
|
||||
- fractional-frequency-offset
|
||||
|
||||
dump:
|
||||
pre: dpll-lock-dumpit
|
||||
|
@ -263,6 +263,27 @@ dpll_msg_add_phase_offset(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dpll_msg_add_ffo(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
struct dpll_pin_ref *ref,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
|
||||
struct dpll_device *dpll = ref->dpll;
|
||||
s64 ffo;
|
||||
int ret;
|
||||
|
||||
if (!ops->ffo_get)
|
||||
return 0;
|
||||
ret = ops->ffo_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
|
||||
dpll, dpll_priv(dpll), &ffo, extack);
|
||||
if (ret) {
|
||||
if (ret == -ENODATA)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
return nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET, ffo);
|
||||
}
|
||||
|
||||
static int
|
||||
dpll_msg_add_pin_freq(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
struct dpll_pin_ref *ref, struct netlink_ext_ack *extack)
|
||||
@ -440,6 +461,9 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
|
||||
prop->phase_range.max))
|
||||
return -EMSGSIZE;
|
||||
ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = dpll_msg_add_ffo(msg, pin, ref, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (xa_empty(&pin->parent_refs))
|
||||
|
@ -36,11 +36,17 @@ static int mlx5_dpll_clock_id_get(struct mlx5_core_dev *mdev, u64 *clock_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct mlx5_dpll_synce_status {
|
||||
enum mlx5_msees_admin_status admin_status;
|
||||
enum mlx5_msees_oper_status oper_status;
|
||||
bool ho_acq;
|
||||
bool oper_freq_measure;
|
||||
s32 frequency_diff;
|
||||
};
|
||||
|
||||
static int
|
||||
mlx5_dpll_synce_status_get(struct mlx5_core_dev *mdev,
|
||||
enum mlx5_msees_admin_status *admin_status,
|
||||
enum mlx5_msees_oper_status *oper_status,
|
||||
bool *ho_acq)
|
||||
struct mlx5_dpll_synce_status *synce_status)
|
||||
{
|
||||
u32 out[MLX5_ST_SZ_DW(msees_reg)] = {};
|
||||
u32 in[MLX5_ST_SZ_DW(msees_reg)] = {};
|
||||
@ -50,11 +56,11 @@ mlx5_dpll_synce_status_get(struct mlx5_core_dev *mdev,
|
||||
MLX5_REG_MSEES, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
if (admin_status)
|
||||
*admin_status = MLX5_GET(msees_reg, out, admin_status);
|
||||
*oper_status = MLX5_GET(msees_reg, out, oper_status);
|
||||
if (ho_acq)
|
||||
*ho_acq = MLX5_GET(msees_reg, out, ho_acq);
|
||||
synce_status->admin_status = MLX5_GET(msees_reg, out, admin_status);
|
||||
synce_status->oper_status = MLX5_GET(msees_reg, out, oper_status);
|
||||
synce_status->ho_acq = MLX5_GET(msees_reg, out, ho_acq);
|
||||
synce_status->oper_freq_measure = MLX5_GET(msees_reg, out, oper_freq_measure);
|
||||
synce_status->frequency_diff = MLX5_GET(msees_reg, out, frequency_diff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -67,21 +73,23 @@ mlx5_dpll_synce_status_set(struct mlx5_core_dev *mdev,
|
||||
|
||||
MLX5_SET(msees_reg, in, field_select,
|
||||
MLX5_MSEES_FIELD_SELECT_ENABLE |
|
||||
MLX5_MSEES_FIELD_SELECT_ADMIN_FREQ_MEASURE |
|
||||
MLX5_MSEES_FIELD_SELECT_ADMIN_STATUS);
|
||||
MLX5_SET(msees_reg, in, admin_status, admin_status);
|
||||
MLX5_SET(msees_reg, in, admin_freq_measure, true);
|
||||
return mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out),
|
||||
MLX5_REG_MSEES, 0, 1);
|
||||
}
|
||||
|
||||
static enum dpll_lock_status
|
||||
mlx5_dpll_lock_status_get(enum mlx5_msees_oper_status oper_status, bool ho_acq)
|
||||
mlx5_dpll_lock_status_get(struct mlx5_dpll_synce_status *synce_status)
|
||||
{
|
||||
switch (oper_status) {
|
||||
switch (synce_status->oper_status) {
|
||||
case MLX5_MSEES_OPER_STATUS_SELF_TRACK:
|
||||
fallthrough;
|
||||
case MLX5_MSEES_OPER_STATUS_OTHER_TRACK:
|
||||
return ho_acq ? DPLL_LOCK_STATUS_LOCKED_HO_ACQ :
|
||||
DPLL_LOCK_STATUS_LOCKED;
|
||||
return synce_status->ho_acq ? DPLL_LOCK_STATUS_LOCKED_HO_ACQ :
|
||||
DPLL_LOCK_STATUS_LOCKED;
|
||||
case MLX5_MSEES_OPER_STATUS_HOLDOVER:
|
||||
fallthrough;
|
||||
case MLX5_MSEES_OPER_STATUS_FAIL_HOLDOVER:
|
||||
@ -92,31 +100,37 @@ mlx5_dpll_lock_status_get(enum mlx5_msees_oper_status oper_status, bool ho_acq)
|
||||
}
|
||||
|
||||
static enum dpll_pin_state
|
||||
mlx5_dpll_pin_state_get(enum mlx5_msees_admin_status admin_status,
|
||||
enum mlx5_msees_oper_status oper_status)
|
||||
mlx5_dpll_pin_state_get(struct mlx5_dpll_synce_status *synce_status)
|
||||
{
|
||||
return (admin_status == MLX5_MSEES_ADMIN_STATUS_TRACK &&
|
||||
(oper_status == MLX5_MSEES_OPER_STATUS_SELF_TRACK ||
|
||||
oper_status == MLX5_MSEES_OPER_STATUS_OTHER_TRACK)) ?
|
||||
return (synce_status->admin_status == MLX5_MSEES_ADMIN_STATUS_TRACK &&
|
||||
(synce_status->oper_status == MLX5_MSEES_OPER_STATUS_SELF_TRACK ||
|
||||
synce_status->oper_status == MLX5_MSEES_OPER_STATUS_OTHER_TRACK)) ?
|
||||
DPLL_PIN_STATE_CONNECTED : DPLL_PIN_STATE_DISCONNECTED;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5_dpll_pin_ffo_get(struct mlx5_dpll_synce_status *synce_status,
|
||||
s64 *ffo)
|
||||
{
|
||||
if (!synce_status->oper_freq_measure)
|
||||
return -ENODATA;
|
||||
*ffo = synce_status->frequency_diff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_dpll_device_lock_status_get(const struct dpll_device *dpll,
|
||||
void *priv,
|
||||
enum dpll_lock_status *status,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
enum mlx5_msees_oper_status oper_status;
|
||||
struct mlx5_dpll_synce_status synce_status;
|
||||
struct mlx5_dpll *mdpll = priv;
|
||||
bool ho_acq;
|
||||
int err;
|
||||
|
||||
err = mlx5_dpll_synce_status_get(mdpll->mdev, NULL,
|
||||
&oper_status, &ho_acq);
|
||||
err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*status = mlx5_dpll_lock_status_get(oper_status, ho_acq);
|
||||
*status = mlx5_dpll_lock_status_get(&synce_status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -151,16 +165,14 @@ static int mlx5_dpll_state_on_dpll_get(const struct dpll_pin *pin,
|
||||
enum dpll_pin_state *state,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
enum mlx5_msees_admin_status admin_status;
|
||||
enum mlx5_msees_oper_status oper_status;
|
||||
struct mlx5_dpll_synce_status synce_status;
|
||||
struct mlx5_dpll *mdpll = pin_priv;
|
||||
int err;
|
||||
|
||||
err = mlx5_dpll_synce_status_get(mdpll->mdev, &admin_status,
|
||||
&oper_status, NULL);
|
||||
err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status);
|
||||
if (err)
|
||||
return err;
|
||||
*state = mlx5_dpll_pin_state_get(admin_status, oper_status);
|
||||
*state = mlx5_dpll_pin_state_get(&synce_status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -179,10 +191,25 @@ static int mlx5_dpll_state_on_dpll_set(const struct dpll_pin *pin,
|
||||
MLX5_MSEES_ADMIN_STATUS_FREE_RUNNING);
|
||||
}
|
||||
|
||||
static int mlx5_dpll_ffo_get(const struct dpll_pin *pin, void *pin_priv,
|
||||
const struct dpll_device *dpll, void *dpll_priv,
|
||||
s64 *ffo, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_dpll_synce_status synce_status;
|
||||
struct mlx5_dpll *mdpll = pin_priv;
|
||||
int err;
|
||||
|
||||
err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status);
|
||||
if (err)
|
||||
return err;
|
||||
return mlx5_dpll_pin_ffo_get(&synce_status, ffo);
|
||||
}
|
||||
|
||||
static const struct dpll_pin_ops mlx5_dpll_pins_ops = {
|
||||
.direction_get = mlx5_dpll_pin_direction_get,
|
||||
.state_on_dpll_get = mlx5_dpll_state_on_dpll_get,
|
||||
.state_on_dpll_set = mlx5_dpll_state_on_dpll_set,
|
||||
.ffo_get = mlx5_dpll_ffo_get,
|
||||
};
|
||||
|
||||
static const struct dpll_pin_properties mlx5_dpll_pin_properties = {
|
||||
@ -202,19 +229,16 @@ static void mlx5_dpll_periodic_work(struct work_struct *work)
|
||||
{
|
||||
struct mlx5_dpll *mdpll = container_of(work, struct mlx5_dpll,
|
||||
work.work);
|
||||
enum mlx5_msees_admin_status admin_status;
|
||||
enum mlx5_msees_oper_status oper_status;
|
||||
struct mlx5_dpll_synce_status synce_status;
|
||||
enum dpll_lock_status lock_status;
|
||||
enum dpll_pin_state pin_state;
|
||||
bool ho_acq;
|
||||
int err;
|
||||
|
||||
err = mlx5_dpll_synce_status_get(mdpll->mdev, &admin_status,
|
||||
&oper_status, &ho_acq);
|
||||
err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status);
|
||||
if (err)
|
||||
goto err_out;
|
||||
lock_status = mlx5_dpll_lock_status_get(oper_status, ho_acq);
|
||||
pin_state = mlx5_dpll_pin_state_get(admin_status, oper_status);
|
||||
lock_status = mlx5_dpll_lock_status_get(&synce_status);
|
||||
pin_state = mlx5_dpll_pin_state_get(&synce_status);
|
||||
|
||||
if (!mdpll->last.valid)
|
||||
goto invalid_out;
|
||||
|
@ -77,6 +77,9 @@ struct dpll_pin_ops {
|
||||
const struct dpll_device *dpll, void *dpll_priv,
|
||||
const s32 phase_adjust,
|
||||
struct netlink_ext_ack *extack);
|
||||
int (*ffo_get)(const struct dpll_pin *pin, void *pin_priv,
|
||||
const struct dpll_device *dpll, void *dpll_priv,
|
||||
s64 *ffo, struct netlink_ext_ack *extack);
|
||||
};
|
||||
|
||||
struct dpll_pin_frequency {
|
||||
|
@ -179,6 +179,7 @@ enum dpll_a_pin {
|
||||
DPLL_A_PIN_PHASE_ADJUST_MAX,
|
||||
DPLL_A_PIN_PHASE_ADJUST,
|
||||
DPLL_A_PIN_PHASE_OFFSET,
|
||||
DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET,
|
||||
|
||||
__DPLL_A_PIN_MAX,
|
||||
DPLL_A_PIN_MAX = (__DPLL_A_PIN_MAX - 1)
|
||||
|
Loading…
Reference in New Issue
Block a user