diff options
Diffstat (limited to 'drivers/dpll/dpll_netlink.c')
| -rw-r--r-- | drivers/dpll/dpll_netlink.c | 63 |
1 files changed, 53 insertions, 10 deletions
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index bf729cde796a..afb31c004038 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -567,6 +567,9 @@ dpll_msg_add_pin_ref_sync(struct sk_buff *msg, struct dpll_pin *pin, if (!dpll_pin_available(ref_sync_pin)) continue; ref_sync_pin_priv = dpll_pin_on_dpll_priv(dpll, ref_sync_pin); + /* Pin may have been unregistered from this dpll already */ + if (!ref_sync_pin_priv) + continue; if (WARN_ON(!ops->ref_sync_get)) return -EOPNOTSUPP; ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin, @@ -696,7 +699,9 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin, struct dpll_pin_ref *ref; int ret; - ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); + ref = dpll_pin_own_dpll_ref_first(pin); + if (!ref) + ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); ASSERT_NOT_NULL(ref); ret = dpll_msg_add_pin_handle(msg, pin); @@ -1087,12 +1092,19 @@ dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a, xa_for_each(&pin->dpll_refs, i, ref) { ops = dpll_pin_ops(ref); - if (!ops->frequency_set || !ops->frequency_get) { - NL_SET_ERR_MSG(extack, "frequency set not supported by the device"); + if ((!ops->frequency_set || !ops->frequency_get) && + ref->dpll->module == pin->module && + ref->dpll->clock_id == pin->clock_id) { + NL_SET_ERR_MSG(extack, + "frequency set not supported by the device"); return -EOPNOTSUPP; } } - ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); + ref = dpll_pin_own_dpll_ref_first(pin); + if (!ref) { + NL_SET_ERR_MSG(extack, "pin owner dpll not found"); + return -ENODEV; + } ops = dpll_pin_ops(ref); dpll = ref->dpll; ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll, @@ -1106,6 +1118,8 @@ dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a, xa_for_each(&pin->dpll_refs, i, ref) { ops = dpll_pin_ops(ref); + if (!ops->frequency_set) + continue; dpll = ref->dpll; ret = ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll, dpll_priv(dpll), freq, extack); @@ -1125,6 +1139,8 @@ rollback: if (ref == failed) break; ops = dpll_pin_ops(ref); + if (!ops->frequency_set) + continue; dpll = ref->dpll; if (ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll, dpll_priv(dpll), old_freq, extack)) @@ -1148,13 +1164,19 @@ dpll_pin_esync_set(struct dpll_pin *pin, struct nlattr *a, xa_for_each(&pin->dpll_refs, i, ref) { ops = dpll_pin_ops(ref); - if (!ops->esync_set || !ops->esync_get) { + if ((!ops->esync_set || !ops->esync_get) && + ref->dpll->module == pin->module && + ref->dpll->clock_id == pin->clock_id) { NL_SET_ERR_MSG(extack, "embedded sync feature is not supported by this device"); return -EOPNOTSUPP; } } - ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); + ref = dpll_pin_own_dpll_ref_first(pin); + if (!ref) { + NL_SET_ERR_MSG(extack, "pin owner dpll not found"); + return -ENODEV; + } ops = dpll_pin_ops(ref); dpll = ref->dpll; ret = ops->esync_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll, @@ -1178,6 +1200,8 @@ dpll_pin_esync_set(struct dpll_pin *pin, struct nlattr *a, void *pin_dpll_priv; ops = dpll_pin_ops(ref); + if (!ops->esync_set) + continue; dpll = ref->dpll; pin_dpll_priv = dpll_pin_on_dpll_priv(dpll, pin); ret = ops->esync_set(pin, pin_dpll_priv, dpll, dpll_priv(dpll), @@ -1201,6 +1225,8 @@ rollback: if (ref == failed) break; ops = dpll_pin_ops(ref); + if (!ops->esync_set) + continue; dpll = ref->dpll; pin_dpll_priv = dpll_pin_on_dpll_priv(dpll, pin); if (ops->esync_set(pin, pin_dpll_priv, dpll, dpll_priv(dpll), @@ -1235,8 +1261,11 @@ dpll_pin_ref_sync_state_set(struct dpll_pin *pin, NL_SET_ERR_MSG(extack, "reference sync pin not available"); return -EINVAL; } - ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); - ASSERT_NOT_NULL(ref); + ref = dpll_pin_own_dpll_ref_first(pin); + if (!ref) { + NL_SET_ERR_MSG(extack, "pin owner dpll not found"); + return -ENODEV; + } ops = dpll_pin_ops(ref); if (!ops->ref_sync_set || !ops->ref_sync_get) { NL_SET_ERR_MSG(extack, "reference sync not supported by this pin"); @@ -1255,6 +1284,8 @@ dpll_pin_ref_sync_state_set(struct dpll_pin *pin, return 0; xa_for_each(&pin->dpll_refs, i, ref) { ops = dpll_pin_ops(ref); + if (!ops->ref_sync_set) + continue; dpll = ref->dpll; ret = ops->ref_sync_set(pin, dpll_pin_on_dpll_priv(dpll, pin), ref_sync_pin, @@ -1277,6 +1308,8 @@ rollback: if (ref == failed) break; ops = dpll_pin_ops(ref); + if (!ops->ref_sync_set) + continue; dpll = ref->dpll; if (ops->ref_sync_set(pin, dpll_pin_on_dpll_priv(dpll, pin), ref_sync_pin, @@ -1468,12 +1501,18 @@ dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr, xa_for_each(&pin->dpll_refs, i, ref) { ops = dpll_pin_ops(ref); - if (!ops->phase_adjust_set || !ops->phase_adjust_get) { + if ((!ops->phase_adjust_set || !ops->phase_adjust_get) && + ref->dpll->module == pin->module && + ref->dpll->clock_id == pin->clock_id) { NL_SET_ERR_MSG(extack, "phase adjust not supported"); return -EOPNOTSUPP; } } - ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); + ref = dpll_pin_own_dpll_ref_first(pin); + if (!ref) { + NL_SET_ERR_MSG(extack, "pin owner dpll not found"); + return -ENODEV; + } ops = dpll_pin_ops(ref); dpll = ref->dpll; ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin), @@ -1488,6 +1527,8 @@ dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr, xa_for_each(&pin->dpll_refs, i, ref) { ops = dpll_pin_ops(ref); + if (!ops->phase_adjust_set) + continue; dpll = ref->dpll; ret = ops->phase_adjust_set(pin, dpll_pin_on_dpll_priv(dpll, pin), @@ -1510,6 +1551,8 @@ rollback: if (ref == failed) break; ops = dpll_pin_ops(ref); + if (!ops->phase_adjust_set) + continue; dpll = ref->dpll; if (ops->phase_adjust_set(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll, dpll_priv(dpll), old_phase_adj, |
