diff --git a/Documentation/driver-api/dpll.rst b/Documentation/driver-api/dpll.rst index 8caa4af022ad..6e88990b3bc6 100644 --- a/Documentation/driver-api/dpll.rst +++ b/Documentation/driver-api/dpll.rst @@ -4,10 +4,25 @@ The Linux kernel dpll subsystem =============================== +DPLL +==== + +PLL - Phase Locked Loop is an electronic circuit which syntonizes clock +signal of a device with an external clock signal. Effectively enabling +device to run on the same clock signal beat as provided on a PLL input. + +DPLL - Digital Phase Locked Loop is am integrated circuit which in +addition to plain PLL behavior incorporates a digital phase detector +and may have digital divider in the loop. As a result, the frequency on +DPLL's input and output may be configurable. + +Subsystem +========= + The main purpose of dpll subsystem is to provide general interface to configure devices that use any kind of Digital PLL and could use -different sources of signal to synchronize to as well as different -types of outputs. +different sources of input signal to synchronize to, as well as +different types of outputs. The main interface is NETLINK_GENERIC based protocol with an event monitoring multicast group defined. @@ -63,16 +78,19 @@ for the states the user can request for a dpll device. In manual mode (``DPLL_MODE_MANUAL``) the user can request or receive one of following pin states: + - ``DPLL_PIN_STATE_CONNECTED`` - the pin is used to drive dpll device - ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not used to drive dpll device In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request or receive one of following pin states: + - ``DPLL_PIN_STATE_SELECTABLE`` - the pin shall be considered as valid input for automatic selection algorithm - ``DPLL_PIN_STATE_DISCONNECTED`` - the pin shall be not considered as a valid input for automatic selection algorithm + In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can only receive pin state ``DPLL_PIN_STATE_CONNECTED`` once automatic selection algorithm locks a dpll device with one of the inputs. @@ -85,6 +103,7 @@ Shared pins A single pin object can be attached to multiple dpll devices. Then there are two groups of configuration knobs: + 1) Set on a pin - the configuration affects all dpll devices pin is registered to (i.e. ``DPLL_A_PIN_FREQUENCY``), 2) Set on a pin-dpll tuple - the configuration affects only selected @@ -103,31 +122,32 @@ with. If a pin was registered with multiple parent pins, they behave like a multiple output multiplexer. In this case output of a ``DPLL_CMD_PIN_GET`` would contain multiple pin-parent nested -attributes with current state related to each parent, like: - -``'pin': [{ - {'clock-id': 282574471561216, - 'module-name': 'ice', - 'pin-dpll-caps': 4, - 'pin-id': 13, - 'pin-parent': [{'pin-id': 2, 'pin-state': 'connected'}, - {'pin-id': 3, 'pin-state': 'disconnected'}, - {'id': 0, 'pin-direction': 'input'}, - {'id': 1, 'pin-direction': 'input'}], - 'pin-type': 'synce-eth-port'} -}]`` +attributes with current state related to each parent, like:: + + 'pin': [{ + {'clock-id': 282574471561216, + 'module-name': 'ice', + 'pin-dpll-caps': 4, + 'pin-id': 13, + 'pin-parent': [{'pin-id': 2, 'pin-state': 'connected'}, + {'pin-id': 3, 'pin-state': 'disconnected'}, + {'id': 0, 'pin-direction': 'input'}, + {'id': 1, 'pin-direction': 'input'}], + 'pin-type': 'synce-eth-port'} + }] Only one child pin can provide its signal to the parent MUX-type pin at a time, the selection is done by requesting change of a child pin state on desired parent, with the use of ``DPLL_A_PIN_PARENT`` nested attribute. Example of netlink `set state on parent pin` message format: - ===================== ============================================= + ====================== ============================================= ``DPLL_A_PIN_ID`` child pin id ``DPLL_A_PIN_PARENT`` nested attribute for requesting configuration related to parent pin ``DPLL_A_PIN_ID`` parent pin id ``DPLL_A_PIN_STATE`` requested pin state on parent + ====================== ============================================= Pin priority ============ @@ -149,6 +169,7 @@ device. Example of netlink `set priority on parent pin` message format: related to parent pin ``DPLL_A_ID`` parent dpll id ``DPLL_A_PIN_PRIO`` requested pin prio on parent dpll + ===================== ============================================= Child pin of MUX-type is not capable of automatic input pin selection, in order to configure a input of a MUX-type pin, the user needs to @@ -176,11 +197,14 @@ prefix and suffix according to attribute purpose: ==================================== ================================= ``DPLL_CMD_DEVICE_ID_GET`` command to get device ID - ``DPLL_A_MODULE_NAME`` attr module name of registerer + ``DPLL_A_MODULE_NAME`` attr module name of registerer ``DPLL_A_CLOCK_ID`` attr Unique Clock Identifier (EUI-64), as defined by the IEEE 1588 standard ``DPLL_A_TYPE`` attr type of dpll device + ==================================== ================================= + + ==================================== ================================= ``DPLL_CMD_DEVICE_GET`` command to get device info or dump list of available devices ``DPLL_A_ID`` attr unique dpll device ID @@ -193,9 +217,15 @@ prefix and suffix according to attribute purpose: ``DPLL_A_LOCK_STATUS`` attr dpll device lock status ``DPLL_A_TEMP`` attr device temperature info ``DPLL_A_TYPE`` attr type of dpll device + ==================================== ================================= + + ==================================== ================================= ``DPLL_CMD_DEVICE_SET`` command to set dpll device config ``DPLL_A_ID`` attr internal dpll device index ``DPLL_A_MODE`` attr selection mode to configure + ==================================== ================================= + + ==================================== ================================= ``DPLL_CMD_PIN_GET`` command to get pin ID ``DPLL_A_MODULE_NAME`` attr module name of registerer ``DPLL_A_CLOCK_ID`` attr Unique Clock Identifier @@ -208,6 +238,9 @@ prefix and suffix according to attribute purpose: ``DPLL_A_PIN_PACKAGE_LABEL`` attr pin package label provided by registerer ``DPLL_A_PIN_TYPE`` attr type of a pin + ==================================== ================================= + + ==================================== ================================= ``DPLL_CMD_PIN_GET`` command to get pin info or dump list of available pins ``DPLL_A_PIN_ID`` attr unique a pin ID @@ -239,6 +272,9 @@ prefix and suffix according to attribute purpose: device or on the parent pin ``DPLL_A_PIN_DPLL_CAPS`` attr bitmask of pin-dpll capabilities + ==================================== ================================= + + ==================================== ================================= ``DPLL_CMD_PIN_SET`` command to set pins configuration ``DPLL_A_PIN_ID`` attr unique a pin ID ``DPLL_A_PIN_DIRECTION`` attr requested direction of a pin @@ -254,6 +290,7 @@ prefix and suffix according to attribute purpose: ``DPLL_A_PIN_STATE`` attr requested state of pin on the dpll device or on the parent pin + ==================================== ================================= Netlink dump requests ===================== @@ -287,82 +324,10 @@ In general, it is possible to configure multiple parameters at once, but internally each parameter change will be invoked separately, where order of configuration is not guaranteed by any means. -Device level configuration pre-defined enums -================================================= +Configuration pre-defined enums +=============================== -Values for ``DPLL_A_LOCK_STATUS`` attribute: - - ================================== =================================== - ``DPLL_LOCK_STATUS_UNLOCKED`` dpll device is in freerun, not - locked to any input pin - ``DPLL_LOCK_STATUS_LOCKED`` dpll device is locked to the input - but no holdover capability yet - acquired - ``DPLL_LOCK_STATUS_LOCKED_HO_ACQ`` dpll device is locked to the input - pin with holdover capability - acquired - ``DPLL_LOCK_STATUS_HOLDOVER`` dpll device lost a lock, using its - frequency holdover capabilities - -Values for ``DPLL_A_MODE`` attribute: - - ======================= ============================================== - ``DPLL_MODE_MANUAL`` input pin is manually selected by setting pin - state to ``DPLL_PIN_STATE_CONNECTED`` on a - dpll device - ``DPLL_MODE_AUTOMATIC`` input pin is auto selected according to - configured pin priorities and input signal - validity - ``DPLL_MODE_HOLDOVER`` force holdover mode of dpll - ``DPLL_MODE_FREERUN`` dpll device is driven by supplied system clock - without holdover capabilities - -Values for ``DPLL_A_TYPE`` attribute: - - ================= =================================================== - ``DPLL_TYPE_PPS`` dpll device used to provide pulse-per-second output - ``DPLL_TYPE_EEC`` dpll device used to drive ethernet equipment clock - -Pin level configuration pre-defined enums -========================================= - -Values for ``DPLL_A_PIN_STATE`` attribute: - - =============================== ====================================== - ``DPLL_PIN_STATE_CONNECTED`` Pin used as active input for a dpll - device or for a parent pin - ``DPLL_PIN_STATE_DISCONNECTED`` Pin disconnected from a dpll device or - from a parent pin - ``DPLL_PIN_STATE_SELECTABLE`` Pin enabled for automatic selection - -Values for ``DPLL_A_PIN_DIRECTION`` attribute: - - ============================= ==================================== - ``DPLL_PIN_DIRECTION_INPUT`` used to provide its signal to a dpll - device - ``DPLL_PIN_DIRECTION_OUTPUT`` used to output the signal from a dpll - device - -Values for ``DPLL_A_PIN_TYPE`` attributes: - - ================================ ===================================== - ``DPLL_PIN_TYPE_MUX`` MUX type pin, connected pins shall - have their own types - ``DPLL_PIN_TYPE_EXT`` External pin - ``DPLL_PIN_TYPE_SYNCE_ETH_PORT`` SyncE on Ethernet port - ``DPLL_PIN_TYPE_INT_OSCILLATOR`` Internal Oscillator (i.e. Holdover - with Atomic Clock as an input) - ``DPLL_PIN_TYPE_GNSS`` GNSS 1PPS input - -Values for ``DPLL_A_PIN_DPLL_CAPS`` attributes: - - ====================================== =============================== - ``DPLL_PIN_CAPS_DIRECTION_CAN_CHANGE`` Bit present if direction of - pin can change - ``DPLL_PIN_CAPS_PRIORITY_CAN_CHANGE`` Bit present if priority of pin - can change - ``DPLL_PIN_CAPS_STATE_CAN_CHANGE`` Bit present if state of pin can - change +.. kernel-doc:: include/uapi/linux/dpll.h Notifications ============= @@ -381,6 +346,7 @@ Notifications messages: ``DPLL_CMD_PIN_CREATE_NTF`` dpll pin was created ``DPLL_CMD_PIN_DELETE_NTF`` dpll pin was deleted ``DPLL_CMD_PIN_CHANGE_NTF`` dpll pin has changed + ============================== ===================================== Events format is the same as for the corresponding get command. Format of ``DPLL_CMD_DEVICE_`` events is the same as response of @@ -413,6 +379,7 @@ increases. Also dpll_pin_put() works similarly to dpll_device_put(). A pin can be registered with parent dpll device or parent pin, depending on hardware needs. Each registration requires registerer to provide set of pin callbacks, and private data pointer for calling them: + - dpll_pin_register() - register pin with a dpll device, - dpll_pin_on_pin_register() - register pin with another MUX type pin. @@ -422,6 +389,7 @@ Notifications about registering/deregistering pins are also invoked by the subsystem. Notifications about status changes either of dpll device or a pin are invoked in two ways: + - after successful change was requested on dpll subsystem, the subsystem calls corresponding notification, - requested by device driver with dpll_device_change_ntf() or @@ -431,16 +399,18 @@ The device driver using dpll interface is not required to implement all the callback operation. Neverthelessi, there are few required to be implemented. Required dpll device level callback operations: + - ``.mode_get``, - ``.lock_status_get``. Required pin level callback operations: + - ``.state_get`` (pins registered with dpll device), - ``.state_on_pin_get`` (pins registered with parent pin), - ``.direction_get``. Every other operation handler is checked for existence and -``-ENOTSUPP`` is returned in case of absence of specific handler. +``-EOPNOTSUPP`` is returned in case of absence of specific handler. SyncE enablement ================ @@ -451,8 +421,8 @@ inputs. In such scenario, dpll device input signal shall be also configurable to drive dpll with signal recovered from the PHY netdevice. This is done by exposing a pin to the netdevice - attaching pin to the -netdevice itself with: -netdev_dpll_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin); +netdevice itself with +``netdev_dpll_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin)``. Exposed pin id handle ``DPLL_A_PIN_ID`` is then identifiable by the user as it is attached to rtnetlink respond to get ``RTM_NEWLINK`` command in nested attribute ``IFLA_DPLL_PIN``. diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml index f7317003d312..af6258c3d8ec 100644 --- a/Documentation/netlink/specs/dpll.yaml +++ b/Documentation/netlink/specs/dpll.yaml @@ -9,7 +9,7 @@ definitions: type: enum name: mode doc: | - working-modes a dpll can support, differentiate if and how dpll selects + working modes a dpll can support, differentiates if and how dpll selects one of its inputs to syntonize with it, valid values for DPLL_A_MODE attribute entries: @@ -19,13 +19,7 @@ definitions: value: 1 - name: automatic - doc: highest prio, valid input, auto selected by dpll - - - name: holdover - doc: dpll forced into holdover mode - - - name: freerun - doc: dpll driven on system clk + doc: highest prio input pin auto selected by dpll render-max: true - type: enum @@ -37,8 +31,7 @@ definitions: - name: unlocked doc: | - dpll was not yet locked to any valid input (or is in mode: - DPLL_MODE_FREERUN) + dpll was not yet locked to any valid input value: 1 - name: locked @@ -52,11 +45,10 @@ definitions: name: holdover doc: | dpll is in holdover state - lost a valid lock or was forced - by selecting DPLL_MODE_HOLDOVER mode (latter possible only - when dpll lock-state was already DPLL_LOCK_STATUS_LOCKED, - if dpll lock-state was not DPLL_LOCK_STATUS_LOCKED, the - dpll's lock-state shall remain DPLL_LOCK_STATUS_UNLOCKED - even if DPLL_MODE_HOLDOVER was requested) + by disconnecting all the pins (latter possible only + when dpll lock-state was already DPLL_LOCK_STATUS_LOCKED_HO_ACQ, + if dpll lock-state was not DPLL_LOCK_STATUS_LOCKED_HO_ACQ, the + dpll's lock-state shall remain DPLL_LOCK_STATUS_UNLOCKED) render-max: true - type: const @@ -164,10 +156,13 @@ definitions: entries: - name: direction-can-change + doc: pin direction can be changed - name: priority-can-change + doc: pin prority can be changed - name: state-can-change + doc: pin state can be changed attribute-sets: - @@ -249,12 +244,17 @@ attribute-sets: name: pin-dpll-caps type: u32 - - name: pin-parent + name: pin-parent-device type: nest multi-attr: true - nested-attributes: pin-parent + nested-attributes: pin-parent-device + - + name: pin-parent-pin + type: nest + multi-attr: true + nested-attributes: pin-parent-pin - - name: pin-parent + name: pin-parent-device subset-of: dpll attributes: - @@ -269,10 +269,16 @@ attribute-sets: - name: pin-state type: u8 + - + name: pin-parent-pin + subset-of: dpll + attributes: + - + name: pin-state + type: u8 - name: pin-id type: u32 - - name: pin-frequency-range subset-of: dpll @@ -385,7 +391,7 @@ operations: - pin-type reply: attributes: - - id + - pin-id - name: pin-get @@ -404,7 +410,6 @@ operations: post: dpll-pin-post-doit request: attributes: - - id - pin-id reply: &pin-attrs attributes: @@ -415,8 +420,9 @@ operations: - pin-type - pin-frequency - pin-frequency-supported - - pin-parent - pin-dpll-caps + - pin-parent-device + - pin-parent-pin dump: pre: dpll-lock-dumpit @@ -437,13 +443,13 @@ operations: post: dpll-pin-post-doit request: attributes: - - id - pin-id - pin-frequency - pin-direction - pin-prio - pin-state - - pin-parent + - pin-parent-device + - pin-parent-pin - name: pin-create-ntf doc: Notification about pin appearing diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index e6efc17aaf26..049dd50a9e33 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -211,7 +211,7 @@ dpll_msg_add_pin_parents(struct sk_buff *msg, struct dpll_pin *pin, ppin, parent_priv, &state, extack); if (ret) return -EFAULT; - nest = nla_nest_start(msg, DPLL_A_PIN_PARENT); + nest = nla_nest_start(msg, DPLL_A_PIN_PARENT_PIN); if (!nest) return -EMSGSIZE; ret = dpll_msg_add_pin_handle(msg, ppin); @@ -241,7 +241,7 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin, int ret; xa_for_each(&pin->dpll_refs, index, ref) { - attr = nla_nest_start(msg, DPLL_A_PIN_PARENT); + attr = nla_nest_start(msg, DPLL_A_PIN_PARENT_DEVICE); if (!attr) return -EMSGSIZE; ret = dpll_msg_add_dev_handle(msg, ref->dpll); @@ -303,12 +303,14 @@ dpll_cmd_pin_fill_details(struct sk_buff *msg, struct dpll_pin *pin, size_t dpll_msg_pin_handle_size(struct dpll_pin *pin) { - return nla_total_size(4); /* DPLL_A_PIN_ID */ + return pin ? nla_total_size(4) : 0; /* DPLL_A_PIN_ID */ } EXPORT_SYMBOL_GPL(dpll_msg_pin_handle_size); int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin) { + if (!pin) + return 0; if (nla_put_u32(msg, DPLL_A_PIN_ID, pin->id)) return -EMSGSIZE; return 0; @@ -523,55 +525,45 @@ dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll, } static int -dpll_pin_parent_set(struct dpll_pin *pin, struct nlattr *parent_nest, - struct netlink_ext_ack *extack) +dpll_pin_parent_device_set(struct dpll_pin *pin, struct nlattr *parent_nest, + struct netlink_ext_ack *extack) { struct nlattr *tb[DPLL_A_MAX + 1]; enum dpll_pin_direction direction; - u32 ppin_idx, pdpll_idx, prio; enum dpll_pin_state state; struct dpll_pin_ref *ref; struct dpll_device *dpll; + u32 pdpll_idx, prio; int ret; nla_parse_nested(tb, DPLL_A_MAX, parent_nest, NULL, extack); - if ((tb[DPLL_A_ID] && tb[DPLL_A_PIN_ID]) || - !(tb[DPLL_A_ID] || tb[DPLL_A_PIN_ID])) { - NL_SET_ERR_MSG(extack, "one parent id expected"); + if (!tb[DPLL_A_ID]) { + NL_SET_ERR_MSG(extack, "device parent id expected"); return -EINVAL; } - if (tb[DPLL_A_ID]) { - pdpll_idx = nla_get_u32(tb[DPLL_A_ID]); - dpll = xa_load(&dpll_device_xa, pdpll_idx); - if (!dpll) - return -EINVAL; - ref = xa_load(&pin->dpll_refs, dpll->device_idx); - if (!ref) - return -EINVAL; - if (tb[DPLL_A_PIN_STATE]) { - state = nla_get_u8(tb[DPLL_A_PIN_STATE]); - ret = dpll_pin_state_set(dpll, pin, state, extack); - if (ret) - return ret; - } - if (tb[DPLL_A_PIN_PRIO]) { - prio = nla_get_u8(tb[DPLL_A_PIN_PRIO]); - ret = dpll_pin_prio_set(dpll, pin, prio, extack); - if (ret) - return ret; - } - if (tb[DPLL_A_PIN_DIRECTION]) { - direction = nla_get_u8(tb[DPLL_A_PIN_DIRECTION]); - ret = dpll_pin_direction_set(pin, dpll, direction, - extack); - if (ret) - return ret; - } - } else if (tb[DPLL_A_PIN_ID]) { - ppin_idx = nla_get_u32(tb[DPLL_A_PIN_ID]); + pdpll_idx = nla_get_u32(tb[DPLL_A_ID]); + dpll = xa_load(&dpll_device_xa, pdpll_idx); + if (!dpll) + return -EINVAL; + ref = xa_load(&pin->dpll_refs, dpll->device_idx); + if (!ref) + return -EINVAL; + if (tb[DPLL_A_PIN_STATE]) { state = nla_get_u8(tb[DPLL_A_PIN_STATE]); - ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack); + ret = dpll_pin_state_set(dpll, pin, state, extack); + if (ret) + return ret; + } + if (tb[DPLL_A_PIN_PRIO]) { + prio = nla_get_u8(tb[DPLL_A_PIN_PRIO]); + ret = dpll_pin_prio_set(dpll, pin, prio, extack); + if (ret) + return ret; + } + if (tb[DPLL_A_PIN_DIRECTION]) { + direction = nla_get_u8(tb[DPLL_A_PIN_DIRECTION]); + ret = dpll_pin_direction_set(pin, dpll, direction, extack); if (ret) return ret; } @@ -579,6 +571,30 @@ dpll_pin_parent_set(struct dpll_pin *pin, struct nlattr *parent_nest, return 0; } +static int +dpll_pin_parent_pin_set(struct dpll_pin *pin, struct nlattr *parent_nest, + struct netlink_ext_ack *extack) +{ + struct nlattr *tb[DPLL_A_MAX + 1]; + enum dpll_pin_state state; + u32 ppin_idx; + int ret; + + nla_parse_nested(tb, DPLL_A_MAX, parent_nest, + NULL, extack); + if (!tb[DPLL_A_PIN_ID]) { + NL_SET_ERR_MSG(extack, "parent pin id expected"); + return -EINVAL; + } + ppin_idx = nla_get_u32(tb[DPLL_A_PIN_ID]); + state = nla_get_u8(tb[DPLL_A_PIN_STATE]); + ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack); + if (ret) + return ret; + + return 0; +} + static int dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info) { @@ -593,8 +609,13 @@ dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info) if (ret) return ret; break; - case DPLL_A_PIN_PARENT: - ret = dpll_pin_parent_set(pin, a, info->extack); + case DPLL_A_PIN_PARENT_DEVICE: + ret = dpll_pin_parent_device_set(pin, a, info->extack); + if (ret) + return ret; + break; + case DPLL_A_PIN_PARENT_PIN: + ret = dpll_pin_parent_pin_set(pin, a, info->extack); if (ret) return ret; break; @@ -632,13 +653,15 @@ dpll_pin_find(u64 clock_id, struct nlattr *mod_name_attr, !nla_strcmp(mod_name_attr, module_name(pin->module)) : true; type_match = type ? prop->type == type : true; - board_match = board_label && prop->board_label ? - !nla_strcmp(board_label, prop->board_label) : true; - panel_match = panel_label && prop->panel_label ? - !nla_strcmp(panel_label, prop->panel_label) : true; - package_match = package_label && prop->package_label ? - !nla_strcmp(package_label, - prop->package_label) : true; + board_match = board_label ? (prop->board_label ? + !nla_strcmp(board_label, prop->board_label) : false) : + true; + panel_match = panel_label ? (prop->panel_label ? + !nla_strcmp(panel_label, prop->panel_label) : false) : + true; + package_match = package_label ? (prop->package_label ? + !nla_strcmp(package_label, prop->package_label) : + false) : true; if (cid_match && mod_match && type_match && board_match && panel_match && package_match) { if (pin_match) @@ -677,22 +700,22 @@ dpll_pin_find_from_nlattr(struct genl_info *info, struct sk_buff *skb) if (type) return -EINVAL; type = nla_get_u8(attr); - break; + break; case DPLL_A_PIN_BOARD_LABEL: if (board_label_attr) return -EINVAL; board_label_attr = attr; - break; + break; case DPLL_A_PIN_PANEL_LABEL: if (panel_label_attr) return -EINVAL; panel_label_attr = attr; - break; + break; case DPLL_A_PIN_PACKAGE_LABEL: if (package_label_attr) return -EINVAL; package_label_attr = attr; - break; + break; default: break; } @@ -807,9 +830,9 @@ dpll_device_find(u64 clock_id, struct nlattr *mod_name_attr, xa_for_each_marked(&dpll_device_xa, i, dpll, DPLL_REGISTERED) { cid_match = clock_id ? dpll->clock_id == clock_id : true; - mod_match = mod_name_attr && module_name(dpll->module) ? + mod_match = mod_name_attr ? (module_name(dpll->module) ? !nla_strcmp(mod_name_attr, - module_name(dpll->module)) : true; + module_name(dpll->module)) : false) : true; type_match = type ? dpll->type == type : true; if (cid_match && mod_match && type_match) { if (dpll_match) diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c index f5d1245deed9..3b5ed39971b4 100644 --- a/drivers/dpll/dpll_nl.c +++ b/drivers/dpll/dpll_nl.c @@ -11,11 +11,14 @@ #include /* Common nested types */ -const struct nla_policy dpll_pin_parent_nl_policy[DPLL_A_PIN_STATE + 1] = { +const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_STATE + 1] = { [DPLL_A_ID] = { .type = NLA_U32, }, - [DPLL_A_PIN_DIRECTION] = NLA_POLICY_MAX(NLA_U8, 2), + [DPLL_A_PIN_DIRECTION] = NLA_POLICY_RANGE(NLA_U8, 1, 2), [DPLL_A_PIN_PRIO] = { .type = NLA_U32, }, - [DPLL_A_PIN_STATE] = NLA_POLICY_MAX(NLA_U8, 3), + [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U8, 1, 3), +}; +const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1] = { + [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U8, 1, 3), [DPLL_A_PIN_ID] = { .type = NLA_U32, }, }; @@ -23,7 +26,7 @@ const struct nla_policy dpll_pin_parent_nl_policy[DPLL_A_PIN_STATE + 1] = { static const struct nla_policy dpll_device_id_get_nl_policy[DPLL_A_TYPE + 1] = { [DPLL_A_MODULE_NAME] = { .type = NLA_NUL_STRING, }, [DPLL_A_CLOCK_ID] = { .type = NLA_U64, }, - [DPLL_A_TYPE] = NLA_POLICY_MAX(NLA_U8, 2), + [DPLL_A_TYPE] = NLA_POLICY_RANGE(NLA_U8, 1, 2), }; /* DPLL_CMD_DEVICE_GET - do */ @@ -35,7 +38,7 @@ static const struct nla_policy dpll_device_get_nl_policy[DPLL_A_MODULE_NAME + 1] /* DPLL_CMD_DEVICE_SET - do */ static const struct nla_policy dpll_device_set_nl_policy[DPLL_A_MODE + 1] = { [DPLL_A_ID] = { .type = NLA_U32, }, - [DPLL_A_MODE] = NLA_POLICY_MAX(NLA_U8, 4), + [DPLL_A_MODE] = NLA_POLICY_RANGE(NLA_U8, 1, 2), }; /* DPLL_CMD_PIN_ID_GET - do */ @@ -45,12 +48,11 @@ static const struct nla_policy dpll_pin_id_get_nl_policy[DPLL_A_PIN_TYPE + 1] = [DPLL_A_PIN_BOARD_LABEL] = { .type = NLA_NUL_STRING, }, [DPLL_A_PIN_PANEL_LABEL] = { .type = NLA_NUL_STRING, }, [DPLL_A_PIN_PACKAGE_LABEL] = { .type = NLA_NUL_STRING, }, - [DPLL_A_PIN_TYPE] = NLA_POLICY_MAX(NLA_U8, 5), + [DPLL_A_PIN_TYPE] = NLA_POLICY_RANGE(NLA_U8, 1, 5), }; /* DPLL_CMD_PIN_GET - do */ static const struct nla_policy dpll_pin_get_do_nl_policy[DPLL_A_PIN_ID + 1] = { - [DPLL_A_ID] = { .type = NLA_U32, }, [DPLL_A_PIN_ID] = { .type = NLA_U32, }, }; @@ -60,14 +62,14 @@ static const struct nla_policy dpll_pin_get_dump_nl_policy[DPLL_A_ID + 1] = { }; /* DPLL_CMD_PIN_SET - do */ -static const struct nla_policy dpll_pin_set_nl_policy[DPLL_A_PIN_PARENT + 1] = { - [DPLL_A_ID] = { .type = NLA_U32, }, +static const struct nla_policy dpll_pin_set_nl_policy[DPLL_A_PIN_PARENT_PIN + 1] = { [DPLL_A_PIN_ID] = { .type = NLA_U32, }, [DPLL_A_PIN_FREQUENCY] = { .type = NLA_U64, }, - [DPLL_A_PIN_DIRECTION] = NLA_POLICY_MAX(NLA_U8, 2), + [DPLL_A_PIN_DIRECTION] = NLA_POLICY_RANGE(NLA_U8, 1, 2), [DPLL_A_PIN_PRIO] = { .type = NLA_U32, }, - [DPLL_A_PIN_STATE] = NLA_POLICY_MAX(NLA_U8, 3), - [DPLL_A_PIN_PARENT] = { .type = NLA_NESTED, }, + [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U8, 1, 3), + [DPLL_A_PIN_PARENT_DEVICE] = NLA_POLICY_NESTED(dpll_pin_parent_device_nl_policy), + [DPLL_A_PIN_PARENT_PIN] = NLA_POLICY_NESTED(dpll_pin_parent_pin_nl_policy), }; /* Ops table for dpll */ @@ -139,7 +141,7 @@ static const struct genl_split_ops dpll_nl_ops[] = { .doit = dpll_nl_pin_set_doit, .post_doit = dpll_pin_post_doit, .policy = dpll_pin_set_nl_policy, - .maxattr = DPLL_A_PIN_PARENT, + .maxattr = DPLL_A_PIN_PARENT_PIN, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, }; diff --git a/drivers/dpll/dpll_nl.h b/drivers/dpll/dpll_nl.h index 54d493778888..1f67aaed4742 100644 --- a/drivers/dpll/dpll_nl.h +++ b/drivers/dpll/dpll_nl.h @@ -12,7 +12,8 @@ #include /* Common nested types */ -extern const struct nla_policy dpll_pin_parent_nl_policy[DPLL_A_PIN_STATE + 1]; +extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_STATE + 1]; +extern const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1]; int dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb, struct genl_info *info); diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index a9e52e37be40..c306e4ac9f1b 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -7,6 +7,7 @@ #include "ice_flow.h" #define ICE_PF_RESET_WAIT_COUNT 300 +#define ICE_MAX_NETLIST_SIZE 10 static const char * const ice_link_mode_str_low[] = { [0] = "100BASE_TX", @@ -464,8 +465,6 @@ ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd, return 0; } -#define MAX_NETLIST_SIZE 10 - /** * ice_find_netlist_node * @hw: pointer to the hw struct @@ -486,7 +485,7 @@ ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx, u8 node_part_number, u16 rec_node_handle; u8 idx; - for (idx = 0; idx < MAX_NETLIST_SIZE; idx++) { + for (idx = 0; idx < ICE_MAX_NETLIST_SIZE; idx++) { int status; memset(&cmd, 0, sizeof(cmd)); @@ -5159,14 +5158,10 @@ ice_aq_get_output_pin_cfg(struct ice_hw *hw, u8 output_idx, u8 *flags, * * Return: signed 64 bit representation of signed 48 bit value. */ -static inline -s64 convert_s48_to_s64(s64 signed_48) +static s64 convert_s48_to_s64(s64 signed_48) { - const s64 MASK_SIGN_BITS = GENMASK_ULL(63, 48); - const s64 SIGN_BIT_47 = BIT_ULL(47); - - return ((signed_48 & SIGN_BIT_47) ? (s64)(MASK_SIGN_BITS | signed_48) - : signed_48); + return signed_48 & BIT_ULL(47) ? + GENMASK_ULL(63, 48) | signed_48 : signed_48; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c index 22a69197188a..c0a14d6d6ada 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.c +++ b/drivers/net/ethernet/intel/ice/ice_dpll.c @@ -11,12 +11,7 @@ #define ICE_DPLL_PIN_IDX_INVALID 0xff #define ICE_DPLL_RCLK_NUM_PER_PF 1 -/** - * dpll_lock_status - map ice cgu states into dpll's subsystem lock status - */ -static const enum dpll_lock_status -ice_dpll_status[__DPLL_LOCK_STATUS_MAX] = { - [ICE_CGU_STATE_INVALID] = 0, +static const enum dpll_lock_status ice_dpll_status[] = { [ICE_CGU_STATE_FREERUN] = DPLL_LOCK_STATUS_UNLOCKED, [ICE_CGU_STATE_LOCKED] = DPLL_LOCK_STATUS_LOCKED, [ICE_CGU_STATE_LOCKED_HO_ACQ] = DPLL_LOCK_STATUS_LOCKED_HO_ACQ, @@ -24,18 +19,19 @@ ice_dpll_status[__DPLL_LOCK_STATUS_MAX] = { }; /** - * ice_dpll_pin_type - enumerate ice pin types + * enum ice_dpll_pin_type - enumerate ice pin types: + * @ICE_DPLL_PIN_INVALID: invalid pin type + * @ICE_DPLL_PIN_TYPE_INPUT: input pin + * @ICE_DPLL_PIN_TYPE_OUTPUT: output pin + * @ICE_DPLL_PIN_TYPE_RCLK_INPUT: recovery clock input pin */ enum ice_dpll_pin_type { - ICE_DPLL_PIN_INVALID = 0, + ICE_DPLL_PIN_INVALID, ICE_DPLL_PIN_TYPE_INPUT, ICE_DPLL_PIN_TYPE_OUTPUT, ICE_DPLL_PIN_TYPE_RCLK_INPUT, }; -/** - * pin_type_name - string names of ice pin types - */ static const char * const pin_type_name[] = { [ICE_DPLL_PIN_TYPE_INPUT] = "input", [ICE_DPLL_PIN_TYPE_OUTPUT] = "output", @@ -45,6 +41,7 @@ static const char * const pin_type_name[] = { /** * ice_dpll_cb_lock - lock dplls mutex in callback context * @pf: private board structure + * @extack: error reporting * * Lock the mutex from the callback operations invoked by dpll subsystem. * Prevent dead lock caused by `rmmod ice` when dpll callbacks are under stress @@ -54,7 +51,7 @@ static const char * const pin_type_name[] = { * 0 - if lock acquired * negative - lock not acquired or dpll was deinitialized */ -static int ice_dpll_cb_lock(struct ice_pf *pf) +static int ice_dpll_cb_lock(struct ice_pf *pf, struct netlink_ext_ack *extack) { int i; @@ -62,9 +59,15 @@ static int ice_dpll_cb_lock(struct ice_pf *pf) if (mutex_trylock(&pf->dplls.lock)) return 0; usleep_range(100, 150); - if (!test_bit(ICE_FLAG_DPLL, pf->flags)) + if (!test_bit(ICE_FLAG_DPLL, pf->flags)) { + if (extack) + NL_SET_ERR_MSG(extack, + "ice dpll was deinitialized"); return -EFAULT; + } } + if (extack) + NL_SET_ERR_MSG(extack, "was not able to acquire mutex"); return -EBUSY; } @@ -86,6 +89,7 @@ static void ice_dpll_cb_unlock(struct ice_pf *pf) * @pin: pointer to a pin * @pin_type: type of pin being configured * @freq: frequency to be set + * @extack: error reporting * * Set requested frequency on a pin. * @@ -96,9 +100,10 @@ static void ice_dpll_cb_unlock(struct ice_pf *pf) */ static int ice_dpll_pin_freq_set(struct ice_pf *pf, struct ice_dpll_pin *pin, - enum ice_dpll_pin_type pin_type, const u32 freq) + enum ice_dpll_pin_type pin_type, const u32 freq, + struct netlink_ext_ack *extack) { - int ret = -EINVAL; + int ret; u8 flags; switch (pin_type) { @@ -113,13 +118,14 @@ ice_dpll_pin_freq_set(struct ice_pf *pf, struct ice_dpll_pin *pin, 0, freq, 0); break; default: - break; + return -EINVAL; } if (ret) { - dev_err(ice_pf_to_dev(pf), - "err:%d %s failed to set pin freq:%u on pin:%u\n", - ret, ice_aq_str(pf->hw.adminq.sq_last_status), - freq, pin->idx); + NL_SET_ERR_MSG_FMT(extack, + "err:%d %s failed to set pin freq:%u on pin:%u\n", + ret, + ice_aq_str(pf->hw.adminq.sq_last_status), + freq, pin->idx); return ret; } pin->freq = freq; @@ -151,17 +157,16 @@ ice_dpll_frequency_set(const struct dpll_pin *pin, void *pin_priv, struct netlink_ext_ack *extack, enum ice_dpll_pin_type pin_type) { - struct ice_pf *pf = ((struct ice_dpll *)dpll_priv)->pf; struct ice_dpll_pin *p = pin_priv; - int ret = -EINVAL; + struct ice_dpll *d = dpll_priv; + struct ice_pf *pf = d->pf; + int ret; - ret = ice_dpll_cb_lock(pf); + ret = ice_dpll_cb_lock(pf, extack); if (ret) return ret; - ret = ice_dpll_pin_freq_set(pf, p, pin_type, frequency); + ret = ice_dpll_pin_freq_set(pf, p, pin_type, frequency, extack); ice_dpll_cb_unlock(pf); - if (ret) - NL_SET_ERR_MSG(extack, "frequency was not set"); return ret; } @@ -239,11 +244,12 @@ ice_dpll_frequency_get(const struct dpll_pin *pin, void *pin_priv, u64 *frequency, struct netlink_ext_ack *extack, enum ice_dpll_pin_type pin_type) { - struct ice_pf *pf = ((struct ice_dpll *)dpll_priv)->pf; struct ice_dpll_pin *p = pin_priv; - int ret = -EINVAL; + struct ice_dpll *d = dpll_priv; + struct ice_pf *pf = d->pf; + int ret; - ret = ice_dpll_cb_lock(pf); + ret = ice_dpll_cb_lock(pf, extack); if (ret) return ret; *frequency = p->freq; @@ -307,6 +313,7 @@ ice_dpll_output_frequency_get(const struct dpll_pin *pin, void *pin_priv, * @hw: board private hw structure * @pin: pointer to a pin * @pin_type: type of pin being enabled + * @extack: error reporting * * Enable a pin on both dplls. Store current state in pin->flags. * @@ -317,10 +324,11 @@ ice_dpll_output_frequency_get(const struct dpll_pin *pin, void *pin_priv, */ static int ice_dpll_pin_enable(struct ice_hw *hw, struct ice_dpll_pin *pin, - enum ice_dpll_pin_type pin_type) + enum ice_dpll_pin_type pin_type, + struct netlink_ext_ack *extack) { - int ret = -EINVAL; u8 flags = 0; + int ret; switch (pin_type) { case ICE_DPLL_PIN_TYPE_INPUT: @@ -336,13 +344,13 @@ ice_dpll_pin_enable(struct ice_hw *hw, struct ice_dpll_pin *pin, ret = ice_aq_set_output_pin_cfg(hw, pin->idx, flags, 0, 0, 0); break; default: - break; + return -EINVAL; } if (ret) - dev_err(ice_pf_to_dev((struct ice_pf *)(hw->back)), - "err:%d %s failed to enable %s pin:%u\n", - ret, ice_aq_str(hw->adminq.sq_last_status), - pin_type_name[pin_type], pin->idx); + NL_SET_ERR_MSG_FMT(extack, + "err:%d %s failed to enable %s pin:%u\n", + ret, ice_aq_str(hw->adminq.sq_last_status), + pin_type_name[pin_type], pin->idx); return ret; } @@ -352,6 +360,7 @@ ice_dpll_pin_enable(struct ice_hw *hw, struct ice_dpll_pin *pin, * @hw: board private hw structure * @pin: pointer to a pin * @pin_type: type of pin being disabled + * @extack: error reporting * * Disable a pin on both dplls. Store current state in pin->flags. * @@ -362,10 +371,11 @@ ice_dpll_pin_enable(struct ice_hw *hw, struct ice_dpll_pin *pin, */ static int ice_dpll_pin_disable(struct ice_hw *hw, struct ice_dpll_pin *pin, - enum ice_dpll_pin_type pin_type) + enum ice_dpll_pin_type pin_type, + struct netlink_ext_ack *extack) { - int ret = -EINVAL; u8 flags = 0; + int ret; switch (pin_type) { case ICE_DPLL_PIN_TYPE_INPUT: @@ -379,22 +389,23 @@ ice_dpll_pin_disable(struct ice_hw *hw, struct ice_dpll_pin *pin, ret = ice_aq_set_output_pin_cfg(hw, pin->idx, flags, 0, 0, 0); break; default: - break; + return -EINVAL; } if (ret) - dev_err(ice_pf_to_dev((struct ice_pf *)(hw->back)), - "err:%d %s failed to disable %s pin:%u\n", - ret, ice_aq_str(hw->adminq.sq_last_status), - pin_type_name[pin_type], pin->idx); + NL_SET_ERR_MSG_FMT(extack, + "err:%d %s failed to disable %s pin:%u\n", + ret, ice_aq_str(hw->adminq.sq_last_status), + pin_type_name[pin_type], pin->idx); return ret; } /** * ice_dpll_pin_state_update - update pin's state - * @hw: private board struct + * @pf: private board struct * @pin: structure with pin attributes to be updated * @pin_type: type of pin being updated + * @extack: error reporting * * Determine pin current state and frequency, then update struct * holding the pin info. For input pin states are separated for each @@ -407,15 +418,18 @@ ice_dpll_pin_disable(struct ice_hw *hw, struct ice_dpll_pin *pin, */ int ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin, - enum ice_dpll_pin_type pin_type) + enum ice_dpll_pin_type pin_type, + struct netlink_ext_ack *extack) { - int ret = -EINVAL; + int ret; switch (pin_type) { case ICE_DPLL_PIN_TYPE_INPUT: ret = ice_aq_get_input_pin_cfg(&pf->hw, pin->idx, NULL, NULL, NULL, &pin->flags[0], &pin->freq, NULL); + if (ret) + goto err; if (ICE_AQC_GET_CGU_IN_CFG_FLG2_INPUT_EN & pin->flags[0]) { if (pin->pin) { pin->state[pf->dplls.eec.dpll_idx] = @@ -443,6 +457,8 @@ ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin, ret = ice_aq_get_output_pin_cfg(&pf->hw, pin->idx, &pin->flags[0], NULL, &pin->freq, NULL); + if (ret) + goto err; if (ICE_AQC_SET_CGU_OUT_CFG_OUT_EN & pin->flags[0]) pin->state[0] = DPLL_PIN_STATE_CONNECTED; else @@ -458,7 +474,7 @@ ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin, &pin->flags[parent], &pin->freq); if (ret) - return ret; + goto err; if (ICE_AQC_GET_PHY_REC_CLK_OUT_OUT_EN & pin->flags[parent]) pin->state[parent] = DPLL_PIN_STATE_CONNECTED; @@ -468,38 +484,33 @@ ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin, } break; default: - break; + return -EINVAL; } + return 0; +err: + if (extack) + NL_SET_ERR_MSG_FMT(extack, + "err:%d %s failed to update %s pin:%u\n", + ret, + ice_aq_str(pf->hw.adminq.sq_last_status), + pin_type_name[pin_type], pin->idx); + else + dev_err_ratelimited(ice_pf_to_dev(pf), + "err:%d %s failed to update %s pin:%u\n", + ret, + ice_aq_str(pf->hw.adminq.sq_last_status), + pin_type_name[pin_type], pin->idx); return ret; } -/** - * ice_find_dpll - find ice_dpll on a pf - * @pf: private board structure - * @dpll: kernel's dpll_device pointer to be searched - * - * Context: Called under pf->dplls.lock - * Return: - * * pointer if ice_dpll with given device dpll pointer is found - * * NULL if not found - */ -static struct ice_dpll -*ice_find_dpll(struct ice_pf *pf, const struct dpll_device *dpll) -{ - if (!pf || !dpll) - return NULL; - - return dpll == pf->dplls.eec.dpll ? &pf->dplls.eec : - dpll == pf->dplls.pps.dpll ? &pf->dplls.pps : NULL; -} - /** * ice_dpll_hw_input_prio_set - set input priority value in hardware * @pf: board private structure * @dpll: ice dpll pointer * @pin: ice pin pointer * @prio: priority value being set on a dpll + * @extack: error reporting * * Internal wrapper for setting the priority in the hardware. * @@ -510,17 +521,19 @@ static struct ice_dpll */ static int ice_dpll_hw_input_prio_set(struct ice_pf *pf, struct ice_dpll *dpll, - struct ice_dpll_pin *pin, const u32 prio) + struct ice_dpll_pin *pin, const u32 prio, + struct netlink_ext_ack *extack) { int ret; ret = ice_aq_set_cgu_ref_prio(&pf->hw, dpll->dpll_idx, pin->idx, (u8)prio); if (ret) - dev_err(ice_pf_to_dev(pf), - "err:%d %s failed to set pin prio:%u on pin:%u\n", - ret, ice_aq_str(pf->hw.adminq.sq_last_status), - prio, pin->idx); + NL_SET_ERR_MSG_FMT(extack, + "err:%d %s failed to set pin prio:%u on pin:%u\n", + ret, + ice_aq_str(pf->hw.adminq.sq_last_status), + prio, pin->idx); else dpll->input_prio[pin->idx] = prio; @@ -530,7 +543,9 @@ ice_dpll_hw_input_prio_set(struct ice_pf *pf, struct ice_dpll *dpll, /** * ice_dpll_lock_status_get - get dpll lock status callback * @dpll: registered dpll pointer + * @dpll_priv: private data pointer passed on dpll registration * @status: on success holds dpll's lock status + * @extack: error reporting * * Dpll subsystem callback, provides dpll's lock status. * @@ -539,21 +554,20 @@ ice_dpll_hw_input_prio_set(struct ice_pf *pf, struct ice_dpll *dpll, * * 0 - success * * negative - failure */ -static int ice_dpll_lock_status_get(const struct dpll_device *dpll, void *priv, - enum dpll_lock_status *status, - struct netlink_ext_ack *extack) +static int +ice_dpll_lock_status_get(const struct dpll_device *dpll, void *dpll_priv, + enum dpll_lock_status *status, + struct netlink_ext_ack *extack) { - struct ice_dpll *d = priv; + struct ice_dpll *d = dpll_priv; struct ice_pf *pf = d->pf; - int ret = -EINVAL; + int ret; - ret = ice_dpll_cb_lock(pf); + ret = ice_dpll_cb_lock(pf, extack); if (ret) return ret; *status = ice_dpll_status[d->dpll_state]; ice_dpll_cb_unlock(pf); - dev_dbg(ice_pf_to_dev(pf), "%s: dpll:%p, pf:%p, ret:%d\n", __func__, - dpll, pf, ret); return ret; } @@ -561,7 +575,7 @@ static int ice_dpll_lock_status_get(const struct dpll_device *dpll, void *priv, /** * ice_dpll_mode_get - get dpll's working mode * @dpll: registered dpll pointer - * @priv: private data pointer passed on dpll registration + * @dpll_priv: private data pointer passed on dpll registration * @mode: on success holds current working mode of dpll * @extack: error reporting * @@ -571,7 +585,7 @@ static int ice_dpll_lock_status_get(const struct dpll_device *dpll, void *priv, * * 0 - success * * negative - failure */ -static int ice_dpll_mode_get(const struct dpll_device *dpll, void *priv, +static int ice_dpll_mode_get(const struct dpll_device *dpll, void *dpll_priv, enum dpll_mode *mode, struct netlink_ext_ack *extack) { @@ -581,9 +595,9 @@ static int ice_dpll_mode_get(const struct dpll_device *dpll, void *priv, } /** - * ice_dpll_mode_get - check if dpll's working mode is supported + * ice_dpll_mode_supported - check if dpll's working mode is supported * @dpll: registered dpll pointer - * @priv: private data pointer passed on dpll registration + * @dpll_priv: private data pointer passed on dpll registration * @mode: mode to be checked for support * @extack: error reporting * @@ -594,7 +608,8 @@ static int ice_dpll_mode_get(const struct dpll_device *dpll, void *priv, * * true - mode is supported * * false - mode is not supported */ -static bool ice_dpll_mode_supported(const struct dpll_device *dpll, void *priv, +static bool ice_dpll_mode_supported(const struct dpll_device *dpll, + void *dpll_priv, enum dpll_mode mode, struct netlink_ext_ack *extack) { @@ -610,7 +625,7 @@ static bool ice_dpll_mode_supported(const struct dpll_device *dpll, void *priv, * @pin_priv: private data pointer passed on pin registration * @dpll: registered dpll pointer * @dpll_priv: private data pointer passed on dpll registration - * @state: state of pin to be set + * @enable: if pin shalll be enabled * @extack: error reporting * @pin_type: type of a pin * @@ -627,24 +642,21 @@ ice_dpll_pin_state_set(const struct dpll_pin *pin, void *pin_priv, bool enable, struct netlink_ext_ack *extack, enum ice_dpll_pin_type pin_type) { - struct ice_pf *pf = ((struct ice_dpll *)dpll_priv)->pf; struct ice_dpll_pin *p = pin_priv; - int ret = -EINVAL; + struct ice_dpll *d = dpll_priv; + struct ice_pf *pf = d->pf; + int ret; - ret = ice_dpll_cb_lock(pf); + ret = ice_dpll_cb_lock(pf, extack); if (ret) return ret; if (enable) - ret = ice_dpll_pin_enable(&pf->hw, p, pin_type); + ret = ice_dpll_pin_enable(&pf->hw, p, pin_type, extack); else - ret = ice_dpll_pin_disable(&pf->hw, p, pin_type); + ret = ice_dpll_pin_disable(&pf->hw, p, pin_type, extack); if (!ret) - ret = ice_dpll_pin_state_update(pf, p, pin_type); + ret = ice_dpll_pin_state_update(pf, p, pin_type, extack); ice_dpll_cb_unlock(pf); - if (ret) - dev_err(ice_pf_to_dev(pf), - "%s: dpll:%p, pin:%p, p:%p pf:%p enable:%d ret:%d\n", - __func__, dpll, pin, p, pf, enable, ret); return ret; } @@ -671,7 +683,7 @@ ice_dpll_output_state_set(const struct dpll_pin *pin, void *pin_priv, enum dpll_pin_state state, struct netlink_ext_ack *extack) { - bool enable = state == DPLL_PIN_STATE_CONNECTED ? true : false; + bool enable = state == DPLL_PIN_STATE_CONNECTED; return ice_dpll_pin_state_set(pin, pin_priv, dpll, dpll_priv, enable, extack, ICE_DPLL_PIN_TYPE_OUTPUT); @@ -699,7 +711,7 @@ ice_dpll_input_state_set(const struct dpll_pin *pin, void *pin_priv, enum dpll_pin_state state, struct netlink_ext_ack *extack) { - bool enable = state == DPLL_PIN_STATE_SELECTABLE ? true : false; + bool enable = state == DPLL_PIN_STATE_SELECTABLE; return ice_dpll_pin_state_set(pin, pin_priv, dpll, dpll_priv, enable, extack, ICE_DPLL_PIN_TYPE_INPUT); @@ -724,23 +736,20 @@ ice_dpll_input_state_set(const struct dpll_pin *pin, void *pin_priv, */ static int ice_dpll_pin_state_get(const struct dpll_pin *pin, void *pin_priv, - const struct dpll_device *dpll, void *dpll_priv, + const struct dpll_device *dpll, void *dpll_priv, enum dpll_pin_state *state, struct netlink_ext_ack *extack, enum ice_dpll_pin_type pin_type) { - struct ice_pf *pf = ((struct ice_dpll *)dpll_priv)->pf; struct ice_dpll_pin *p = pin_priv; - struct ice_dpll *d; - int ret = -EINVAL; + struct ice_dpll *d = dpll_priv; + struct ice_pf *pf = d->pf; + int ret; - ret = ice_dpll_cb_lock(pf); + ret = ice_dpll_cb_lock(pf, extack); if (ret) return ret; - d = ice_find_dpll(pf, dpll); - if (!d) - goto unlock; - ret = ice_dpll_pin_state_update(pf, p, pin_type); + ret = ice_dpll_pin_state_update(pf, p, pin_type, extack); if (ret) goto unlock; if (pin_type == ICE_DPLL_PIN_TYPE_INPUT) @@ -750,10 +759,6 @@ ice_dpll_pin_state_get(const struct dpll_pin *pin, void *pin_priv, ret = 0; unlock: ice_dpll_cb_unlock(pf); - if (ret) - dev_err(ice_pf_to_dev(pf), - "%s: dpll:%p, pin:%p, pf:%p state: %d ret:%d\n", - __func__, dpll, pin, pf, *state, ret); return ret; } @@ -834,15 +839,13 @@ ice_dpll_input_prio_get(const struct dpll_pin *pin, void *pin_priv, struct ice_dpll_pin *p = pin_priv; struct ice_dpll *d = dpll_priv; struct ice_pf *pf = d->pf; - int ret = -EINVAL; + int ret; - ret = ice_dpll_cb_lock(pf); + ret = ice_dpll_cb_lock(pf, extack); if (ret) return ret; *prio = d->input_prio[p->idx]; ice_dpll_cb_unlock(pf); - dev_dbg(ice_pf_to_dev(pf), "%s: dpll:%p, pin:%p, pf:%p ret:%d\n", - __func__, dpll, pin, pf, ret); return 0; } @@ -871,7 +874,7 @@ ice_dpll_input_prio_set(const struct dpll_pin *pin, void *pin_priv, struct ice_dpll_pin *p = pin_priv; struct ice_dpll *d = dpll_priv; struct ice_pf *pf = d->pf; - int ret = -EINVAL; + int ret; if (prio > ICE_DPLL_PRIO_MAX) { NL_SET_ERR_MSG_FMT(extack, "prio out of supported range 0-%d", @@ -879,15 +882,11 @@ ice_dpll_input_prio_set(const struct dpll_pin *pin, void *pin_priv, return ret; } - ret = ice_dpll_cb_lock(pf); + ret = ice_dpll_cb_lock(pf, extack); if (ret) return ret; - ret = ice_dpll_hw_input_prio_set(pf, d, p, prio); - if (ret) - NL_SET_ERR_MSG_FMT(extack, "unable to set prio: %u", prio); + ret = ice_dpll_hw_input_prio_set(pf, d, p, prio, extack); ice_dpll_cb_unlock(pf); - dev_dbg(ice_pf_to_dev(pf), "%s: dpll:%p, pin:%p, pf:%p ret:%d\n", - __func__, dpll, pin, pf, ret); return ret; } @@ -944,10 +943,10 @@ ice_dpll_output_direction(const struct dpll_pin *pin, void *pin_priv, /** * ice_dpll_rclk_state_on_pin_set - set a state on rclk pin - * @dpll: registered dpll pointer * @pin: pointer to a pin * @pin_priv: private data pointer passed on pin registration * @parent_pin: pin parent pointer + * @parent_pin_priv: parent private data pointer passed on pin registration * @state: state to be set on pin * @extack: error reporting * @@ -965,13 +964,13 @@ ice_dpll_rclk_state_on_pin_set(const struct dpll_pin *pin, void *pin_priv, enum dpll_pin_state state, struct netlink_ext_ack *extack) { - bool enable = state == DPLL_PIN_STATE_CONNECTED ? true : false; struct ice_dpll_pin *p = pin_priv, *parent = parent_pin_priv; + bool enable = state == DPLL_PIN_STATE_CONNECTED; struct ice_pf *pf = p->pf; - int ret = -EINVAL; u32 hw_idx; + int ret; - ret = ice_dpll_cb_lock(pf); + ret = ice_dpll_cb_lock(pf, extack); if (ret) return ret; hw_idx = parent->idx - pf->dplls.base_rclk_idx; @@ -980,16 +979,22 @@ ice_dpll_rclk_state_on_pin_set(const struct dpll_pin *pin, void *pin_priv, if ((enable && p->state[hw_idx] == DPLL_PIN_STATE_CONNECTED) || (!enable && p->state[hw_idx] == DPLL_PIN_STATE_DISCONNECTED)) { + NL_SET_ERR_MSG_FMT(extack, + "pin:%u state:%u on parent:%u already set", + p->idx, state, parent->idx); ret = -EINVAL; goto unlock; } ret = ice_aq_set_phy_rec_clk_out(&pf->hw, hw_idx, enable, &p->freq); + if (ret) + NL_SET_ERR_MSG_FMT(extack, + "err:%d %s failed to set pin state:%u for pin:%u on parent:%u\n", + ret, + ice_aq_str(pf->hw.adminq.sq_last_status), + state, p->idx, parent->idx); unlock: ice_dpll_cb_unlock(pf); - dev_dbg(ice_pf_to_dev(pf), - "%s: parent:%p, pin:%p, pf:%p hw_idx:%u enable:%d ret:%d\n", - __func__, parent_pin, pin, pf, hw_idx, enable, ret); return ret; } @@ -999,6 +1004,7 @@ ice_dpll_rclk_state_on_pin_set(const struct dpll_pin *pin, void *pin_priv, * @pin: pointer to a pin * @pin_priv: private data pointer passed on pin registration * @parent_pin: pin parent pointer + * @parent_pin_priv: pin parent priv data pointer passed on pin registration * @state: on success holds pin state on parent pin * @extack: error reporting * @@ -1018,17 +1024,18 @@ ice_dpll_rclk_state_on_pin_get(const struct dpll_pin *pin, void *pin_priv, { struct ice_dpll_pin *p = pin_priv, *parent = parent_pin_priv; struct ice_pf *pf = p->pf; - int ret = -EFAULT; u32 hw_idx; + int ret; - ret = ice_dpll_cb_lock(pf); + ret = ice_dpll_cb_lock(pf, extack); if (ret) return ret; hw_idx = parent->idx - pf->dplls.base_rclk_idx; if (hw_idx >= pf->dplls.num_inputs) goto unlock; - ret = ice_dpll_pin_state_update(pf, p, ICE_DPLL_PIN_TYPE_RCLK_INPUT); + ret = ice_dpll_pin_state_update(pf, p, ICE_DPLL_PIN_TYPE_RCLK_INPUT, + extack); if (ret) goto unlock; @@ -1036,9 +1043,6 @@ ice_dpll_rclk_state_on_pin_get(const struct dpll_pin *pin, void *pin_priv, ret = 0; unlock: ice_dpll_cb_unlock(pf); - dev_dbg(ice_pf_to_dev(pf), - "%s: parent:%p, pin:%p, pf:%p hw_idx:%u state:%u ret:%d\n", - __func__, parent_pin, pin, pf, hw_idx, *state, ret); return ret; } @@ -1074,84 +1078,147 @@ static const struct dpll_device_ops ice_dpll_ops = { }; /** - * ice_dpll_deinit_info - release memory allocated for pins info + * ice_generate_clock_id - generates unique clock_id for registering dpll. * @pf: board private structure * - * Release memory allocated for pins by ice_dpll_init_info function. + * Generates unique (per board) clock_id for allocation and search of dpll + * devices in Linux dpll subsystem. * - * Context: Called under pf->dplls.lock + * Return: generated clock id for the board */ -static void ice_dpll_deinit_info(struct ice_pf *pf) +static u64 ice_generate_clock_id(struct ice_pf *pf) { - kfree(pf->dplls.inputs); - pf->dplls.inputs = NULL; - kfree(pf->dplls.outputs); - pf->dplls.outputs = NULL; - kfree(pf->dplls.eec.input_prio); - pf->dplls.eec.input_prio = NULL; - kfree(pf->dplls.pps.input_prio); - pf->dplls.pps.input_prio = NULL; + return pci_get_dsn(pf->pdev); } /** - * ice_dpll_deinit_rclk_pin - release rclk pin resources - * @pf: board private structure - * - * Deregister rclk pin from parent pins and release resources in dpll subsystem. + * ice_dpll_notify_changes - notify dpll subsystem about changes + * @d: pointer do dpll * - * Context: Called under pf->dplls.lock + * Once change detected appropriate event is submitted to the dpll subsystem. */ -static void ice_dpll_deinit_rclk_pin(struct ice_pf *pf) +static void ice_dpll_notify_changes(struct ice_dpll *d) { - struct ice_dpll_pin *rclk = &pf->dplls.rclk; - struct ice_vsi *vsi = ice_get_main_vsi(pf); - struct dpll_pin *parent; - int i; - - for (i = 0; i < rclk->num_parents; i++) { - parent = pf->dplls.inputs[rclk->parent_idx[i]].pin; - if (!parent) - continue; - if (!IS_ERR_OR_NULL(rclk->pin)) - dpll_pin_on_pin_unregister(parent, rclk->pin, - &ice_dpll_rclk_ops, rclk); + if (d->prev_dpll_state != d->dpll_state) { + d->prev_dpll_state = d->dpll_state; + dpll_device_change_ntf(d->dpll); + } + if (d->prev_input != d->active_input) { + if (d->prev_input) + dpll_pin_change_ntf(d->prev_input); + d->prev_input = d->active_input; + if (d->active_input) + dpll_pin_change_ntf(d->active_input); } - if (WARN_ON_ONCE(!vsi || !vsi->netdev)) - return; - netdev_dpll_pin_clear(vsi->netdev); - dpll_pin_put(rclk->pin); - rclk->pin = NULL; } /** - * ice_dpll_unregister_pins - unregister pins from a dpll - * @dpll: dpll device pointer - * @pins: pointer to pins array - * @ops: callback ops registered with the pins - * @count: number of pins + * ice_dpll_update_state - update dpll state + * @pf: pf private structure + * @d: pointer to queried dpll device + * @init: if function called on initialization of ice dpll * - * Unregister pins of a given array of pins from given dpll device registered in - * dpll subsystem. + * Poll current state of dpll from hw and update ice_dpll struct. * * Context: Called under pf->dplls.lock + * Return: + * * 0 - success + * * negative - AQ failure */ -static void -ice_dpll_unregister_pins(struct dpll_device *dpll, struct ice_dpll_pin *pins, - const struct dpll_pin_ops *ops, int count) +static int +ice_dpll_update_state(struct ice_pf *pf, struct ice_dpll *d, bool init) { struct ice_dpll_pin *p; - int i; + int ret; - for (i = 0; i < count; i++) { - p = &pins[i]; - if (p && !IS_ERR_OR_NULL(p->pin)) - dpll_pin_unregister(dpll, p->pin, ops, p); + ret = ice_get_cgu_state(&pf->hw, d->dpll_idx, d->prev_dpll_state, + &d->input_idx, &d->ref_state, &d->eec_mode, + &d->phase_offset, &d->dpll_state); + + dev_dbg(ice_pf_to_dev(pf), + "update dpll=%d, prev_src_idx:%u, src_idx:%u, state:%d, prev:%d\n", + d->dpll_idx, d->prev_input_idx, d->input_idx, + d->dpll_state, d->prev_dpll_state); + if (ret) { + dev_err(ice_pf_to_dev(pf), + "update dpll=%d state failed, ret=%d %s\n", + d->dpll_idx, ret, + ice_aq_str(pf->hw.adminq.sq_last_status)); + return ret; + } + if (init) { + if (d->dpll_state == ICE_CGU_STATE_LOCKED && + d->dpll_state == ICE_CGU_STATE_LOCKED_HO_ACQ) + d->active_input = pf->dplls.inputs[d->input_idx].pin; + p = &pf->dplls.inputs[d->input_idx]; + return ice_dpll_pin_state_update(pf, p, + ICE_DPLL_PIN_TYPE_INPUT, NULL); + } + if (d->dpll_state == ICE_CGU_STATE_HOLDOVER || + d->dpll_state == ICE_CGU_STATE_FREERUN) { + d->active_input = NULL; + p = &pf->dplls.inputs[d->input_idx]; + d->prev_input_idx = ICE_DPLL_PIN_IDX_INVALID; + d->input_idx = ICE_DPLL_PIN_IDX_INVALID; + ret = ice_dpll_pin_state_update(pf, p, + ICE_DPLL_PIN_TYPE_INPUT, NULL); + } else if (d->input_idx != d->prev_input_idx) { + p = &pf->dplls.inputs[d->prev_input_idx]; + ice_dpll_pin_state_update(pf, p, ICE_DPLL_PIN_TYPE_INPUT, NULL); + p = &pf->dplls.inputs[d->input_idx]; + d->active_input = p->pin; + ice_dpll_pin_state_update(pf, p, ICE_DPLL_PIN_TYPE_INPUT, NULL); + d->prev_input_idx = d->input_idx; + } + + return ret; +} + +/** + * ice_dpll_periodic_work - DPLLs periodic worker + * @work: pointer to kthread_work structure + * + * DPLLs periodic worker is responsible for polling state of dpll. + * Context: Holds pf->dplls.lock + */ +static void ice_dpll_periodic_work(struct kthread_work *work) +{ + struct ice_dplls *d = container_of(work, struct ice_dplls, work.work); + struct ice_pf *pf = container_of(d, struct ice_pf, dplls); + struct ice_dpll *de = &pf->dplls.eec; + struct ice_dpll *dp = &pf->dplls.pps; + int ret; + + ret = ice_dpll_cb_lock(pf, NULL); + if (ret == -EBUSY) + goto resched; + else if (ret) + return; + ret = ice_dpll_update_state(pf, de, false); + if (!ret) + ret = ice_dpll_update_state(pf, dp, false); + if (ret) { + d->cgu_state_acq_err_num++; + /* stop rescheduling this worker */ + if (d->cgu_state_acq_err_num > + ICE_CGU_STATE_ACQ_ERR_THRESHOLD) { + dev_err(ice_pf_to_dev(pf), + "EEC/PPS DPLLs periodic work disabled\n"); + return; + } } + ice_dpll_cb_unlock(pf); + ice_dpll_notify_changes(de); + ice_dpll_notify_changes(dp); +resched: + /* Run twice a second or reschedule if update failed */ + kthread_queue_delayed_work(d->kworker, &d->work, + ret ? msecs_to_jiffies(10) : + msecs_to_jiffies(500)); } /** * ice_dpll_release_pins - release pins resources from dpll subsystem - * @pf: board private structure * @pins: pointer to pins array * @count: number of pins * @@ -1161,16 +1228,10 @@ ice_dpll_unregister_pins(struct dpll_device *dpll, struct ice_dpll_pin *pins, */ static void ice_dpll_release_pins(struct ice_dpll_pin *pins, int count) { - struct ice_dpll_pin *p; int i; - for (i = 0; i < count; i++) { - p = &pins[i]; - if (p && !IS_ERR_OR_NULL(p->pin)) { - dpll_pin_put(p->pin); - p->pin = NULL; - } - } + for (i = 0; i < count; i++) + dpll_pin_put(pins[i].pin); } /** @@ -1207,17 +1268,39 @@ ice_dpll_get_pins(struct ice_pf *pf, struct ice_dpll_pin *pins, return 0; release_pins: - ice_dpll_release_pins(pins, i); + while (--i >= 0) + dpll_pin_put(pins[i].pin); return ret; } +/** + * ice_dpll_unregister_pins - unregister pins from a dpll + * @dpll: dpll device pointer + * @pins: pointer to pins array + * @ops: callback ops registered with the pins + * @count: number of pins + * + * Unregister pins of a given array of pins from given dpll device registered in + * dpll subsystem. + * + * Context: Called under pf->dplls.lock + */ +static void +ice_dpll_unregister_pins(struct dpll_device *dpll, struct ice_dpll_pin *pins, + const struct dpll_pin_ops *ops, int count) +{ + int i; + + for (i = 0; i < count; i++) + dpll_pin_unregister(dpll, pins[i].pin, ops, &pins[i]); +} + /** * ice_dpll_register_pins - register pins with a dpll * @dpll: dpll pointer to register pins with * @pins: pointer to pins array * @ops: callback ops registered with the pins * @count: number of pins - * @cgu: if cgu is present and controlled by this NIC * * Register pins of a given array with given dpll in dpll subsystem. * @@ -1241,23 +1324,50 @@ ice_dpll_register_pins(struct dpll_device *dpll, struct ice_dpll_pin *pins, return 0; unregister_pins: - ice_dpll_unregister_pins(dpll, pins, ops, i); + while (--i >= 0) + dpll_pin_unregister(dpll, pins[i].pin, ops, &pins[i]); return ret; } /** - * ice_dpll_init_direct_pins - initialize direct pins - * @dpll: dpll pointer to register pins with + * ice_dpll_deinit_direct_pins - deinitialize direct pins * @cgu: if cgu is present and controlled by this NIC * @pins: pointer to pins array - * @start_idx: on which index shall allocation start in dpll subsystem * @count: number of pins * @ops: callback ops registered with the pins * @first: dpll device pointer * @second: dpll device pointer * - * Allocate directly connected pins of a given array in dpll subsystem. - * If cgu is owned register allocated pins with given dplls. + * Context: Called under pf->dplls.lock + * If cgu is owned unregister pins from given dplls. + * Release pins resources to the dpll subsystem. + */ +static void +ice_dpll_deinit_direct_pins(bool cgu, struct ice_dpll_pin *pins, int count, + const struct dpll_pin_ops *ops, + struct dpll_device *first, + struct dpll_device *second) +{ + if (cgu) { + ice_dpll_unregister_pins(first, pins, ops, count); + ice_dpll_unregister_pins(second, pins, ops, count); + } + ice_dpll_release_pins(pins, count); +} + +/** + * ice_dpll_init_direct_pins - initialize direct pins + * @pf: board private structure + * @cgu: if cgu is present and controlled by this NIC + * @pins: pointer to pins array + * @start_idx: on which index shall allocation start in dpll subsystem + * @count: number of pins + * @ops: callback ops registered with the pins + * @first: dpll device pointer + * @second: dpll device pointer + * + * Allocate directly connected pins of a given array in dpll subsystem. + * If cgu is owned register allocated pins with given dplls. * * Context: Called under pf->dplls.lock * Return: @@ -1294,38 +1404,38 @@ ice_dpll_init_direct_pins(struct ice_pf *pf, bool cgu, } /** - * ice_dpll_deinit_direct_pins - deinitialize direct pins - * @cgu: if cgu is present and controlled by this NIC - * @pins: pointer to pins array - * @count: number of pins - * @ops: callback ops registered with the pins - * @first: dpll device pointer - * @second: dpll device pointer + * ice_dpll_deinit_rclk_pin - release rclk pin resources + * @pf: board private structure + * + * Deregister rclk pin from parent pins and release resources in dpll subsystem. * * Context: Called under pf->dplls.lock - * If cgu is owned unregister pins from given dplls. - * Release pins resources to the dpll subsystem. */ -static void -ice_dpll_deinit_direct_pins(bool cgu, struct ice_dpll_pin *pins, int count, - const struct dpll_pin_ops *ops, - struct dpll_device *first, - struct dpll_device *second) +static void ice_dpll_deinit_rclk_pin(struct ice_pf *pf) { - if (cgu) { - ice_dpll_unregister_pins(first, pins, ops, count); - ice_dpll_unregister_pins(second, pins, ops, count); + struct ice_dpll_pin *rclk = &pf->dplls.rclk; + struct ice_vsi *vsi = ice_get_main_vsi(pf); + struct dpll_pin *parent; + int i; + + for (i = 0; i < rclk->num_parents; i++) { + parent = pf->dplls.inputs[rclk->parent_idx[i]].pin; + if (!parent) + continue; + dpll_pin_on_pin_unregister(parent, rclk->pin, + &ice_dpll_rclk_ops, rclk); } - ice_dpll_release_pins(pins, count); + if (WARN_ON_ONCE(!vsi || !vsi->netdev)) + return; + netdev_dpll_pin_clear(vsi->netdev); + dpll_pin_put(rclk->pin); } /** * ice_dpll_init_rclk_pins - initialize recovered clock pin - * @dpll: dpll pointer to register pins with - * @cgu: if cgu is present and controlled by this NIC - * @pins: pointer to pins array + * @pf: board private structure + * @pin: pin to register * @start_idx: on which index shall allocation start in dpll subsystem - * @count: number of pins * @ops: callback ops registered with the pins * * Allocate resource for recovered clock pin in dpll subsystem. Register the @@ -1376,6 +1486,43 @@ ice_dpll_init_rclk_pins(struct ice_pf *pf, struct ice_dpll_pin *pin, return ret; } +/** + * ice_dpll_deinit_pins - deinitialize direct pins + * @pf: board private structure + * @cgu: if cgu is controlled by this pf + * + * If cgu is owned unregister directly connected pins from the dplls. + * Release resources of directly connected pins from the dpll subsystem. + * + * Context: Called under pf->dplls.lock + */ +static void ice_dpll_deinit_pins(struct ice_pf *pf, bool cgu) +{ + struct ice_dpll_pin *outputs = pf->dplls.outputs; + struct ice_dpll_pin *inputs = pf->dplls.inputs; + int num_outputs = pf->dplls.num_outputs; + int num_inputs = pf->dplls.num_inputs; + struct ice_dplls *d = &pf->dplls; + struct ice_dpll *de = &d->eec; + struct ice_dpll *dp = &d->pps; + + ice_dpll_deinit_rclk_pin(pf); + if (cgu) { + ice_dpll_unregister_pins(dp->dpll, inputs, &ice_dpll_input_ops, + num_inputs); + ice_dpll_unregister_pins(de->dpll, inputs, &ice_dpll_input_ops, + num_inputs); + } + ice_dpll_release_pins(inputs, num_inputs); + if (cgu) { + ice_dpll_unregister_pins(dp->dpll, outputs, + &ice_dpll_output_ops, num_outputs); + ice_dpll_unregister_pins(de->dpll, outputs, + &ice_dpll_output_ops, num_outputs); + ice_dpll_release_pins(outputs, num_outputs); + } +} + /** * ice_dpll_init_pins - init pins and register pins with a dplls * @pf: board private structure @@ -1430,17 +1577,22 @@ static int ice_dpll_init_pins(struct ice_pf *pf, bool cgu) } /** - * ice_generate_clock_id - generates unique clock_id for registering dpll. + * ice_dpll_deinit_dpll - deinitialize dpll device * @pf: board private structure + * @d: pointer to ice_dpll + * @cgu: if cgu is present and controlled by this NIC * - * Generates unique (per board) clock_id for allocation and search of dpll - * devices in Linux dpll subsystem. + * If cgu is owned unregister the dpll from dpll subsystem. + * Release resources of dpll device from dpll subsystem. * - * Return: generated clock id for the board + * Context: Called under pf->dplls.lock */ -static u64 ice_generate_clock_id(struct ice_pf *pf) +static void +ice_dpll_deinit_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu) { - return pci_get_dsn(pf->pdev); + if (cgu) + dpll_device_unregister(d->dpll, &ice_dpll_ops, d); + dpll_device_put(d->dpll); } /** @@ -1485,130 +1637,19 @@ ice_dpll_init_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu, } /** - * ice_dpll_update_state - update dpll state - * @pf: pf private structure - * @d: pointer to queried dpll device + * ice_dpll_deinit_worker - deinitialize dpll kworker + * @pf: board private structure * - * Poll current state of dpll from hw and update ice_dpll struct. + * Stop dpll's kworker, release it's resources. * * Context: Called under pf->dplls.lock - * Return: - * * 0 - success - * * negative - AQ failure - */ -static int -ice_dpll_update_state(struct ice_pf *pf, struct ice_dpll *d, bool init) -{ - struct ice_dpll_pin *p; - int ret; - - ret = ice_get_cgu_state(&pf->hw, d->dpll_idx, d->prev_dpll_state, - &d->input_idx, &d->ref_state, &d->eec_mode, - &d->phase_offset, &d->dpll_state); - - dev_dbg(ice_pf_to_dev(pf), - "update dpll=%d, prev_src_idx:%u, src_idx:%u, state:%d, prev:%d\n", - d->dpll_idx, d->prev_input_idx, d->input_idx, - d->dpll_state, d->prev_dpll_state); - if (ret) { - dev_err(ice_pf_to_dev(pf), - "update dpll=%d state failed, ret=%d %s\n", - d->dpll_idx, ret, - ice_aq_str(pf->hw.adminq.sq_last_status)); - return ret; - } - if (init) { - if (d->dpll_state == ICE_CGU_STATE_LOCKED && - d->dpll_state == ICE_CGU_STATE_LOCKED_HO_ACQ) - d->active_input = pf->dplls.inputs[d->input_idx].pin; - p = &pf->dplls.inputs[d->input_idx]; - return ice_dpll_pin_state_update(pf, p, - ICE_DPLL_PIN_TYPE_INPUT); - } - if (d->dpll_state == ICE_CGU_STATE_HOLDOVER || - d->dpll_state == ICE_CGU_STATE_FREERUN) { - d->active_input = NULL; - p = &pf->dplls.inputs[d->input_idx]; - d->prev_input_idx = ICE_DPLL_PIN_IDX_INVALID; - d->input_idx = ICE_DPLL_PIN_IDX_INVALID; - ret = ice_dpll_pin_state_update(pf, p, - ICE_DPLL_PIN_TYPE_INPUT); - } else if (d->input_idx != d->prev_input_idx) { - p = &pf->dplls.inputs[d->prev_input_idx]; - ice_dpll_pin_state_update(pf, p, ICE_DPLL_PIN_TYPE_INPUT); - p = &pf->dplls.inputs[d->input_idx]; - d->active_input = p->pin; - ice_dpll_pin_state_update(pf, p, ICE_DPLL_PIN_TYPE_INPUT); - d->prev_input_idx = d->input_idx; - } - - return ret; -} - -/** - * ice_dpll_notify_changes - notify dpll subsystem about changes - * @d: pointer do dpll - * - * Once change detected appropriate event is submitted to the dpll subsystem. - */ -static void ice_dpll_notify_changes(struct ice_dpll *d) -{ - if (d->prev_dpll_state != d->dpll_state) { - d->prev_dpll_state = d->dpll_state; - dpll_device_change_ntf(d->dpll); - } - if (d->prev_input != d->active_input) { - if (d->prev_input) - dpll_pin_change_ntf(d->prev_input); - d->prev_input = d->active_input; - if (d->active_input) - dpll_pin_change_ntf(d->active_input); - } -} - -/** - * ice_dpll_periodic_work - DPLLs periodic worker - * @work: pointer to kthread_work structure - * - * DPLLs periodic worker is responsible for polling state of dpll. - * Context: Holds pf->dplls.lock */ -static void ice_dpll_periodic_work(struct kthread_work *work) +static void ice_dpll_deinit_worker(struct ice_pf *pf) { - struct ice_dplls *d = container_of(work, struct ice_dplls, work.work); - struct ice_pf *pf = container_of(d, struct ice_pf, dplls); - struct ice_dpll *de = &pf->dplls.eec; - struct ice_dpll *dp = &pf->dplls.pps; - int ret = 0; + struct ice_dplls *d = &pf->dplls; - if (!test_bit(ICE_FLAG_DPLL, pf->flags)) - return; - ret = ice_dpll_cb_lock(pf); - if (ret) { - d->lock_err_num++; - goto resched; - } - ret = ice_dpll_update_state(pf, de, false); - if (!ret) - ret = ice_dpll_update_state(pf, dp, false); - if (ret) { - d->cgu_state_acq_err_num++; - /* stop rescheduling this worker */ - if (d->cgu_state_acq_err_num > - ICE_CGU_STATE_ACQ_ERR_THRESHOLD) { - dev_err(ice_pf_to_dev(pf), - "EEC/PPS DPLLs periodic work disabled\n"); - return; - } - } - ice_dpll_cb_unlock(pf); - ice_dpll_notify_changes(de); - ice_dpll_notify_changes(dp); -resched: - /* Run twice a second or reschedule if update failed */ - kthread_queue_delayed_work(d->kworker, &d->work, - ret ? msecs_to_jiffies(10) : - msecs_to_jiffies(500)); + kthread_cancel_delayed_work_sync(&d->work); + kthread_destroy_worker(d->kworker); } /** @@ -1641,111 +1682,6 @@ static int ice_dpll_init_worker(struct ice_pf *pf) return 0; } -/** - * ice_dpll_deinit_pins - deinitialize direct pins - * @pf: board private structure - * @cgu: if cgu is controlled by this pf - * - * If cgu is owned unregister directly connected pins from the dplls. - * Release resources of directly connected pins from the dpll subsystem. - * - * Context: Called under pf->dplls.lock - */ -static void ice_dpll_deinit_pins(struct ice_pf *pf, bool cgu) -{ - struct ice_dpll_pin *outputs = pf->dplls.outputs; - struct ice_dpll_pin *inputs = pf->dplls.inputs; - int num_outputs = pf->dplls.num_outputs; - int num_inputs = pf->dplls.num_inputs; - struct ice_dplls *d = &pf->dplls; - struct ice_dpll *de = &d->eec; - struct ice_dpll *dp = &d->pps; - - ice_dpll_deinit_rclk_pin(pf); - if (cgu) { - ice_dpll_unregister_pins(dp->dpll, inputs, &ice_dpll_input_ops, - num_inputs); - ice_dpll_unregister_pins(de->dpll, inputs, &ice_dpll_input_ops, - num_inputs); - } - ice_dpll_release_pins(inputs, num_inputs); - if (cgu) { - ice_dpll_unregister_pins(dp->dpll, outputs, - &ice_dpll_output_ops, num_outputs); - ice_dpll_unregister_pins(de->dpll, outputs, - &ice_dpll_output_ops, num_outputs); - ice_dpll_release_pins(outputs, num_outputs); - } -} - -/** - * ice_dpll_deinit_dpll - deinitialize dpll device - * @pf: board private structure - * - * If cgu is owned unregister the dpll from dpll subsystem. - * Release resources of dpll device from dpll subsystem. - * - * Context: Called under pf->dplls.lock - */ -static void -ice_dpll_deinit_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu) -{ - if (!IS_ERR(d->dpll)) { - if (cgu) - dpll_device_unregister(d->dpll, &ice_dpll_ops, d); - dpll_device_put(d->dpll); - dev_dbg(ice_pf_to_dev(pf), "(%p) dpll removed\n", d); - } -} - -/** - * ice_dpll_deinit_worker - deinitialize dpll kworker - * @pf: board private structure - * - * Stop dpll's kworker, release it's resources. - * - * Context: Called under pf->dplls.lock - */ -static void ice_dpll_deinit_worker(struct ice_pf *pf) -{ - struct ice_dplls *d = &pf->dplls; - - kthread_cancel_delayed_work_sync(&d->work); - if (!IS_ERR_OR_NULL(d->kworker)) { - kthread_destroy_worker(d->kworker); - d->kworker = NULL; - dev_dbg(ice_pf_to_dev(pf), "DPLLs worker removed\n"); - } -} - -/** - * ice_dpll_deinit - Disable the driver/HW support for dpll subsystem - * the dpll device. - * @pf: board private structure - * - * Handles the cleanup work required after dpll initialization,freeing resources - * and unregistering the dpll, pin and all resources used for handling them. - * - * Context: Function holds pf->dplls.lock mutex. - */ -void ice_dpll_deinit(struct ice_pf *pf) -{ - bool cgu = ice_is_feature_supported(pf, ICE_F_CGU); - - if (test_bit(ICE_FLAG_DPLL, pf->flags)) { - mutex_lock(&pf->dplls.lock); - ice_dpll_deinit_pins(pf, cgu); - ice_dpll_deinit_info(pf); - ice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu); - ice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu); - if (cgu) - ice_dpll_deinit_worker(pf); - clear_bit(ICE_FLAG_DPLL, pf->flags); - mutex_unlock(&pf->dplls.lock); - mutex_destroy(&pf->dplls.lock); - } -} - /** * ice_dpll_init_info_direct_pins - initializes direct pins info * @pf: board private structure @@ -1754,7 +1690,7 @@ void ice_dpll_deinit(struct ice_pf *pf) * Init information for directly connected pins, cache them in pf's pins * structures. * - * Context: Function initializes and holds pf->dplls.lock mutex. + * Context: Called under pf->dplls.lock. * Return: * * 0 - success * * negative - init failure reason @@ -1764,9 +1700,9 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf, enum ice_dpll_pin_type pin_type) { struct ice_dpll *de = &pf->dplls.eec, *dp = &pf->dplls.pps; - int num_pins, i, ret = -EINVAL; struct ice_hw *hw = &pf->hw; struct ice_dpll_pin *pins; + int num_pins, i, ret; u8 freq_supp_num; bool input; @@ -1782,7 +1718,7 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf, input = false; break; default: - return ret; + return -EINVAL; } for (i = 0; i < num_pins; i++) { @@ -1802,7 +1738,7 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf, DPLL_PIN_CAPS_PRIORITY_CAN_CHANGE; } pins[i].prop.capabilities |= DPLL_PIN_CAPS_STATE_CAN_CHANGE; - ret = ice_dpll_pin_state_update(pf, &pins[i], pin_type); + ret = ice_dpll_pin_state_update(pf, &pins[i], pin_type, NULL); if (ret) return ret; pins[i].prop.freq_supported = @@ -1815,9 +1751,8 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf, } /** - * ice_dpll_init_rclk_pin - initializes rclk pin information + * ice_dpll_init_info_rclk_pin - initializes rclk pin information * @pf: board private structure - * @pin_type: type of pins being initialized * * Init information for rclk pin, cache them in pf->dplls.rclk. * @@ -1825,18 +1760,18 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf, * * 0 - success * * negative - init failure reason */ -static int ice_dpll_init_rclk_pin(struct ice_pf *pf) +static int ice_dpll_init_info_rclk_pin(struct ice_pf *pf) { struct ice_dpll_pin *pin = &pf->dplls.rclk; struct device *dev = ice_pf_to_dev(pf); - pin->prop.board_label = dev_name(dev); + pin->prop.package_label = dev_name(dev); pin->prop.type = DPLL_PIN_TYPE_SYNCE_ETH_PORT; pin->prop.capabilities |= DPLL_PIN_CAPS_STATE_CAN_CHANGE; pin->pf = pf; return ice_dpll_pin_state_update(pf, pin, - ICE_DPLL_PIN_TYPE_RCLK_INPUT); + ICE_DPLL_PIN_TYPE_RCLK_INPUT, NULL); } /** @@ -1858,12 +1793,28 @@ ice_dpll_init_pins_info(struct ice_pf *pf, enum ice_dpll_pin_type pin_type) case ICE_DPLL_PIN_TYPE_OUTPUT: return ice_dpll_init_info_direct_pins(pf, pin_type); case ICE_DPLL_PIN_TYPE_RCLK_INPUT: - return ice_dpll_init_rclk_pin(pf); + return ice_dpll_init_info_rclk_pin(pf); default: return -EINVAL; } } +/** + * ice_dpll_deinit_info - release memory allocated for pins info + * @pf: board private structure + * + * Release memory allocated for pins by ice_dpll_init_info function. + * + * Context: Called under pf->dplls.lock + */ +static void ice_dpll_deinit_info(struct ice_pf *pf) +{ + kfree(pf->dplls.inputs); + kfree(pf->dplls.outputs); + kfree(pf->dplls.eec.input_prio); + kfree(pf->dplls.pps.input_prio); +} + /** * ice_dpll_init_info - prepare pf's dpll information structure * @pf: board private structure @@ -1871,6 +1822,7 @@ ice_dpll_init_pins_info(struct ice_pf *pf, enum ice_dpll_pin_type pin_type) * * Acquire (from HW) and set basic dpll information (on pf->dplls struct). * + * Context: Called under pf->dplls.lock * Return: * * 0 - success * * negative - init failure reason @@ -1952,6 +1904,35 @@ static int ice_dpll_init_info(struct ice_pf *pf, bool cgu) return ret; } +/** + * ice_dpll_deinit - Disable the driver/HW support for dpll subsystem + * the dpll device. + * @pf: board private structure + * + * Handles the cleanup work required after dpll initialization,freeing resources + * and unregistering the dpll, pin and all resources used for handling them. + * + * Context: Function holds pf->dplls.lock mutex. + */ +void ice_dpll_deinit(struct ice_pf *pf) +{ + bool cgu = ice_is_feature_supported(pf, ICE_F_CGU); + + if (!test_bit(ICE_FLAG_DPLL, pf->flags)) + return; + + mutex_lock(&pf->dplls.lock); + ice_dpll_deinit_pins(pf, cgu); + ice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu); + ice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu); + ice_dpll_deinit_info(pf); + if (cgu) + ice_dpll_deinit_worker(pf); + clear_bit(ICE_FLAG_DPLL, pf->flags); + mutex_unlock(&pf->dplls.lock); + mutex_destroy(&pf->dplls.lock); +} + /** * ice_dpll_init - initialize support for dpll subsystem * @pf: board private structure @@ -1960,56 +1941,51 @@ static int ice_dpll_init_info(struct ice_pf *pf, bool cgu) * subsystem. Allow userpsace to obtain state of DPLL and handling of DPLL * configuration requests. * - * Return: - * * 0 - success - * * negative - init failure reason + * Context: Function initializes and holds pf->dplls.lock mutex. */ -int ice_dpll_init(struct ice_pf *pf) +void ice_dpll_init(struct ice_pf *pf) { - bool cgu_present = ice_is_feature_supported(pf, ICE_F_CGU); + bool cgu = ice_is_feature_supported(pf, ICE_F_CGU); struct ice_dplls *d = &pf->dplls; int err = 0; mutex_init(&d->lock); mutex_lock(&d->lock); - err = ice_dpll_init_info(pf, cgu_present); + err = ice_dpll_init_info(pf, cgu); if (err) goto err_exit; - err = ice_dpll_init_dpll(pf, &pf->dplls.eec, cgu_present, - DPLL_TYPE_EEC); + err = ice_dpll_init_dpll(pf, &pf->dplls.eec, cgu, DPLL_TYPE_EEC); if (err) goto deinit_info; - err = ice_dpll_init_dpll(pf, &pf->dplls.pps, cgu_present, - DPLL_TYPE_PPS); + err = ice_dpll_init_dpll(pf, &pf->dplls.pps, cgu, DPLL_TYPE_PPS); if (err) goto deinit_eec; - err = ice_dpll_init_pins(pf, cgu_present); + err = ice_dpll_init_pins(pf, cgu); if (err) goto deinit_pps; set_bit(ICE_FLAG_DPLL, pf->flags); - if (cgu_present) { + if (cgu) { err = ice_dpll_init_worker(pf); if (err) goto deinit_pins; } mutex_unlock(&d->lock); - dev_info(ice_pf_to_dev(pf), "DPLLs init successful\n"); - return err; + return; deinit_pins: - ice_dpll_deinit_pins(pf, cgu_present); + ice_dpll_deinit_pins(pf, cgu); deinit_pps: - ice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu_present); + ice_dpll_deinit_dpll(pf, &pf->dplls.pps, cgu); deinit_eec: - ice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu_present); + ice_dpll_deinit_dpll(pf, &pf->dplls.eec, cgu); deinit_info: ice_dpll_deinit_info(pf); err_exit: clear_bit(ICE_FLAG_DPLL, pf->flags); mutex_unlock(&d->lock); mutex_destroy(&d->lock); - dev_warn(ice_pf_to_dev(pf), "DPLLs init failure err:\n"); + dev_warn(ice_pf_to_dev(pf), "DPLLs init failure err:%d\n", err); - return err; + return; } diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.h b/drivers/net/ethernet/intel/ice/ice_dpll.h index 287892825deb..e331eaef61b5 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.h +++ b/drivers/net/ethernet/intel/ice/ice_dpll.h @@ -90,12 +90,11 @@ struct ice_dplls { u32 num_inputs; u32 num_outputs; int cgu_state_acq_err_num; - int lock_err_num; u8 base_rclk_idx; u64 clock_id; }; -int ice_dpll_init(struct ice_pf *pf); +void ice_dpll_init(struct ice_pf *pf); void ice_dpll_deinit(struct ice_pf *pf); diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c index 39b692945f73..3f5d0d827637 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c @@ -3281,7 +3281,6 @@ int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx) ctx = ICE_AQC_LINK_TOPO_NODE_TYPE_PHY << ICE_AQC_LINK_TOPO_NODE_TYPE_S; ctx |= ICE_AQC_LINK_TOPO_NODE_CTX_PORT << ICE_AQC_LINK_TOPO_NODE_CTX_S; cmd.addr.topo_params.node_type_ctx = ctx; - cmd.addr.topo_params.index = 0; status = ice_aq_get_netlist_node(hw, &cmd, &node_part_number, &node_handle); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f17a1fab8358..99bfc427ffee 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3971,6 +3971,16 @@ int dev_get_port_parent_id(struct net_device *dev, bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b); void netdev_dpll_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin); void netdev_dpll_pin_clear(struct net_device *dev); + +static inline struct dpll_pin *netdev_dpll_pin(const struct net_device *dev) +{ +#if IS_ENABLED(CONFIG_DPLL) + return dev->dpll_pin; +#else + return NULL; +#endif +} + struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev, bool *again); struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq, int *ret); diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h index d99d7dc20670..fd09965aed00 100644 --- a/include/uapi/linux/dpll.h +++ b/include/uapi/linux/dpll.h @@ -10,19 +10,15 @@ #define DPLL_FAMILY_VERSION 1 /** - * enum dpll_mode - working-modes a dpll can support, differentiate if and how + * enum dpll_mode - working modes a dpll can support, differentiates if and how * dpll selects one of its inputs to syntonize with it, valid values for * DPLL_A_MODE attribute * @DPLL_MODE_MANUAL: input can be only selected by sending a request to dpll - * @DPLL_MODE_AUTOMATIC: highest prio, valid input, auto selected by dpll - * @DPLL_MODE_HOLDOVER: dpll forced into holdover mode - * @DPLL_MODE_FREERUN: dpll driven on system clk + * @DPLL_MODE_AUTOMATIC: highest prio input pin auto selected by dpll */ enum dpll_mode { DPLL_MODE_MANUAL = 1, DPLL_MODE_AUTOMATIC, - DPLL_MODE_HOLDOVER, - DPLL_MODE_FREERUN, __DPLL_MODE_MAX, DPLL_MODE_MAX = (__DPLL_MODE_MAX - 1) @@ -31,16 +27,15 @@ enum dpll_mode { /** * enum dpll_lock_status - provides information of dpll device lock status, * valid values for DPLL_A_LOCK_STATUS attribute - * @DPLL_LOCK_STATUS_UNLOCKED: dpll was not yet locked to any valid input (or - * is in mode: DPLL_MODE_FREERUN) + * @DPLL_LOCK_STATUS_UNLOCKED: dpll was not yet locked to any valid input * @DPLL_LOCK_STATUS_LOCKED: dpll is locked to a valid signal, but no holdover * available * @DPLL_LOCK_STATUS_LOCKED_HO_ACQ: dpll is locked and holdover acquired * @DPLL_LOCK_STATUS_HOLDOVER: dpll is in holdover state - lost a valid lock or - * was forced by selecting DPLL_MODE_HOLDOVER mode (latter possible only when - * dpll lock-state was already DPLL_LOCK_STATUS_LOCKED, if dpll lock-state - * was not DPLL_LOCK_STATUS_LOCKED, the dpll's lock-state shall remain - * DPLL_LOCK_STATUS_UNLOCKED even if DPLL_MODE_HOLDOVER was requested) + * was forced by disconnecting all the pins (latter possible only when dpll + * lock-state was already DPLL_LOCK_STATUS_LOCKED_HO_ACQ, if dpll lock-state + * was not DPLL_LOCK_STATUS_LOCKED_HO_ACQ, the dpll's lock-state shall remain + * DPLL_LOCK_STATUS_UNLOCKED) */ enum dpll_lock_status { DPLL_LOCK_STATUS_UNLOCKED = 1, @@ -126,6 +121,9 @@ enum dpll_pin_state { /** * enum dpll_pin_caps - defines possible capabilities of a pin, valid flags on * DPLL_A_PIN_CAPS attribute + * @DPLL_PIN_CAPS_DIRECTION_CAN_CHANGE: pin direction can be changed + * @DPLL_PIN_CAPS_PRIORITY_CAN_CHANGE: pin prority can be changed + * @DPLL_PIN_CAPS_STATE_CAN_CHANGE: pin state can be changed */ enum dpll_pin_caps { DPLL_PIN_CAPS_DIRECTION_CAN_CHANGE = 1, @@ -155,7 +153,8 @@ enum dpll_a { DPLL_A_PIN_PRIO, DPLL_A_PIN_STATE, DPLL_A_PIN_DPLL_CAPS, - DPLL_A_PIN_PARENT, + DPLL_A_PIN_PARENT_DEVICE, + DPLL_A_PIN_PARENT_PIN, __DPLL_A_MAX, DPLL_A_MAX = (__DPLL_A_MAX - 1) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index c03599e74110..48ce14306f28 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1059,8 +1059,7 @@ static size_t rtnl_dpll_pin_size(const struct net_device *dev) { size_t size = nla_total_size(0); /* nest IFLA_DPLL_PIN */ - if (dev->dpll_pin) - size += dpll_msg_pin_handle_size(dev->dpll_pin); + size += dpll_msg_pin_handle_size(netdev_dpll_pin(dev)); return size; } @@ -1796,11 +1795,9 @@ static int rtnl_fill_dpll_pin(struct sk_buff *skb, if (!dpll_pin_nest) return -EMSGSIZE; - if (dev->dpll_pin) { - ret = dpll_msg_add_pin_handle(skb, dev->dpll_pin); - if (ret < 0) - goto nest_cancel; - } + ret = dpll_msg_add_pin_handle(skb, netdev_dpll_pin(dev)); + if (ret < 0) + goto nest_cancel; nla_nest_end(skb, dpll_pin_nest); return 0;