From patchwork Sun Mar 26 17:00:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 13188364 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CF68FC77B61 for ; Sun, 26 Mar 2023 17:01:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232418AbjCZRA7 (ORCPT ); Sun, 26 Mar 2023 13:00:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47824 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232410AbjCZRA6 (ORCPT ); Sun, 26 Mar 2023 13:00:58 -0400 Received: from mail-ed1-x536.google.com (mail-ed1-x536.google.com [IPv6:2a00:1450:4864:20::536]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1BB5459F1 for ; Sun, 26 Mar 2023 10:00:57 -0700 (PDT) Received: by mail-ed1-x536.google.com with SMTP id ek18so26611244edb.6 for ; Sun, 26 Mar 2023 10:00:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=resnulli-us.20210112.gappssmtp.com; s=20210112; t=1679850055; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GgdFnEC+G0UCGygoBkz7mAsO99oCv1F1QOJil/I+FSQ=; b=rSbRs0Ejz+MMl27sWojxGrzlH3aPN7wM/mRGklbiFbsSfzLE6SzDusJOrZmIGz89Sr eeVuXyjpeBnxO+O02Gwo/n6s8JMKjsR8vES1BqblAYE+XfmYSzIDvZ0MSK1jBWA8zHjU Lxsj9A8lpwGxaWjyg03HkOVceVnsFkzqERo1dxzw3LA49ehDc0jN2Vbw3Se+xao/NKpD TK354xn2UcUNSpsbFFJir3kjG2N0OzKLQqOrvNvQrz9lW9WPZtNOTMgA9vzBnVdOz8Y3 lj9VUlRgNTOZdkshZ4ylCM1wy5XQEq2eefSjI2MkuHuIlT71o9Rx99zwAR0kZs/CdCZO oAvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679850055; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GgdFnEC+G0UCGygoBkz7mAsO99oCv1F1QOJil/I+FSQ=; b=YKD8P87Meft3kQoxMoaFWhE5emFAHWJf8Y2BT/I9z27Ii5Am/uDRgBoLX8CMoZlfQB iU2MFEhEw9ezQHwvzS3+FDEqUSjpZDNkx+i6MIVQwpYH+chhTQWlDaikKFCM4r1lSjTd ulpmudOi6HX8xaBQgmdpelystWJhS7QCcOUiq9QD9i7NcOPDS9t6zdRn0blcQXMw0C+k 8mnxOBpUxby4fjZ/mzFmD8OmS1+TMuIdwZ20U16vuPGfCtuL3EyNrRVS+xt6WrkgMOLr q5iZP2zmLerQ6RXo+ai57aLFJLMd7OyeBHavD+XxOk9iEyQTaqPHfzQcWHhD2R0D5ZQK 6irg== X-Gm-Message-State: AAQBX9cElzCubnzVCvC16H2iAV/k0vPpEp7czb2ZrGiuGM3g8hW5M06i 8FspMrRpzH5ltzqzcRZINxzdxh0ULG1Yvpm3iZ0= X-Google-Smtp-Source: AKy350YyNS3KsH2kUfOS1O4CATRcNe1sskoWPr1JyRQV1IsigQ2KYF8G1P2M2bXOhaWZiVn1xP/x+g== X-Received: by 2002:a17:907:3188:b0:8b1:781d:f9a4 with SMTP id xe8-20020a170907318800b008b1781df9a4mr10631709ejb.21.1679850055485; Sun, 26 Mar 2023 10:00:55 -0700 (PDT) Received: from localhost (host-213-179-129-39.customer.m-online.net. [213.179.129.39]) by smtp.gmail.com with ESMTPSA id 27-20020a170906319b00b0093ba099fe64sm6650424ejy.182.2023.03.26.10.00.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Mar 2023 10:00:54 -0700 (PDT) From: Jiri Pirko To: netdev@vger.kernel.org, arkadiusz.kubalewski@intel.com, vadim.fedorenko@linux.dev, vadfed@meta.com Cc: kuba@kernel.org, jonathan.lemon@gmail.com, pabeni@redhat.com, poros@redhat.com, mschmidt@redhat.com, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org Subject: [patch dpll-rfc 1/7] dpll: make ops function args const Date: Sun, 26 Mar 2023 19:00:46 +0200 Message-Id: <20230326170052.2065791-2-jiri@resnulli.us> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230326170052.2065791-1-jiri@resnulli.us> References: <20230312022807.278528-1-vadfed@meta.com> <20230326170052.2065791-1-jiri@resnulli.us> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC From: Jiri Pirko Make ops args passed over *_register() functions const. Signed-off-by: Jiri Pirko --- drivers/dpll/dpll_core.c | 25 ++++++++++++------------- include/linux/dpll.h | 9 +++++---- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index d478ab5e2001..7f8442b73fd8 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -89,7 +89,7 @@ dpll_device_get_by_name(const char *bus_name, const char *device_name) */ static int dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, - struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv) { struct dpll_pin_ref *ref; unsigned long i; @@ -189,7 +189,7 @@ dpll_xa_ref_pin_find(struct xarray *xa_pins, const struct dpll_pin *pin) */ static int dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, - struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv) { struct dpll_pin_ref *ref; unsigned long i; @@ -385,8 +385,9 @@ EXPORT_SYMBOL_GPL(dpll_device_put); * * 0 on success * * -EINVAL on failure */ -int dpll_device_register(struct dpll_device *dpll, struct dpll_device_ops *ops, - void *priv, struct device *owner) +int dpll_device_register(struct dpll_device *dpll, + const struct dpll_device_ops *ops, void *priv, + struct device *owner) { if (WARN_ON(!ops || !owner)) return -EINVAL; @@ -551,7 +552,7 @@ EXPORT_SYMBOL_GPL(dpll_pin_put); static int __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, - struct dpll_pin_ops *ops, void *priv, + const struct dpll_pin_ops *ops, void *priv, const char *rclk_device_name) { int ret; @@ -592,10 +593,9 @@ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, * * -EINVAL - missing dpll or pin * * -ENOMEM - failed to allocate memory */ -int -dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, - struct dpll_pin_ops *ops, void *priv, - struct device *rclk_device) +int dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, + const struct dpll_pin_ops *ops, void *priv, + struct device *rclk_device) { const char *rclk_name = rclk_device ? dev_name(rclk_device) : NULL; int ret; @@ -661,10 +661,9 @@ EXPORT_SYMBOL_GPL(dpll_pin_unregister); * * -ENOMEM failed allocation * * -EPERM if parent is not allowed */ -int -dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, - struct dpll_pin_ops *ops, void *priv, - struct device *rclk_device) +int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, + const struct dpll_pin_ops *ops, void *priv, + struct device *rclk_device) { struct dpll_pin_ref *ref; unsigned long i, stop; diff --git a/include/linux/dpll.h b/include/linux/dpll.h index 2e516d91c343..496358df83a9 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -123,8 +123,9 @@ void dpll_device_put(struct dpll_device *dpll); * @owner: device struct of the owner * */ -int dpll_device_register(struct dpll_device *dpll, struct dpll_device_ops *ops, - void *priv, struct device *owner); +int dpll_device_register(struct dpll_device *dpll, + const struct dpll_device_ops *ops, void *priv, + struct device *owner); /** * dpll_device_unregister - deregister registered dpll @@ -200,7 +201,7 @@ struct dpll_pin * * -EBUSY - couldn't allocate id for a pin. */ int dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, - struct dpll_pin_ops *ops, void *priv, + const struct dpll_pin_ops *ops, void *priv, struct device *rclk_device); /** @@ -244,7 +245,7 @@ void dpll_pin_put(struct dpll_pin *pin); * * -EEXIST - pin already registered with this parent pin, */ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, - struct dpll_pin_ops *ops, void *priv, + const struct dpll_pin_ops *ops, void *priv, struct device *rclk_device); /** From patchwork Sun Mar 26 17:00:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 13188365 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C5802C74A5B for ; Sun, 26 Mar 2023 17:01:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232410AbjCZRBB (ORCPT ); Sun, 26 Mar 2023 13:01:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47894 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232406AbjCZRBA (ORCPT ); Sun, 26 Mar 2023 13:01:00 -0400 Received: from mail-ed1-x531.google.com (mail-ed1-x531.google.com [IPv6:2a00:1450:4864:20::531]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8EA4C55B5 for ; Sun, 26 Mar 2023 10:00:58 -0700 (PDT) Received: by mail-ed1-x531.google.com with SMTP id ek18so26611390edb.6 for ; Sun, 26 Mar 2023 10:00:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=resnulli-us.20210112.gappssmtp.com; s=20210112; t=1679850057; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jKvFgxFIOMcDomywgSDCrBRk0DXR5IUKz0LkYeOJtEs=; b=MqBkz9hDpJOSQidWrDvkJ50SCXAxGgp4KQaQ8as68UNv7r+sVy0Myx3RJ+JxS0ZWFy d8khfP7wEFyCx6DgShheqjpj9LRa9Q13baKFmGHjR4zUweb3OGaOGDkCAcQh6HNr+wX/ RPb14hkVRBOBwu+T950blOnTIkRPr5iA/Rp7TW2pM6Cmpju9g45PBpixLZRILCqB7/r2 uKDtc5sdPNJGCdk8qpxLT5V8RruB8MmKQ5kKvQvVa6fceDFUeV5+eedTl1YvmjlwZp3z Lgw7EVZx7lmKtKDBcBmWpLEPaOHh4ny5qzSs8YMxkUXgOdXQ7aLV2O1IYaTMWTvilQ9i cVJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679850057; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jKvFgxFIOMcDomywgSDCrBRk0DXR5IUKz0LkYeOJtEs=; b=ek2ScDQ4Zz1dLORUsfDNTIe1Ncl+5SpVlDxFJBhvUpNxWyi4lZeI/4BW7oHGB37cZd LdDGej2SufmvbDXxXnSNdftysD+btnB+xGi9f7pryvplGwP3/0AZa6HTFh+PSCw62TzI 4Cf21tUUuPe11lZwztnp3b0qRZcPg5sXcGa2rEEjQFmVxUhA4Q2JVabuxbnv3ElISY2Q bgwPe3ztbBqSJjQnGm1rLiRNevbu/rk8VTYpVaFGGDAKRxwHYHtP5Lj+Ok9QpV7GTEsU vqHTRAjmVY5FaWE8gDtl+kJoDjnkoMOIVnHHGkfqesbo2kwGO4LIc3vPNrqO/xX6Kl5X wkJw== X-Gm-Message-State: AAQBX9cFFgMknV0VZh9KlsUtDM2tLKLVoB9saYS4/kGw3dG5+klJXx7P Xz3oBK1D8RlPwlOulR1vF404xkitJkIRY8uvdRQ= X-Google-Smtp-Source: AKy350ZMSZEbVP7WntRh5N3QsB8+wW7gLpCzIK+IPhpkhbpXX0IYxYElgvFFPYGnqMCfRuH4dytvuw== X-Received: by 2002:a17:906:5fd9:b0:930:d17b:959b with SMTP id k25-20020a1709065fd900b00930d17b959bmr10024477ejv.22.1679850056882; Sun, 26 Mar 2023 10:00:56 -0700 (PDT) Received: from localhost (host-213-179-129-39.customer.m-online.net. [213.179.129.39]) by smtp.gmail.com with ESMTPSA id w17-20020a170906b19100b0093fa8c2e877sm1996762ejy.80.2023.03.26.10.00.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Mar 2023 10:00:56 -0700 (PDT) From: Jiri Pirko To: netdev@vger.kernel.org, arkadiusz.kubalewski@intel.com, vadim.fedorenko@linux.dev, vadfed@meta.com Cc: kuba@kernel.org, jonathan.lemon@gmail.com, pabeni@redhat.com, poros@redhat.com, mschmidt@redhat.com, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org Subject: [patch dpll-rfc 2/7] dpll: allow to call device register multiple times Date: Sun, 26 Mar 2023 19:00:47 +0200 Message-Id: <20230326170052.2065791-3-jiri@resnulli.us> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230326170052.2065791-1-jiri@resnulli.us> References: <20230312022807.278528-1-vadfed@meta.com> <20230326170052.2065791-1-jiri@resnulli.us> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Jiri Pirko Some devices allow to control a single dpll instance over multiple channels. In case of mlx5 for example, one dpll could be controlled over multiple PFs that reside on a single ASIC. These are equal. Allow each to register/unregister dpll device. Use the first ops and priv always as the is no difference in between those and the rest. Signed-off-by: Jiri Pirko --- drivers/dpll/dpll_core.c | 85 +++++++++++++++++++++-- drivers/dpll/dpll_core.h | 11 ++- drivers/dpll/dpll_netlink.c | 29 ++++---- drivers/net/ethernet/intel/ice/ice_dpll.c | 4 +- drivers/ptp/ptp_ocp.c | 2 +- include/linux/dpll.h | 5 +- 6 files changed, 113 insertions(+), 23 deletions(-) diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index 7f8442b73fd8..6e50216a636a 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -293,6 +293,7 @@ dpll_device_alloc(const u64 clock_id, u32 dev_driver_id, if (!dpll) return ERR_PTR(-ENOMEM); refcount_set(&dpll->refcount, 1); + INIT_LIST_HEAD(&dpll->registration_list); dpll->dev.class = &dpll_class; dpll->dev_driver_id = dev_driver_id; dpll->clock_id = clock_id; @@ -366,12 +367,26 @@ void dpll_device_put(struct dpll_device *dpll) WARN_ON_ONCE(!xa_empty(&dpll->pin_refs)); xa_destroy(&dpll->pin_refs); xa_erase(&dpll_device_xa, dpll->id); + WARN_ON(!list_empty(&dpll->registration_list)); kfree(dpll); } mutex_unlock(&dpll_device_xa_lock); } EXPORT_SYMBOL_GPL(dpll_device_put); +static struct dpll_device_registration * +dpll_device_registration_find(struct dpll_device *dpll, + const struct dpll_device_ops *ops, void *priv) +{ + struct dpll_device_registration *reg; + + list_for_each_entry(reg, &dpll->registration_list, list) { + if (reg->ops == ops && reg->priv == priv) + return reg; + } + return NULL; +} + /** * dpll_device_register - register the dpll device in the subsystem * @dpll: pointer to a dpll @@ -389,19 +404,39 @@ int dpll_device_register(struct dpll_device *dpll, const struct dpll_device_ops *ops, void *priv, struct device *owner) { + struct dpll_device_registration *reg; + bool first_registration = false; + if (WARN_ON(!ops || !owner)) return -EINVAL; + mutex_lock(&dpll_device_xa_lock); - if (ASSERT_DPLL_NOT_REGISTERED(dpll)) { + reg = dpll_device_registration_find(dpll, ops, priv); + if (reg) { mutex_unlock(&dpll_device_xa_lock); return -EEXIST; } + + reg = kzalloc(sizeof(*reg), GFP_KERNEL); + if (!reg) { + mutex_unlock(&dpll_device_xa_lock); + return -ENOMEM; + } + reg->ops = ops; + reg->priv = priv; + dpll->dev.bus = owner->bus; dpll->parent = owner; - dpll->ops = ops; dev_set_name(&dpll->dev, "%s_%d", dev_name(owner), dpll->dev_driver_id); - dpll->priv = priv; + + first_registration = list_empty(&dpll->registration_list); + list_add_tail(®->list, &dpll->registration_list); + if (!first_registration) { + mutex_unlock(&dpll_device_xa_lock); + return 0; + } + xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED); mutex_unlock(&dpll_device_xa_lock); dpll_notify_device_create(dpll); @@ -413,14 +448,32 @@ EXPORT_SYMBOL_GPL(dpll_device_register); /** * dpll_device_unregister - deregister dpll device * @dpll: registered dpll pointer + * @ops: ops for a dpll device + * @priv: pointer to private information of owner * * Deregister device, make it unavailable for userspace. * Note: It does not free the memory */ -void dpll_device_unregister(struct dpll_device *dpll) +void dpll_device_unregister(struct dpll_device *dpll, + const struct dpll_device_ops *ops, void *priv) { + struct dpll_device_registration *reg; + mutex_lock(&dpll_device_xa_lock); ASSERT_DPLL_REGISTERED(dpll); + + reg = dpll_device_registration_find(dpll, ops, priv); + if (WARN_ON(!reg)) { + mutex_unlock(&dpll_device_xa_lock); + return; + } + list_del(®->list); + kfree(reg); + + if (!list_empty(&dpll->registration_list)) { + mutex_unlock(&dpll_device_xa_lock); + return; + } xa_clear_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED); mutex_unlock(&dpll_device_xa_lock); dpll_notify_device_delete(dpll); @@ -760,6 +813,17 @@ struct dpll_pin *dpll_pin_get_by_idx(struct dpll_device *dpll, u32 idx) return NULL; } +static struct dpll_device_registration * +dpll_device_registration_first(struct dpll_device *dpll) +{ + struct dpll_device_registration *reg; + + reg = list_first_entry_or_null((struct list_head *) &dpll->registration_list, + struct dpll_device_registration, list); + WARN_ON(!reg); + return reg; +} + /** * dpll_priv - get the dpll device private owner data * @dpll: registered dpll pointer @@ -768,10 +832,21 @@ struct dpll_pin *dpll_pin_get_by_idx(struct dpll_device *dpll, u32 idx) */ void *dpll_priv(const struct dpll_device *dpll) { - return dpll->priv; + struct dpll_device_registration *reg; + + reg = dpll_device_registration_first((struct dpll_device *) dpll); + return reg->priv; } EXPORT_SYMBOL_GPL(dpll_priv); +const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll) +{ + struct dpll_device_registration *reg; + + reg = dpll_device_registration_first(dpll); + return reg->ops; +} + /** * dpll_pin_on_dpll_priv - get the dpll device private owner data * @dpll: registered dpll pointer diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h index 876b6ac6f3a0..21ba31621b44 100644 --- a/drivers/dpll/dpll_core.h +++ b/drivers/dpll/dpll_core.h @@ -7,11 +7,18 @@ #define __DPLL_CORE_H__ #include +#include #include #include "dpll_netlink.h" #define DPLL_REGISTERED XA_MARK_1 +struct dpll_device_registration { + struct list_head list; + const struct dpll_device_ops *ops; + void *priv; +}; + /** * struct dpll_device - structure for a DPLL device * @id: unique id number for each device @@ -34,9 +41,8 @@ struct dpll_device { struct device dev; struct device *parent; struct module *module; - struct dpll_device_ops *ops; enum dpll_type type; - void *priv; + struct list_head registration_list; struct xarray pin_refs; u64 clock_id; unsigned long mode_supported_mask; @@ -84,6 +90,7 @@ struct dpll_pin_ref { refcount_t refcount; }; +const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll); struct dpll_device *dpll_device_get_by_id(int id); struct dpll_device *dpll_device_get_by_name(const char *bus_name, const char *dev_name); diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index d2c699015215..430c009d0a71 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -18,7 +18,7 @@ static u32 dpll_pin_freq_value[] = { }; static int -dpll_msg_add_dev_handle(struct sk_buff *msg, const struct dpll_device *dpll) +dpll_msg_add_dev_handle(struct sk_buff *msg, struct dpll_device *dpll) { if (nla_put_u32(msg, DPLL_A_ID, dpll->id)) return -EMSGSIZE; @@ -31,14 +31,15 @@ dpll_msg_add_dev_handle(struct sk_buff *msg, const struct dpll_device *dpll) } static int -dpll_msg_add_mode(struct sk_buff *msg, const struct dpll_device *dpll, +dpll_msg_add_mode(struct sk_buff *msg, struct dpll_device *dpll, struct netlink_ext_ack *extack) { + const struct dpll_device_ops *ops = dpll_device_ops(dpll); enum dpll_mode mode; - if (WARN_ON(!dpll->ops->mode_get)) + if (WARN_ON(!ops->mode_get)) return -EOPNOTSUPP; - if (dpll->ops->mode_get(dpll, &mode, extack)) + if (ops->mode_get(dpll, &mode, extack)) return -EFAULT; if (nla_put_u8(msg, DPLL_A_MODE, mode)) return -EMSGSIZE; @@ -50,11 +51,12 @@ static int dpll_msg_add_source_pin_idx(struct sk_buff *msg, struct dpll_device *dpll, struct netlink_ext_ack *extack) { + const struct dpll_device_ops *ops = dpll_device_ops(dpll); u32 source_pin_idx; - if (!dpll->ops->source_pin_idx_get) + if (!ops->source_pin_idx_get) return 0; - if (dpll->ops->source_pin_idx_get(dpll, &source_pin_idx, extack)) + if (ops->source_pin_idx_get(dpll, &source_pin_idx, extack)) return -EFAULT; if (nla_put_u32(msg, DPLL_A_SOURCE_PIN_IDX, source_pin_idx)) return -EMSGSIZE; @@ -66,11 +68,12 @@ static int dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll, struct netlink_ext_ack *extack) { + const struct dpll_device_ops *ops = dpll_device_ops(dpll); enum dpll_lock_status status; - if (WARN_ON(!dpll->ops->lock_status_get)) + if (WARN_ON(!ops->lock_status_get)) return -EOPNOTSUPP; - if (dpll->ops->lock_status_get(dpll, &status, extack)) + if (ops->lock_status_get(dpll, &status, extack)) return -EFAULT; if (nla_put_u8(msg, DPLL_A_LOCK_STATUS, status)) return -EMSGSIZE; @@ -82,11 +85,12 @@ static int dpll_msg_add_temp(struct sk_buff *msg, struct dpll_device *dpll, struct netlink_ext_ack *extack) { + const struct dpll_device_ops *ops = dpll_device_ops(dpll); s32 temp; - if (!dpll->ops->temp_get) + if (!ops->temp_get) return -EOPNOTSUPP; - if (dpll->ops->temp_get(dpll, &temp, extack)) + if (ops->temp_get(dpll, &temp, extack)) return -EFAULT; if (nla_put_s32(msg, DPLL_A_TEMP, temp)) return -EMSGSIZE; @@ -686,6 +690,7 @@ int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) static int dpll_set_from_nlattr(struct dpll_device *dpll, struct genl_info *info) { + const struct dpll_device_ops *ops = dpll_device_ops(dpll); struct nlattr *attr; enum dpll_mode mode; int rem, ret = 0; @@ -696,9 +701,9 @@ dpll_set_from_nlattr(struct dpll_device *dpll, struct genl_info *info) case DPLL_A_MODE: mode = nla_get_u8(attr); - if (!dpll->ops || !dpll->ops->mode_set) + if (!ops->mode_set) return -EOPNOTSUPP; - ret = dpll->ops->mode_set(dpll, mode, info->extack); + ret = ops->mode_set(dpll, mode, info->extack); if (ret) return ret; break; diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c index 87572ecc21e4..532ad7314f49 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.c +++ b/drivers/net/ethernet/intel/ice/ice_dpll.c @@ -1551,7 +1551,7 @@ static void ice_dpll_release_all(struct ice_pf *pf, bool cgu) if (dp->dpll) { mutex_lock(&pf->dplls.lock); if (cgu) - dpll_device_unregister(dp->dpll); + dpll_device_unregister(dp->dpll, &ice_dpll_ops, pf); dpll_device_put(dp->dpll); mutex_unlock(&pf->dplls.lock); dev_dbg(ice_pf_to_dev(pf), "PPS dpll removed\n"); @@ -1560,7 +1560,7 @@ static void ice_dpll_release_all(struct ice_pf *pf, bool cgu) if (de->dpll) { mutex_lock(&pf->dplls.lock); if (cgu) - dpll_device_unregister(de->dpll); + dpll_device_unregister(de->dpll, &ice_dpll_ops, pf); dpll_device_put(de->dpll); mutex_unlock(&pf->dplls.lock); dev_dbg(ice_pf_to_dev(pf), "EEC dpll removed\n"); diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c index cc840d0e3265..5e7fceae2a6a 100644 --- a/drivers/ptp/ptp_ocp.c +++ b/drivers/ptp/ptp_ocp.c @@ -4431,7 +4431,7 @@ ptp_ocp_remove(struct pci_dev *pdev) struct ptp_ocp *bp = pci_get_drvdata(pdev); struct devlink *devlink = priv_to_devlink(bp); - dpll_device_unregister(bp->dpll); + dpll_device_unregister(bp->dpll, &dpll_ops, bp); dpll_device_put(bp->dpll); devlink_unregister(devlink); ptp_ocp_detach(bp); diff --git a/include/linux/dpll.h b/include/linux/dpll.h index 496358df83a9..09863d66a44c 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -130,11 +130,14 @@ int dpll_device_register(struct dpll_device *dpll, /** * dpll_device_unregister - deregister registered dpll * @dpll: pointer to dpll + * @ops: ops for a dpll device + * @priv: pointer to private information of owner * * Unregister the dpll from the subsystem, make it unavailable for netlink * API users. */ -void dpll_device_unregister(struct dpll_device *dpll); +void dpll_device_unregister(struct dpll_device *dpll, + const struct dpll_device_ops *ops, void *priv); /** * dpll_priv - get dpll private data From patchwork Sun Mar 26 17:00:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 13188366 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 355BDC74A5B for ; Sun, 26 Mar 2023 17:01:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232468AbjCZRBH (ORCPT ); Sun, 26 Mar 2023 13:01:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47946 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232428AbjCZRBB (ORCPT ); Sun, 26 Mar 2023 13:01:01 -0400 Received: from mail-ed1-x52a.google.com (mail-ed1-x52a.google.com [IPv6:2a00:1450:4864:20::52a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E5D3F5FF7 for ; Sun, 26 Mar 2023 10:00:59 -0700 (PDT) Received: by mail-ed1-x52a.google.com with SMTP id t10so26488572edd.12 for ; Sun, 26 Mar 2023 10:00:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=resnulli-us.20210112.gappssmtp.com; s=20210112; t=1679850058; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=G9ZxDtIaWa6JS/i9pa4g+bZzhL99n85gnvJfpee8Jl8=; b=x53ZrdJ9DaTRVfmR9rAfOoLh6eAY6wPjpKcxw8+0btXTlch/Agw3cDQjeVdpzVYwMF FqQowgDd6PFzuH1/AhNqveBsTO7JDT8Tpm1+qDwFEndg09eHfjYyEb3Mg5Cb5AiEfQzd 8hzdgm4zh0NC3GJpSHO43szexqhv1HiibAwlP8pLLcqJ6+emGnKha1aaPqmCQUxXg+0g XjAdTDNhJYOh8nS4wCo+EgDWZzB9532KoCPL+HEnaEkPOxhByYiSG3hizfgw6GyPEVZ/ 9eBOjTmq9bUVJ4gUOdtkpBqNZBOfPDYLGwFNso0hUF+AU8tpCcoPM+iczh0jIzi0m0h9 3Pww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679850058; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=G9ZxDtIaWa6JS/i9pa4g+bZzhL99n85gnvJfpee8Jl8=; b=KTLtmHbLBpjJCUvHnumtCABHO/G33kKYyYdkM0PrdbWGAO1aZ8Jbs1KLAbd3WcAj8x LDLWz+AfNvigGpWPY3bxDVm4AtCqb5/N//yr6Krll7P0b9rJBBFy0QhPHW1/C31khXxd 7DPsIx1RJ7fBQUqmfW/g/up+fBKPdJOrD67ZmviiYzi4Wgq8O3KWouMvbI/FGLErNIlg rB/9tmd/OHQaEbpHaOWLrdLkqXZOKANohCl8Gq63BoIy7Cp1TsEGq4FQF0grzc1a/4kY Mt9JTZn5ydF+r6e7gSI5cgi+scI7fT9VuYdX3COZRgWju+yvT+htZDc462b3+9B9F/5L jJiQ== X-Gm-Message-State: AAQBX9dRcPBYYCSIasIikyziLZvYjqTeewGbIlTN51Kc8XrC4F/uO1/r PGnCN4CtFzb+Em5qjlkYQA2vZoE4knNPfD8lEo4= X-Google-Smtp-Source: AKy350Y5aQWqa9W2mRHP1x54fuPjQgpetEBmUNq81mEiwA2RuH5Nf8qb4iSMUWnV9kRNgeyh6Inzmg== X-Received: by 2002:a17:907:77d2:b0:886:50d:be8d with SMTP id kz18-20020a17090777d200b00886050dbe8dmr10980768ejc.13.1679850058382; Sun, 26 Mar 2023 10:00:58 -0700 (PDT) Received: from localhost (host-213-179-129-39.customer.m-online.net. [213.179.129.39]) by smtp.gmail.com with ESMTPSA id ha8-20020a170906a88800b0093a6c591743sm7745266ejb.69.2023.03.26.10.00.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Mar 2023 10:00:57 -0700 (PDT) From: Jiri Pirko To: netdev@vger.kernel.org, arkadiusz.kubalewski@intel.com, vadim.fedorenko@linux.dev, vadfed@meta.com Cc: kuba@kernel.org, jonathan.lemon@gmail.com, pabeni@redhat.com, poros@redhat.com, mschmidt@redhat.com, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org Subject: [patch dpll-rfc 3/7] dpll: introduce a helper to get first dpll ref and use it Date: Sun, 26 Mar 2023 19:00:48 +0200 Message-Id: <20230326170052.2065791-4-jiri@resnulli.us> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230326170052.2065791-1-jiri@resnulli.us> References: <20230312022807.278528-1-vadfed@meta.com> <20230326170052.2065791-1-jiri@resnulli.us> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC From: Jiri Pirko No need to iterate xaarray in dpll_msg_add_pin_direction() and dpll_msg_add_pin_freq(). Just introduce a helper to get the first dpll reference and use that. Add a check for ops not being null in pin_register() function, not only for sake of this change, but also for the sake of existing code relying on it. Signed-off-by: Jiri Pirko --- drivers/dpll/dpll_core.c | 12 ++++++++++++ drivers/dpll/dpll_core.h | 1 + drivers/dpll/dpll_netlink.c | 34 ++++++++++++---------------------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index 6e50216a636a..2f788d2349fe 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -267,6 +267,15 @@ dpll_xa_ref_dpll_find(struct xarray *xa_refs, const struct dpll_device *dpll) return NULL; } +struct dpll_pin_ref *dpll_xa_ref_dpll_first(struct xarray *xa_refs) +{ + struct dpll_pin_ref *ref; + unsigned long i = 0; + + ref = xa_find(xa_refs, &i, ULONG_MAX, XA_PRESENT); + WARN_ON(!ref); + return ref; +} /** * dpll_device_alloc - allocate the memory for dpll device @@ -610,6 +619,9 @@ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, { int ret; + if (WARN_ON(!ops)) + return -EINVAL; + if (rclk_device_name && !pin->rclk_dev_name) { pin->rclk_dev_name = kstrdup(rclk_device_name, GFP_KERNEL); if (!pin->rclk_dev_name) diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h index 21ba31621b44..636dd4c6710e 100644 --- a/drivers/dpll/dpll_core.h +++ b/drivers/dpll/dpll_core.h @@ -99,6 +99,7 @@ struct dpll_pin_ref * dpll_xa_ref_pin_find(struct xarray *xa_refs, const struct dpll_pin *pin); struct dpll_pin_ref * dpll_xa_ref_dpll_find(struct xarray *xa_refs, const struct dpll_device *dpll); +struct dpll_pin_ref *dpll_xa_ref_dpll_first(struct xarray *xa_refs); extern struct xarray dpll_device_xa; extern struct xarray dpll_pin_xa; extern struct mutex dpll_device_xa_lock; diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index 430c009d0a71..41e2f8a90aeb 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -134,18 +134,11 @@ dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, const struct dpll_pin *pin, static int dpll_msg_add_pin_direction(struct sk_buff *msg, const struct dpll_pin *pin, + struct dpll_pin_ref *ref, struct netlink_ext_ack *extack) { enum dpll_pin_direction direction; - struct dpll_pin_ref *ref; - unsigned long i; - xa_for_each((struct xarray *)&pin->dpll_refs, i, ref) { - if (ref && ref->ops && ref->dpll) - break; - } - if (!ref || !ref->ops || !ref->dpll) - return -ENODEV; if (!ref->ops->direction_get) return -EOPNOTSUPP; if (ref->ops->direction_get(pin, ref->dpll, &direction, extack)) @@ -158,19 +151,12 @@ dpll_msg_add_pin_direction(struct sk_buff *msg, const struct dpll_pin *pin, static int dpll_msg_add_pin_freq(struct sk_buff *msg, const struct dpll_pin *pin, - struct netlink_ext_ack *extack, bool dump_any_freq) + struct dpll_pin_ref *ref, struct netlink_ext_ack *extack, + bool dump_any_freq) { enum dpll_pin_freq_supp fs; - struct dpll_pin_ref *ref; - unsigned long i; u32 freq; - xa_for_each((struct xarray *)&pin->dpll_refs, i, ref) { - if (ref && ref->ops && ref->dpll) - break; - } - if (!ref || !ref->ops || !ref->dpll) - return -ENODEV; if (!ref->ops->frequency_get) return -EOPNOTSUPP; if (ref->ops->frequency_get(pin, ref->dpll, &freq, extack)) @@ -325,10 +311,11 @@ dpll_cmd_pin_on_dpll_get(struct sk_buff *msg, struct dpll_pin *pin, return -EMSGSIZE; if (nla_put_u32(msg, DPLL_A_PIN_DPLL_CAPS, pin->prop.capabilities)) return -EMSGSIZE; - ret = dpll_msg_add_pin_direction(msg, pin, extack); + ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); + ret = dpll_msg_add_pin_direction(msg, pin, ref, extack); if (ret) return ret; - ret = dpll_msg_add_pin_freq(msg, pin, extack, true); + ret = dpll_msg_add_pin_freq(msg, pin, ref, extack, true); if (ret && ret != -EOPNOTSUPP) return ret; ref = dpll_xa_ref_dpll_find(&pin->dpll_refs, dpll); @@ -355,6 +342,7 @@ static int __dpll_cmd_pin_dump_one(struct sk_buff *msg, struct dpll_pin *pin, struct netlink_ext_ack *extack, bool dump_dpll) { + struct dpll_pin_ref *ref; int ret; if (nla_put_u32(msg, DPLL_A_PIN_IDX, pin->dev_driver_id)) @@ -363,10 +351,11 @@ __dpll_cmd_pin_dump_one(struct sk_buff *msg, struct dpll_pin *pin, return -EMSGSIZE; if (nla_put_u8(msg, DPLL_A_PIN_TYPE, pin->prop.type)) return -EMSGSIZE; - ret = dpll_msg_add_pin_direction(msg, pin, extack); + ref = dpll_xa_ref_dpll_first(&pin->dpll_refs); + ret = dpll_msg_add_pin_direction(msg, pin, ref, extack); if (ret) return ret; - ret = dpll_msg_add_pin_freq(msg, pin, extack, true); + ret = dpll_msg_add_pin_freq(msg, pin, ref, extack, true); if (ret && ret != -EOPNOTSUPP) return ret; ret = dpll_msg_add_pins_on_pin(msg, pin, extack); @@ -920,7 +909,8 @@ dpll_event_device_change(struct sk_buff *msg, struct dpll_device *dpll, ret = dpll_msg_add_temp(msg, dpll, NULL); break; case DPLL_A_PIN_FREQUENCY: - ret = dpll_msg_add_pin_freq(msg, pin, NULL, false); + ref = dpll_xa_ref_dpll_find(&pin->dpll_refs, dpll); + ret = dpll_msg_add_pin_freq(msg, pin, ref, NULL, false); break; case DPLL_A_PIN_PRIO: ref = dpll_xa_ref_dpll_find(&pin->dpll_refs, dpll); From patchwork Sun Mar 26 17:00:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 13188368 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8469AC761AF for ; Sun, 26 Mar 2023 17:01:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232420AbjCZRBJ (ORCPT ); Sun, 26 Mar 2023 13:01:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48050 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232455AbjCZRBD (ORCPT ); Sun, 26 Mar 2023 13:01:03 -0400 Received: from mail-ed1-x536.google.com (mail-ed1-x536.google.com [IPv6:2a00:1450:4864:20::536]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8DB5D6582 for ; Sun, 26 Mar 2023 10:01:00 -0700 (PDT) Received: by mail-ed1-x536.google.com with SMTP id ew6so26537106edb.7 for ; Sun, 26 Mar 2023 10:01:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=resnulli-us.20210112.gappssmtp.com; s=20210112; t=1679850060; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=668o2k4Nn1fxnXh54mywli34jSX4IoNNpKzsc6h/awQ=; b=Xoa5KgJ08Zo4I18MXAfK4jZv6x2ycI0dUMCvDutflAM4KBUxE1fPfGXfIEqLzv25KT uVNNeCBbbgvUtKd0OwA7tOBLajKVIqqXYm+3eDrFJbNTFrJApH37BAw+hFEQ0LvO9Af5 YEqb8iqvDUKQwRlLpHvnmG73p7snY/uBkg6zpbF7kBtR8ihS22kqDZ4iCZArrB1kKJPR 7+R7R4DsCFP5jb18h0TgEy6waXzgU3F+XtdLy+J21tTr/9ZPoXvoUUF5ZvPZRM0xPCMj 40mr4sXgEDWxmpDBr0qJNnAJRSAU/fhI/Lys/hYhfg8hDuWANE6/yFyHBNdDffPvOsSY dzBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679850060; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=668o2k4Nn1fxnXh54mywli34jSX4IoNNpKzsc6h/awQ=; b=YeD5eDP7oBD49sUN1Nsb/T7srXvChdUl0ugIVLpT5+VE6kqEie+qDAUmLNXWpCP96J /SEknSgdoQatbSKTCZjxQa+UoaWedMZZk9Yhd2Modi/daTc/foQwAyJA8FwnHXHYBR7b /wZEsnVt2q/RQU19PGxsTI1E9iRKH0ugIeEtJN66Ggeh9GChEJEu2M3PwGunUIWlQOhm 33rYlhwqpYGfNO0whQ32kM6IRU61NSWUOzzzjOOjHiIO5JvVN4mBL6qY6My7e2n6k9yD XKjKo/0bM6F2heA85pJcRy90YGREhUYbUohMrcs05WFyqN51NEmahP7T1xADGkbBqzDN 3NxQ== X-Gm-Message-State: AAQBX9drUgQBC+1sU2EIFtXjObrSjd1ERRS5XCODqNX9TqoROE5EgLk3 4CclP0J0ITj62jmlvACVuK73aKmPn+JMTPT+X+E= X-Google-Smtp-Source: AKy350aDM78BliaPSmIQXAF7QZlXug3YwSHicTayVwm1NuE+noFc+cwTmnEeawHX7ilYH8pc1DnafA== X-Received: by 2002:a17:906:ca0c:b0:930:1914:88fe with SMTP id jt12-20020a170906ca0c00b00930191488femr9309271ejb.68.1679850059899; Sun, 26 Mar 2023 10:00:59 -0700 (PDT) Received: from localhost (host-213-179-129-39.customer.m-online.net. [213.179.129.39]) by smtp.gmail.com with ESMTPSA id c24-20020a50d658000000b00501d5432f2fsm8837945edj.60.2023.03.26.10.00.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Mar 2023 10:00:59 -0700 (PDT) From: Jiri Pirko To: netdev@vger.kernel.org, arkadiusz.kubalewski@intel.com, vadim.fedorenko@linux.dev, vadfed@meta.com Cc: kuba@kernel.org, jonathan.lemon@gmail.com, pabeni@redhat.com, poros@redhat.com, mschmidt@redhat.com, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org Subject: [patch dpll-rfc 4/7] dpll: allow to call pin register multiple times Date: Sun, 26 Mar 2023 19:00:49 +0200 Message-Id: <20230326170052.2065791-5-jiri@resnulli.us> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230326170052.2065791-1-jiri@resnulli.us> References: <20230312022807.278528-1-vadfed@meta.com> <20230326170052.2065791-1-jiri@resnulli.us> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Jiri Pirko Some devices allow to control a single dpll pin instance over multiple channels. In case of mlx5 for example, one dpll pin could be controlled over multiple PFs that reside on a single ASIC. These are equal. Allow each to register/unregister dpll pin. Use the first ops and priv always as the is no difference in between those and the rest. Replace the existing reference counting by the list of registrations as they serve the same purpose. Signed-off-by: Jiri Pirko --- drivers/dpll/dpll_core.c | 212 +++++++++++++++------- drivers/dpll/dpll_core.h | 13 +- drivers/dpll/dpll_netlink.c | 69 ++++--- drivers/net/ethernet/intel/ice/ice_dpll.c | 18 +- include/linux/dpll.h | 8 +- 5 files changed, 220 insertions(+), 100 deletions(-) diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index 2f788d2349fe..dfff3e07fe43 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -73,6 +73,19 @@ dpll_device_get_by_name(const char *bus_name, const char *device_name) return ret; } +static struct dpll_pin_registration * +dpll_pin_registration_find(struct dpll_pin_ref *ref, + const struct dpll_pin_ops *ops, void *priv) +{ + struct dpll_pin_registration *reg; + + list_for_each_entry(reg, &ref->registration_list, list) { + if (reg->ops == ops && reg->priv == priv) + return reg; + } + return NULL; +} + /** * dpll_xa_ref_pin_add - add pin reference to a given xarray * @xa_pins: dpll_pin_ref xarray holding pins @@ -80,8 +93,8 @@ dpll_device_get_by_name(const char *bus_name, const char *device_name) * @ops: ops for a pin * @priv: pointer to private data of owner * - * Allocate and create reference of a pin or increase refcount on existing pin - * reference on given xarray. + * Allocate and create reference of a pin and enlist a registration + * structure storing ops and priv pointers of a caller registant. * * Return: * * 0 on success @@ -91,31 +104,48 @@ static int dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, const struct dpll_pin_ops *ops, void *priv) { + struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; + bool ref_exists = false; unsigned long i; u32 idx; int ret; xa_for_each(xa_pins, i, ref) { - if (ref->pin == pin) { - refcount_inc(&ref->refcount); - return 0; + if (ref->pin != pin) + continue; + reg = dpll_pin_registration_find(ref, ops, priv); + if (reg) + return -EEXIST; + ref_exists = true; + break; + } + + if (!ref_exists) { + ref = kzalloc(sizeof(*ref), GFP_KERNEL); + if (!ref) + return -ENOMEM; + ref->pin = pin; + INIT_LIST_HEAD(&ref->registration_list); + ret = xa_alloc(xa_pins, &idx, ref, xa_limit_16b, GFP_KERNEL); + if (ret) { + kfree(ref); + return ret; } } - ref = kzalloc(sizeof(*ref), GFP_KERNEL); - if (!ref) + reg = kzalloc(sizeof(*reg), GFP_KERNEL); + if (!reg) { + if (!ref_exists) + kfree(ref); return -ENOMEM; - ref->pin = pin; - ref->ops = ops; - ref->priv = priv; - ret = xa_alloc(xa_pins, &idx, ref, xa_limit_16b, GFP_KERNEL); - if (!ret) - refcount_set(&ref->refcount, 1); - else - kfree(ref); + } + reg->ops = ops; + reg->priv = priv; - return ret; + list_add_tail(®->list, &ref->registration_list); + + return 0; } /** @@ -124,25 +154,31 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, * @pin: pointer to a pin * * Decrement refcount of existing pin reference on given xarray. - * If all references are dropped, delete the reference and free its memory. + * If all registrations are lifted delete the reference and free its memory. * * Return: * * 0 on success * * -EINVAL if reference to a pin was not found */ -static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin) +static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin, + const struct dpll_pin_ops *ops, void *priv) { + struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; unsigned long i; xa_for_each(xa_pins, i, ref) { - if (ref->pin == pin) { - if (refcount_dec_and_test(&ref->refcount)) { - xa_erase(xa_pins, i); - kfree(ref); - } - return 0; - } + if (ref->pin != pin) + continue; + reg = dpll_pin_registration_find(ref, ops, priv); + if (WARN_ON(!reg)) + return -EINVAL; + list_del(®->list); + kfree(reg); + xa_erase(xa_pins, i); + WARN_ON(!list_empty(&ref->registration_list)); + kfree(ref); + return 0; } return -EINVAL; @@ -191,30 +227,48 @@ static int dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, const struct dpll_pin_ops *ops, void *priv) { + struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; + bool ref_exists = false; unsigned long i; u32 idx; int ret; xa_for_each(xa_dplls, i, ref) { - if (ref->dpll == dpll) { - refcount_inc(&ref->refcount); - return 0; + if (ref->dpll != dpll) + continue; + reg = dpll_pin_registration_find(ref, ops, priv); + if (reg) + return -EEXIST; + ref_exists = true; + break; + } + + if (!ref_exists) { + ref = kzalloc(sizeof(*ref), GFP_KERNEL); + if (!ref) + return -ENOMEM; + ref->dpll = dpll; + INIT_LIST_HEAD(&ref->registration_list); + ret = xa_alloc(xa_dplls, &idx, ref, xa_limit_16b, GFP_KERNEL); + if (ret) { + kfree(ref); + return ret; } } - ref = kzalloc(sizeof(*ref), GFP_KERNEL); - if (!ref) + + reg = kzalloc(sizeof(*reg), GFP_KERNEL); + if (!reg) { + if (!ref_exists) + kfree(ref); return -ENOMEM; - ref->dpll = dpll; - ref->ops = ops; - ref->priv = priv; - ret = xa_alloc(xa_dplls, &idx, ref, xa_limit_16b, GFP_KERNEL); - if (!ret) - refcount_set(&ref->refcount, 1); - else - kfree(ref); + } + reg->ops = ops; + reg->priv = priv; - return ret; + list_add_tail(®->list, &ref->registration_list); + + return 0; } /** @@ -226,19 +280,25 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, * If all references are dropped, delete the reference and free its memory. */ static void -dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll) +dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll, + const struct dpll_pin_ops *ops, void *priv) { + struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; unsigned long i; xa_for_each(xa_dplls, i, ref) { - if (ref->dpll == dpll) { - if (refcount_dec_and_test(&ref->refcount)) { - xa_erase(xa_dplls, i); - kfree(ref); - } - break; - } + if (ref->dpll != dpll) + continue; + reg = dpll_pin_registration_find(ref, ops, priv); + if (WARN_ON(!reg)) + return; + list_del(®->list); + kfree(reg); + xa_erase(xa_dplls, i); + WARN_ON(!list_empty(&ref->registration_list)); + kfree(ref); + return; } } @@ -639,7 +699,7 @@ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, return ret; ref_pin_del: - dpll_xa_ref_pin_del(&dpll->pin_refs, pin); + dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv); rclk_free: kfree(pin->rclk_dev_name); return ret; @@ -681,27 +741,31 @@ int dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, EXPORT_SYMBOL_GPL(dpll_pin_register); static void -__dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin) +__dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, + const struct dpll_pin_ops *ops, void *priv) { - dpll_xa_ref_pin_del(&dpll->pin_refs, pin); - dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll); + dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv); + dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv); } /** * dpll_pin_unregister - deregister dpll pin from dpll device * @dpll: registered dpll pointer * @pin: pointer to a pin + * @ops: ops for a dpll pin ops + * @priv: pointer to private information of owner * * Note: It does not free the memory */ -int dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin) +int dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, + const struct dpll_pin_ops *ops, void *priv) { if (WARN_ON(xa_empty(&dpll->pin_refs))) return -ENOENT; mutex_lock(&dpll_device_xa_lock); mutex_lock(&dpll_pin_xa_lock); - __dpll_pin_unregister(dpll, pin); + __dpll_pin_unregister(dpll, pin, ops, priv); mutex_unlock(&dpll_pin_xa_lock); mutex_unlock(&dpll_device_xa_lock); @@ -763,12 +827,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, xa_for_each(&parent->dpll_refs, i, ref) { if (i < stop) { mutex_lock(&dpll_device_xa_lock); - __dpll_pin_unregister(ref->dpll, pin); + __dpll_pin_unregister(ref->dpll, pin, ops, priv); mutex_unlock(&dpll_device_xa_lock); } } refcount_dec(&pin->refcount); - dpll_xa_ref_pin_del(&pin->parent_refs, parent); + dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv); unlock: mutex_unlock(&dpll_pin_xa_lock); return ret; @@ -779,20 +843,23 @@ EXPORT_SYMBOL_GPL(dpll_pin_on_pin_register); * dpll_pin_on_pin_unregister - deregister dpll pin from a parent pin * @parent: pointer to a parent pin * @pin: pointer to a pin + * @ops: ops for a dpll pin + * @priv: pointer to private information of owner * * Note: It does not free the memory */ -void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin) +void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, + const struct dpll_pin_ops *ops, void *priv) { struct dpll_pin_ref *ref; unsigned long i; mutex_lock(&dpll_device_xa_lock); mutex_lock(&dpll_pin_xa_lock); - dpll_xa_ref_pin_del(&pin->parent_refs, parent); + dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv); refcount_dec(&pin->refcount); xa_for_each(&pin->dpll_refs, i, ref) { - __dpll_pin_unregister(ref->dpll, pin); + __dpll_pin_unregister(ref->dpll, pin, ops, priv); dpll_pin_parent_notify(ref->dpll, pin, parent, DPLL_A_PIN_IDX); } @@ -859,6 +926,17 @@ const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll) return reg->ops; } +static struct dpll_pin_registration * +dpll_pin_registration_first(struct dpll_pin_ref *ref) +{ + struct dpll_pin_registration *reg; + + reg = list_first_entry_or_null(&ref->registration_list, + struct dpll_pin_registration, list); + WARN_ON(!reg); + return reg; +} + /** * dpll_pin_on_dpll_priv - get the dpll device private owner data * @dpll: registered dpll pointer @@ -869,13 +947,14 @@ const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll) void *dpll_pin_on_dpll_priv(const struct dpll_device *dpll, const struct dpll_pin *pin) { + struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; ref = dpll_xa_ref_pin_find((struct xarray *)&dpll->pin_refs, pin); if (!ref) return NULL; - - return ref->priv; + reg = dpll_pin_registration_first(ref); + return reg->priv; } EXPORT_SYMBOL_GPL(dpll_pin_on_dpll_priv); @@ -889,16 +968,25 @@ EXPORT_SYMBOL_GPL(dpll_pin_on_dpll_priv); void *dpll_pin_on_pin_priv(const struct dpll_pin *parent, const struct dpll_pin *pin) { + struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; ref = dpll_xa_ref_pin_find((struct xarray *)&pin->parent_refs, parent); if (!ref) return NULL; - - return ref->priv; + reg = dpll_pin_registration_first(ref); + return reg->priv; } EXPORT_SYMBOL_GPL(dpll_pin_on_pin_priv); +const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref) +{ + struct dpll_pin_registration *reg; + + reg = dpll_pin_registration_first(ref); + return reg->ops; +} + static int __init dpll_init(void) { int ret; diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h index 636dd4c6710e..2ab2d9e0a3cd 100644 --- a/drivers/dpll/dpll_core.h +++ b/drivers/dpll/dpll_core.h @@ -73,27 +73,30 @@ struct dpll_pin { refcount_t refcount; }; +struct dpll_pin_registration { + struct list_head list; + const struct dpll_pin_ops *ops; + void *priv; +}; + /** * struct dpll_pin_ref - structure for referencing either dpll or pins * @dpll: pointer to a dpll * @pin: pointer to a pin - * @ops: ops for a dpll pin - * @priv: pointer to private information of owner **/ struct dpll_pin_ref { union { struct dpll_device *dpll; struct dpll_pin *pin; }; - struct dpll_pin_ops *ops; - void *priv; - refcount_t refcount; + struct list_head registration_list; }; const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll); struct dpll_device *dpll_device_get_by_id(int id); struct dpll_device *dpll_device_get_by_name(const char *bus_name, const char *dev_name); +const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref); struct dpll_pin *dpll_pin_get_by_idx(struct dpll_device *dpll, u32 idx); struct dpll_pin_ref * dpll_xa_ref_pin_find(struct xarray *xa_refs, const struct dpll_pin *pin); diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index 41e2f8a90aeb..125dc3c7e643 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -103,11 +103,12 @@ dpll_msg_add_pin_prio(struct sk_buff *msg, const struct dpll_pin *pin, struct dpll_pin_ref *ref, struct netlink_ext_ack *extack) { + const struct dpll_pin_ops *ops = dpll_pin_ops(ref); u32 prio; - if (!ref->ops->prio_get) + if (!ops->prio_get) return -EOPNOTSUPP; - if (ref->ops->prio_get(pin, ref->dpll, &prio, extack)) + if (ops->prio_get(pin, ref->dpll, &prio, extack)) return -EFAULT; if (nla_put_u32(msg, DPLL_A_PIN_PRIO, prio)) return -EMSGSIZE; @@ -120,11 +121,12 @@ dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, const struct dpll_pin *pin, struct dpll_pin_ref *ref, struct netlink_ext_ack *extack) { + const struct dpll_pin_ops *ops = dpll_pin_ops(ref); enum dpll_pin_state state; - if (!ref->ops->state_on_dpll_get) + if (!ops->state_on_dpll_get) return -EOPNOTSUPP; - if (ref->ops->state_on_dpll_get(pin, ref->dpll, &state, extack)) + if (ops->state_on_dpll_get(pin, ref->dpll, &state, extack)) return -EFAULT; if (nla_put_u8(msg, DPLL_A_PIN_STATE, state)) return -EMSGSIZE; @@ -137,11 +139,12 @@ dpll_msg_add_pin_direction(struct sk_buff *msg, const struct dpll_pin *pin, struct dpll_pin_ref *ref, struct netlink_ext_ack *extack) { + const struct dpll_pin_ops *ops = dpll_pin_ops(ref); enum dpll_pin_direction direction; - if (!ref->ops->direction_get) + if (!ops->direction_get) return -EOPNOTSUPP; - if (ref->ops->direction_get(pin, ref->dpll, &direction, extack)) + if (ops->direction_get(pin, ref->dpll, &direction, extack)) return -EFAULT; if (nla_put_u8(msg, DPLL_A_PIN_DIRECTION, direction)) return -EMSGSIZE; @@ -154,12 +157,13 @@ dpll_msg_add_pin_freq(struct sk_buff *msg, const struct dpll_pin *pin, struct dpll_pin_ref *ref, struct netlink_ext_ack *extack, bool dump_any_freq) { + const struct dpll_pin_ops *ops = dpll_pin_ops(ref); enum dpll_pin_freq_supp fs; u32 freq; - if (!ref->ops->frequency_get) + if (!ops->frequency_get) return -EOPNOTSUPP; - if (ref->ops->frequency_get(pin, ref->dpll, &freq, extack)) + if (ops->frequency_get(pin, ref->dpll, &freq, extack)) return -EFAULT; if (nla_put_u32(msg, DPLL_A_PIN_FREQUENCY, freq)) return -EMSGSIZE; @@ -196,10 +200,12 @@ dpll_msg_add_pin_parents(struct sk_buff *msg, struct dpll_pin *pin, int ret; xa_for_each(&pin->parent_refs, index, ref_parent) { - if (WARN_ON(!ref_parent->ops->state_on_pin_get)) + const struct dpll_pin_ops *ops = dpll_pin_ops(ref_parent); + + if (WARN_ON(!ops->state_on_pin_get)) return -EFAULT; - ret = ref_parent->ops->state_on_pin_get(pin, ref_parent->pin, - &state, extack); + ret = ops->state_on_pin_get(pin, ref_parent->pin, + &state, extack); if (ret) return -EFAULT; nest = nla_nest_start(msg, DPLL_A_PIN_PARENT); @@ -235,10 +241,11 @@ dpll_msg_add_pins_on_pin(struct sk_buff *msg, struct dpll_pin *pin, int ret; xa_for_each(&pin->parent_refs, index, ref) { - if (WARN_ON(!ref->ops->state_on_pin_get)) + const struct dpll_pin_ops *ops = dpll_pin_ops(ref); + + if (WARN_ON(!ops->state_on_pin_get)) return -EFAULT; - ret = ref->ops->state_on_pin_get(pin, ref->pin, &state, - extack); + ret = ops->state_on_pin_get(pin, ref->pin, &state, extack); if (ret) return -EFAULT; nest = nla_nest_start(msg, DPLL_A_PIN_PARENT); @@ -452,7 +459,9 @@ dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a, return -EINVAL; xa_for_each(&pin->dpll_refs, i, ref) { - ret = ref->ops->frequency_set(pin, ref->dpll, freq, extack); + const struct dpll_pin_ops *ops = dpll_pin_ops(ref); + + ret = ops->frequency_set(pin, ref->dpll, freq, extack); if (ret) return -EFAULT; dpll_pin_notify(ref->dpll, pin, DPLL_A_PIN_FREQUENCY); @@ -466,6 +475,7 @@ dpll_pin_on_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin, u32 parent_idx, enum dpll_pin_state state, struct netlink_ext_ack *extack) { + const struct dpll_pin_ops *ops; struct dpll_pin_ref *ref; struct dpll_pin *parent; @@ -477,9 +487,10 @@ dpll_pin_on_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin, ref = dpll_xa_ref_pin_find(&pin->parent_refs, parent); if (!ref) return -EINVAL; - if (!ref->ops || !ref->ops->state_on_pin_set) + ops = dpll_pin_ops(ref); + if (!ops->state_on_pin_set) return -EOPNOTSUPP; - if (ref->ops->state_on_pin_set(pin, parent, state, extack)) + if (ops->state_on_pin_set(pin, parent, state, extack)) return -EFAULT; dpll_pin_parent_notify(dpll, pin, parent, DPLL_A_PIN_STATE); @@ -491,6 +502,7 @@ dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin, enum dpll_pin_state state, struct netlink_ext_ack *extack) { + const struct dpll_pin_ops *ops; struct dpll_pin_ref *ref; if (!(DPLL_PIN_CAPS_STATE_CAN_CHANGE & pin->prop.capabilities)) @@ -498,9 +510,10 @@ dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin, ref = dpll_xa_ref_dpll_find(&pin->dpll_refs, dpll); if (!ref) return -EFAULT; - if (!ref->ops || !ref->ops->state_on_dpll_set) + ops = dpll_pin_ops(ref); + if (!ops->state_on_dpll_set) return -EOPNOTSUPP; - if (ref->ops->state_on_dpll_set(pin, ref->dpll, state, extack)) + if (ops->state_on_dpll_set(pin, ref->dpll, state, extack)) return -EINVAL; dpll_pin_notify(ref->dpll, pin, DPLL_A_PIN_STATE); @@ -511,6 +524,7 @@ static int dpll_pin_prio_set(struct dpll_device *dpll, struct dpll_pin *pin, struct nlattr *prio_attr, struct netlink_ext_ack *extack) { + const struct dpll_pin_ops *ops; struct dpll_pin_ref *ref; u32 prio = nla_get_u8(prio_attr); @@ -519,9 +533,10 @@ dpll_pin_prio_set(struct dpll_device *dpll, struct dpll_pin *pin, ref = dpll_xa_ref_dpll_find(&pin->dpll_refs, dpll); if (!ref) return -EFAULT; - if (!ref->ops || !ref->ops->prio_set) + ops = dpll_pin_ops(ref); + if (!ops->prio_set) return -EOPNOTSUPP; - if (ref->ops->prio_set(pin, dpll, prio, extack)) + if (ops->prio_set(pin, dpll, prio, extack)) return -EINVAL; dpll_pin_notify(dpll, pin, DPLL_A_PIN_PRIO); @@ -540,7 +555,9 @@ dpll_pin_direction_set(struct dpll_pin *pin, struct nlattr *a, return -EOPNOTSUPP; xa_for_each(&pin->dpll_refs, i, ref) { - if (ref->ops->direction_set(pin, ref->dpll, direction, extack)) + const struct dpll_pin_ops *ops = dpll_pin_ops(ref); + + if (ops->direction_set(pin, ref->dpll, direction, extack)) return -EFAULT; dpll_pin_notify(ref->dpll, pin, DPLL_A_PIN_DIRECTION); } @@ -920,13 +937,15 @@ dpll_event_device_change(struct sk_buff *msg, struct dpll_device *dpll, break; case DPLL_A_PIN_STATE: if (parent) { + const struct dpll_pin_ops *ops; + ref = dpll_xa_ref_pin_find(&pin->parent_refs, parent); if (!ref) return -EFAULT; - if (!ref->ops || !ref->ops->state_on_pin_get) + ops = dpll_pin_ops(ref); + if (!ops->state_on_pin_get) return -EOPNOTSUPP; - ret = ref->ops->state_on_pin_get(pin, parent, &state, - NULL); + ret = ops->state_on_pin_get(pin, parent, &state, NULL); if (ret) return ret; if (nla_put_u32(msg, DPLL_A_PIN_PARENT_IDX, diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c index 532ad7314f49..d39292ad102f 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.c +++ b/drivers/net/ethernet/intel/ice/ice_dpll.c @@ -1194,7 +1194,8 @@ ice_dpll_release_rclk_pin(struct ice_pf *pf) parent = pf->dplls.inputs[rclk->parent_idx[i]].pin; if (!parent) continue; - dpll_pin_on_pin_unregister(parent, rclk->pin); + dpll_pin_on_pin_unregister(parent, rclk->pin, + &ice_dpll_rclk_ops, pf); } dpll_pin_put(rclk->pin); rclk->pin = NULL; @@ -1202,6 +1203,7 @@ ice_dpll_release_rclk_pin(struct ice_pf *pf) /** * ice_dpll_release_pins - release pin's from dplls registered in subsystem + * @pf: board private structure * @dpll_eec: dpll_eec dpll pointer * @dpll_pps: dpll_pps dpll pointer * @pins: pointer to pins array @@ -1215,7 +1217,7 @@ ice_dpll_release_rclk_pin(struct ice_pf *pf) * * positive - number of errors encounterd on pin's deregistration. */ static int -ice_dpll_release_pins(struct dpll_device *dpll_eec, +ice_dpll_release_pins(struct ice_pf *pf, struct dpll_device *dpll_eec, struct dpll_device *dpll_pps, struct ice_dpll_pin *pins, int count, bool cgu) { @@ -1226,12 +1228,16 @@ ice_dpll_release_pins(struct dpll_device *dpll_eec, if (p && !IS_ERR_OR_NULL(p->pin)) { if (cgu && dpll_eec) { - ret = dpll_pin_unregister(dpll_eec, p->pin); + ret = dpll_pin_unregister(dpll_eec, p->pin, + &ice_dpll_source_ops, + pf); if (ret) err++; } if (cgu && dpll_pps) { - ret = dpll_pin_unregister(dpll_pps, p->pin); + ret = dpll_pin_unregister(dpll_pps, p->pin, + &ice_dpll_source_ops, + pf); if (ret) err++; } @@ -1532,7 +1538,7 @@ static void ice_dpll_release_all(struct ice_pf *pf, bool cgu) mutex_lock(&pf->dplls.lock); ice_dpll_release_rclk_pin(pf); - ret = ice_dpll_release_pins(de->dpll, dp->dpll, d->inputs, + ret = ice_dpll_release_pins(pf, de->dpll, dp->dpll, d->inputs, d->num_inputs, cgu); mutex_unlock(&pf->dplls.lock); if (ret) @@ -1540,7 +1546,7 @@ static void ice_dpll_release_all(struct ice_pf *pf, bool cgu) "source pins release dplls err=%d\n", ret); if (cgu) { mutex_lock(&pf->dplls.lock); - ret = ice_dpll_release_pins(de->dpll, dp->dpll, d->outputs, + ret = ice_dpll_release_pins(pf, de->dpll, dp->dpll, d->outputs, d->num_outputs, cgu); mutex_unlock(&pf->dplls.lock); if (ret) diff --git a/include/linux/dpll.h b/include/linux/dpll.h index 09863d66a44c..be5717e1da99 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -211,6 +211,8 @@ int dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, * dpll_pin_unregister - deregister pin from a dpll device * @dpll: pointer to dpll object to deregister pin from * @pin: pointer to allocated pin object being deregistered from dpll + * @ops: ops for a dpll pin ops + * @priv: pointer to private information of owner * * Deregister previously registered pin object from a dpll device. * @@ -219,7 +221,8 @@ int dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, * * -ENXIO - given pin was not registered with this dpll device, * * -EINVAL - pin pointer is not valid. */ -int dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin); +int dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, + const struct dpll_pin_ops *ops, void *priv); /** * dpll_pin_put - drop reference to a pin acquired with dpll_pin_get @@ -268,7 +271,8 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, * * -ENOMEM - failed to allocate memory, * * -EEXIST - pin already registered with this parent pin, */ -void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin); +void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, + const struct dpll_pin_ops *ops, void *priv); /** * dpll_device_notify - notify on dpll device change From patchwork Sun Mar 26 17:00:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 13188367 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02EF6C74A5B for ; Sun, 26 Mar 2023 17:01:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232495AbjCZRBK (ORCPT ); Sun, 26 Mar 2023 13:01:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232456AbjCZRBG (ORCPT ); Sun, 26 Mar 2023 13:01:06 -0400 Received: from mail-ed1-x536.google.com (mail-ed1-x536.google.com [IPv6:2a00:1450:4864:20::536]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C6635659C for ; Sun, 26 Mar 2023 10:01:01 -0700 (PDT) Received: by mail-ed1-x536.google.com with SMTP id x3so26519997edb.10 for ; Sun, 26 Mar 2023 10:01:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=resnulli-us.20210112.gappssmtp.com; s=20210112; t=1679850061; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bwW6oUpD5h8cj23E/vde86PKPUzMAEIVBwgEWSiD3uA=; b=maShE7hQ0xVsk01dePT8Gyl+ZzjKlPhD4CBzQJx8U5K+HL4vf+tAy2IyFHqgOLz7V9 4au6EfidxkbYOBa8mB01sV8TLc2+RaUbM7pcXwv9/41bu0u0LJ/X52M090WluCeG5pN2 3InXvbCpLGcWUlhj0jS8I53HT9I879VPJSOehlH9ERkRAOVvAEjSojNUOD8EUYXVjquN BnmnvLeF/HzvaFH9VAPlD1L0pzsFab6SabwqVfkTONYS0sANTpLe+QFACxNVzG88wAE7 EQjd9w37QGfEdTrng5xsesLYMOJbBaF8anaWikTSAOPEshw8p5gbTWutIohked+ICaOJ 3bNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679850061; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bwW6oUpD5h8cj23E/vde86PKPUzMAEIVBwgEWSiD3uA=; b=akeffW4I8DzwCKRBTh0qAhyIWY7p1RlTVuVrkwxHHaOO6cpMT5W2w6l0D30vRm3qp/ OriMWgUBOMRgpIGCowZgUrNwMdKbJ3jONSTfek6s084km2BvOCHW6Ez5gn7FUQAwIu+S b/RsvPt13khpc2Anee8RwcMDfuP2WYr+RMUXiW0SsEVITfACjPVpWOKCtCUIVkfUw8ud 9Mxdjmrglwt0ZiqDrV/w7LoDOSLRhU1JwoQg157yTjgMnQOmq8ZWbTI5Za2JSX05g/64 S23Q7qNIJdMbzV7/zICWM/UbljZ3uIsTYOAFauzDBdbIcrIl79T+JP8iD3B+S0DlOT2c zK+Q== X-Gm-Message-State: AAQBX9fQGVg+zHoH4CPdTnRZi1bH8mQHxCcRl2rKizOYHRz/YPLrGx5X OjeQ8sEvo87UWWiNdSmocCtnRvH9BMhz72mBkTE= X-Google-Smtp-Source: AKy350aAoyrIBElGGuBqNIPvfAlr7j+pHNViwWZzsB345Jd6yv4nK48yXBcBagk0NV05PxljKZpuCg== X-Received: by 2002:a17:906:578c:b0:88f:a236:69e6 with SMTP id k12-20020a170906578c00b0088fa23669e6mr9545337ejq.7.1679850061356; Sun, 26 Mar 2023 10:01:01 -0700 (PDT) Received: from localhost (host-213-179-129-39.customer.m-online.net. [213.179.129.39]) by smtp.gmail.com with ESMTPSA id m27-20020a170906259b00b0093a3a663ebdsm7941215ejb.154.2023.03.26.10.01.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Mar 2023 10:01:00 -0700 (PDT) From: Jiri Pirko To: netdev@vger.kernel.org, arkadiusz.kubalewski@intel.com, vadim.fedorenko@linux.dev, vadfed@meta.com Cc: kuba@kernel.org, jonathan.lemon@gmail.com, pabeni@redhat.com, poros@redhat.com, mschmidt@redhat.com, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org Subject: [patch dpll-rfc 5/7] dpll: export dpll_pin_notify() Date: Sun, 26 Mar 2023 19:00:50 +0200 Message-Id: <20230326170052.2065791-6-jiri@resnulli.us> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230326170052.2065791-1-jiri@resnulli.us> References: <20230312022807.278528-1-vadfed@meta.com> <20230326170052.2065791-1-jiri@resnulli.us> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC From: Jiri Pirko Export dpll_pin_notify() as it is needed to be called from drivers. Signed-off-by: Jiri Pirko --- drivers/dpll/dpll_netlink.c | 1 + drivers/dpll/dpll_netlink.h | 3 --- include/linux/dpll.h | 4 ++++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index 125dc3c7e643..cd77881ee1ec 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -1056,6 +1056,7 @@ int dpll_pin_notify(struct dpll_device *dpll, struct dpll_pin *pin, { return dpll_send_event_change(dpll, pin, NULL, attr); } +EXPORT_SYMBOL_GPL(dpll_pin_notify); int dpll_pin_parent_notify(struct dpll_device *dpll, struct dpll_pin *pin, struct dpll_pin *parent, enum dplla attr) diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h index 072efa10f0e6..952e0335595e 100644 --- a/drivers/dpll/dpll_netlink.h +++ b/drivers/dpll/dpll_netlink.h @@ -20,9 +20,6 @@ int dpll_notify_device_create(struct dpll_device *dpll); */ int dpll_notify_device_delete(struct dpll_device *dpll); -int dpll_pin_notify(struct dpll_device *dpll, struct dpll_pin *pin, - enum dplla attr); - int dpll_pin_parent_notify(struct dpll_device *dpll, struct dpll_pin *pin, struct dpll_pin *parent, enum dplla attr); diff --git a/include/linux/dpll.h b/include/linux/dpll.h index be5717e1da99..562b9b7bd001 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -287,5 +287,9 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, */ int dpll_device_notify(struct dpll_device *dpll, enum dplla attr); +int dpll_pin_notify(struct dpll_device *dpll, struct dpll_pin *pin, + enum dplla attr); + + #endif From patchwork Sun Mar 26 17:00:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 13188369 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 314ECC761AF for ; Sun, 26 Mar 2023 17:01:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232533AbjCZRBU (ORCPT ); Sun, 26 Mar 2023 13:01:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232484AbjCZRBI (ORCPT ); Sun, 26 Mar 2023 13:01:08 -0400 Received: from mail-ed1-x52e.google.com (mail-ed1-x52e.google.com [IPv6:2a00:1450:4864:20::52e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 97B586A53 for ; Sun, 26 Mar 2023 10:01:04 -0700 (PDT) Received: by mail-ed1-x52e.google.com with SMTP id er18so15368924edb.9 for ; Sun, 26 Mar 2023 10:01:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=resnulli-us.20210112.gappssmtp.com; s=20210112; t=1679850063; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wVw8mNIYgBevA5WAbZRzEVceVuQ8FZJe/xIyNmE1HIg=; b=dtMeZISBFJD4Y1iX25nk1jG3zfNA4pZZRckmOUNi23elyCG5DI+bQgTtsvKVznEEt8 2YFMS1wYiK0bU9qQSUxvKODsdkfNjKXS12+MK9y+boBWd7iqfUvzApiPSYzcTxxgBkop TijJzXRK7I4WsE0YZwUTnpOdFkXv/Mx4Dtrs6Faj2s7igQ3O1WhzwKLE2Bu33WIo5SqW 7sy4xS2Gdb94ns/y9Mnt2ApBtzDR9qOutkzcJ6m1h4R6PZ35zOOlXA0aDnXGsKb+5DYD hpweIiHvFaIrs43D+y6A3cH4/AY62XkpX/oROBJmdtrbnVlbc0N4R0QNpBozsG0i59b+ Dq5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679850063; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wVw8mNIYgBevA5WAbZRzEVceVuQ8FZJe/xIyNmE1HIg=; b=qtBryKx97I8Y1FH8jsJUNtwGgXZVqS0VMdfzgdVCkgSIvxfqnaDClZMf4pi9vYqdHv E0JvAXxpaFu+BeV7BoXV3hJg4UGUXs6U6v7AFLXyzvSHMF3U/xunzFmMPZJ5OOKuYaEE dfgY+gXGklJLbUHbFu73jb5tQEBdGMwouUL+r4aXEhI1lIiPhISqH28LEbD9/JeUIwqE KW1DBmyTXthXH0ypK0hiLID++mWuWibhG4P8O7RfYkfGhpyyNUTbQJUhQQYYiY+PjVEB YzBsc/A4DyJZDfniIy/zwWJX4gYxb/cES+793qmdjnHzNfi92Yln2MsbevmO6Sr5QLmF 7N4w== X-Gm-Message-State: AAQBX9dowAxMHn+E1Vu+z9cJq3Ufkgqw/lHcrDA8RWrvhsbHp5Bby0At ZkIbiLGNKQ7O74ZsbGWHBg7MsrknqwcTIxDq9CI= X-Google-Smtp-Source: AKy350bjFaVpgOcNLLdrsugeYmhEfzcs6Xab2vP4Fh1lmBuaxXVpDg02V36R1QWwVKeawousjXcGJQ== X-Received: by 2002:a17:907:d22:b0:932:5b67:6dee with SMTP id gn34-20020a1709070d2200b009325b676deemr10652498ejc.27.1679850062898; Sun, 26 Mar 2023 10:01:02 -0700 (PDT) Received: from localhost (host-213-179-129-39.customer.m-online.net. [213.179.129.39]) by smtp.gmail.com with ESMTPSA id c16-20020a170906925000b009327f9a397csm12566473ejx.145.2023.03.26.10.01.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Mar 2023 10:01:02 -0700 (PDT) From: Jiri Pirko To: netdev@vger.kernel.org, arkadiusz.kubalewski@intel.com, vadim.fedorenko@linux.dev, vadfed@meta.com Cc: kuba@kernel.org, jonathan.lemon@gmail.com, pabeni@redhat.com, poros@redhat.com, mschmidt@redhat.com, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org Subject: [patch dpll-rfc 6/7] netdev: expose DPLL pin handle for netdevice Date: Sun, 26 Mar 2023 19:00:51 +0200 Message-Id: <20230326170052.2065791-7-jiri@resnulli.us> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230326170052.2065791-1-jiri@resnulli.us> References: <20230312022807.278528-1-vadfed@meta.com> <20230326170052.2065791-1-jiri@resnulli.us> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Jiri Pirko In case netdevice represents a SyncE port, the user needs to understand the connection between netdevice and associated DPLL pin. There might me multiple netdevices pointing to the same pin, in case of VF/SF implementation. Add a IFLA Netlink attribute to nest the DPLL pin handle, similar to how is is implemented for devlink port. Add a struct dpll_pin pointer to netdev and protect access to it by RTNL. Expose netdev_dpll_pin_set() and netdev_dpll_pin_clear() helpers to the drivers so they can set/clear the DPLL pin relationship to netdev. Note that during the lifetime of struct dpll_pin the handle fields do not change. Therefore it is save to access them lockless. It is drivers responsibility to call netdev_dpll_pin_clear() before dpll_pin_put(). Signed-off-by: Jiri Pirko --- drivers/dpll/dpll_netlink.c | 28 ++++++++++++++++++++++---- include/linux/dpll.h | 20 +++++++++++++++++++ include/linux/netdevice.h | 7 +++++++ include/uapi/linux/if_link.h | 2 ++ net/core/dev.c | 20 +++++++++++++++++++ net/core/rtnetlink.c | 38 ++++++++++++++++++++++++++++++++++++ 6 files changed, 111 insertions(+), 4 deletions(-) diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index cd77881ee1ec..ac5cbf5a2e19 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -302,6 +302,24 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin, return ret; } +size_t dpll_msg_pin_handle_size(struct dpll_pin *pin) +{ + // TMP- THE HANDLE IS GOING TO CHANGE TO DRIVERNAME/CLOCKID/PIN_INDEX + // LEAVING ORIG HANDLE NOW AS PUT IN THE LAST RFC VERSION + return nla_total_size(4); /* DPLL_A_PIN_IDX */ +} +EXPORT_SYMBOL_GPL(dpll_msg_pin_handle_size); + +int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin) +{ + // TMP- THE HANDLE IS GOING TO CHANGE TO DRIVERNAME/CLOCKID/PIN_INDEX + // LEAVING ORIG HANDLE NOW AS PUT IN THE LAST RFC VERSION + if (nla_put_u32(msg, DPLL_A_PIN_IDX, pin->dev_driver_id)) + return -EMSGSIZE; + return 0; +} +EXPORT_SYMBOL_GPL(dpll_msg_add_pin_handle); + static int dpll_cmd_pin_on_dpll_get(struct sk_buff *msg, struct dpll_pin *pin, struct dpll_device *dpll, @@ -310,8 +328,9 @@ dpll_cmd_pin_on_dpll_get(struct sk_buff *msg, struct dpll_pin *pin, struct dpll_pin_ref *ref; int ret; - if (nla_put_u32(msg, DPLL_A_PIN_IDX, pin->dev_driver_id)) - return -EMSGSIZE; + ret = dpll_msg_add_pin_handle(msg, pin); + if (ret) + return ret; if (nla_put_string(msg, DPLL_A_PIN_DESCRIPTION, pin->prop.description)) return -EMSGSIZE; if (nla_put_u8(msg, DPLL_A_PIN_TYPE, pin->prop.type)) @@ -352,8 +371,9 @@ __dpll_cmd_pin_dump_one(struct sk_buff *msg, struct dpll_pin *pin, struct dpll_pin_ref *ref; int ret; - if (nla_put_u32(msg, DPLL_A_PIN_IDX, pin->dev_driver_id)) - return -EMSGSIZE; + ret = dpll_msg_add_pin_handle(msg, pin); + if (ret) + return ret; if (nla_put_string(msg, DPLL_A_PIN_DESCRIPTION, pin->prop.description)) return -EMSGSIZE; if (nla_put_u8(msg, DPLL_A_PIN_TYPE, pin->prop.type)) diff --git a/include/linux/dpll.h b/include/linux/dpll.h index 562b9b7bd001..f9081e5fc522 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -92,6 +92,26 @@ enum dpll_pin_freq_supp { DPLL_PIN_FREQ_SUPP_MAX = (__DPLL_PIN_FREQ_SUPP_MAX - 1) }; +#if IS_ENABLED(CONFIG_DPLL) + +size_t dpll_msg_pin_handle_size(struct dpll_pin *pin); + +int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin); + +#else + +static inline size_t dpll_msg_pin_handle_size(struct dpll_pin *pin) +{ + return 0; +} + +static inline int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin) +{ + return 0; +} + +#endif + /** * dpll_device_get - find or create dpll_device object * @clock_id: a system unique number for a device diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7621c512765f..79a90b52ee77 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #ifdef CONFIG_DCB @@ -2403,6 +2404,10 @@ struct net_device { struct rtnl_hw_stats64 *offload_xstats_l3; struct devlink_port *devlink_port; + +#if IS_ENABLED(CONFIG_DPLL) + struct dpll_pin *dpll_pin; +#endif }; #define to_net_dev(d) container_of(d, struct net_device, dev) @@ -3939,6 +3944,8 @@ int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name); int dev_get_port_parent_id(struct net_device *dev, struct netdev_phys_item_id *ppid, bool recurse); 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); 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/if_link.h b/include/uapi/linux/if_link.h index 57ceb788250f..280573f723da 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -377,6 +377,8 @@ enum { IFLA_GSO_IPV4_MAX_SIZE, IFLA_GRO_IPV4_MAX_SIZE, + IFLA_DPLL_PIN, + __IFLA_MAX }; diff --git a/net/core/dev.c b/net/core/dev.c index c7853192563d..cf9f61cf33e2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -8949,6 +8949,26 @@ bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b) } EXPORT_SYMBOL(netdev_port_same_parent_id); +static void netdev_dpll_pin_assign(struct net_device *dev, struct dpll_pin *dpll_pin) +{ + rtnl_lock(); + dev->dpll_pin = dpll_pin; + rtnl_unlock(); +} + +void netdev_dpll_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin) +{ + WARN_ON(!dpll_pin); + netdev_dpll_pin_assign(dev, dpll_pin); +} +EXPORT_SYMBOL(netdev_dpll_pin_set); + +void netdev_dpll_pin_clear(struct net_device *dev) +{ + netdev_dpll_pin_assign(dev, NULL); +} +EXPORT_SYMBOL(netdev_dpll_pin_clear); + /** * dev_change_proto_down - set carrier according to proto_down. * diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b7b1661d0d56..e29aed39625d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1052,6 +1052,16 @@ static size_t rtnl_devlink_port_size(const struct net_device *dev) return size; } +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); + + return size; +} + static noinline size_t if_nlmsg_size(const struct net_device *dev, u32 ext_filter_mask) { @@ -1108,6 +1118,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + rtnl_prop_list_size(dev) + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */ + rtnl_devlink_port_size(dev) + + rtnl_dpll_pin_size(dev) + 0; } @@ -1769,6 +1780,30 @@ static int rtnl_fill_devlink_port(struct sk_buff *skb, return ret; } +static int rtnl_fill_dpll_pin(struct sk_buff *skb, + const struct net_device *dev) +{ + struct nlattr *dpll_pin_nest; + int ret; + + dpll_pin_nest = nla_nest_start(skb, IFLA_DPLL_PIN); + 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; + } + + nla_nest_end(skb, dpll_pin_nest); + return 0; + +nest_cancel: + nla_nest_cancel(skb, dpll_pin_nest); + return ret; +} + static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, struct net *src_net, int type, u32 pid, u32 seq, u32 change, @@ -1911,6 +1946,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, if (rtnl_fill_devlink_port(skb, dev)) goto nla_put_failure; + if (rtnl_fill_dpll_pin(skb, dev)) + goto nla_put_failure; + nlmsg_end(skb, nlh); return 0; From patchwork Sun Mar 26 17:00:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 13188370 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7CFA9C6FD1C for ; Sun, 26 Mar 2023 17:01:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232492AbjCZRBW (ORCPT ); Sun, 26 Mar 2023 13:01:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48278 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232489AbjCZRBI (ORCPT ); Sun, 26 Mar 2023 13:01:08 -0400 Received: from mail-ed1-x52a.google.com (mail-ed1-x52a.google.com [IPv6:2a00:1450:4864:20::52a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 357395FFD for ; Sun, 26 Mar 2023 10:01:05 -0700 (PDT) Received: by mail-ed1-x52a.google.com with SMTP id t10so26489160edd.12 for ; Sun, 26 Mar 2023 10:01:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=resnulli-us.20210112.gappssmtp.com; s=20210112; t=1679850064; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=nZXb2+qygNbjzLHXmsrj7zi5WUAuLCHh86RQvypcKFM=; b=q+sAgEA1tWrHayteteZXKjSxrxezbir3t+wBsdKGIAoBkOoTMMm3pKi4jRWImIKU6d bDWlamdhWgWdF4eOQ8L4wfw3AWzNIkqQgEGSSr/Xw/qFLeKiAXBUAT3UWFokg2kEPgID +vDHQ85sdPBUc6WAaUVeF82R2q9oASw3ss9vKFmdSQpkwULsDiweGL5xf8IhyveZahs0 wkYhuyX53dLvGvH6tQuZkKAEzMqAvOQ2htlJh4FPW6sAHkX+B3ENVx054nljW7s0f3Hl snM/ZmqY8BY/3+a8eL1TU3Puf5CS9P+mbJX9dGDF6H2oC3OjUk9AQMmUkienURbejifw bisg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679850064; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=nZXb2+qygNbjzLHXmsrj7zi5WUAuLCHh86RQvypcKFM=; b=yTjbRzEtmrlkK1gUfSdhHZyHm8n12bmCPceajdbiiSuM9hei5bP0+a0/qOtSd1R8zb BDi9cvPPVfCU56OKy3zTG2aXrusaO3OiKC9LjJykKITo/7L0eOWN4Ht5vDOEYH99PNq8 xTBayjVnwwyIo7g2CTVSmHEV71mFyILYYddxfDS4j4qCygQl88oioJEtmy232qvf8wC5 Lwb3Ui8EL0iXjZtt31Ay9KL8BOTrkxIr9nYMl8xjyt1Y1Zzwy5RpopwiywSt+GS66g9M 3jZZ7QPwWWuvp551I3HH0CXWe/fg9xZ6yprb9gpOkwWxf5/w1EZXw3PtACUHxyBNhhe9 L6+A== X-Gm-Message-State: AAQBX9dQ/ZuwCJH9vjBJP77OfHWoBtXW+84xZc4EaV9SMREpy70/bhwV UM1CMerQQygO2MEDEvUMYCDIZyqmkbh1TsVipbw= X-Google-Smtp-Source: AKy350Y8KqmSx4SJO/HdBUgJZAtE4an2+rgY5TSAdQyfaVzCo5KUni7h4KHnZ1X3U+S7dr1V3iHAuA== X-Received: by 2002:a17:906:d8d0:b0:932:3688:ae81 with SMTP id re16-20020a170906d8d000b009323688ae81mr9369494ejb.9.1679850064490; Sun, 26 Mar 2023 10:01:04 -0700 (PDT) Received: from localhost (host-213-179-129-39.customer.m-online.net. [213.179.129.39]) by smtp.gmail.com with ESMTPSA id u23-20020a170906409700b009334a6ef3e8sm11132772ejj.141.2023.03.26.10.01.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Mar 2023 10:01:03 -0700 (PDT) From: Jiri Pirko To: netdev@vger.kernel.org, arkadiusz.kubalewski@intel.com, vadim.fedorenko@linux.dev, vadfed@meta.com Cc: kuba@kernel.org, jonathan.lemon@gmail.com, pabeni@redhat.com, poros@redhat.com, mschmidt@redhat.com, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org Subject: [patch dpll-rfc 7/7] mlx5: Implement SyncE support using DPLL infrastructure Date: Sun, 26 Mar 2023 19:00:52 +0200 Message-Id: <20230326170052.2065791-8-jiri@resnulli.us> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230326170052.2065791-1-jiri@resnulli.us> References: <20230312022807.278528-1-vadfed@meta.com> <20230326170052.2065791-1-jiri@resnulli.us> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Jiri Pirko Implement SyncE support using newly introduced DPLL support. Make sure that each PFs/VFs/SFs probed with appropriate capability will spawn a dpll auxiliary device and register appropriate dpll device and pin instances. Signed-off-by: Jiri Pirko --- .../net/ethernet/mellanox/mlx5/core/Kconfig | 8 + .../net/ethernet/mellanox/mlx5/core/Makefile | 3 + drivers/net/ethernet/mellanox/mlx5/core/dev.c | 17 + .../net/ethernet/mellanox/mlx5/core/dpll.c | 429 ++++++++++++++++++ include/linux/mlx5/driver.h | 2 + include/linux/mlx5/mlx5_ifc.h | 59 ++- 6 files changed, 517 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/dpll.c diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig index bb1d7b039a7e..15a48d376eb3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig @@ -188,3 +188,11 @@ config MLX5_SF_MANAGER port is managed through devlink. A subfunction supports RDMA, netdevice and vdpa device. It is similar to a SRIOV VF but it doesn't require SRIOV support. + +config MLX5_DPLL + tristate "Mellanox 5th generation network adapters (ConnectX series) DPLL support" + depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE + select DPLL + help + DPLL support in Mellanox Technologies ConnectX NICs. + diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 6c2f1d4a58ab..c2c864aba1f5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -123,3 +123,6 @@ mlx5_core-$(CONFIG_MLX5_SF) += sf/vhca_event.o sf/dev/dev.o sf/dev/driver.o irq_ # SF manager # mlx5_core-$(CONFIG_MLX5_SF_MANAGER) += sf/cmd.o sf/hw_table.o sf/devlink.o + +obj-$(CONFIG_MLX5_DPLL) += mlx5_dpll.o +mlx5_dpll-y := dpll.o diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c index 445fe30c3d0b..7520e5987cb2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c @@ -227,6 +227,19 @@ static bool is_ib_enabled(struct mlx5_core_dev *dev) return err ? false : val.vbool; } +static bool is_dpll_supported(struct mlx5_core_dev *dev) +{ + if (!IS_ENABLED(CONFIG_MLX5_DPLL)) + return false; + + if (!MLX5_CAP_MCAM_REG2(dev, synce_registers)) { + mlx5_core_warn(dev, "Missing SyncE capability\n"); + return false; + } + + return true; +} + enum { MLX5_INTERFACE_PROTOCOL_ETH, MLX5_INTERFACE_PROTOCOL_ETH_REP, @@ -236,6 +249,8 @@ enum { MLX5_INTERFACE_PROTOCOL_MPIB, MLX5_INTERFACE_PROTOCOL_VNET, + + MLX5_INTERFACE_PROTOCOL_DPLL, }; static const struct mlx5_adev_device { @@ -258,6 +273,8 @@ static const struct mlx5_adev_device { .is_supported = &is_ib_rep_supported }, [MLX5_INTERFACE_PROTOCOL_MPIB] = { .suffix = "multiport", .is_supported = &is_mp_supported }, + [MLX5_INTERFACE_PROTOCOL_DPLL] = { .suffix = "dpll", + .is_supported = &is_dpll_supported }, }; int mlx5_adev_idx_alloc(void) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c new file mode 100644 index 000000000000..afb092fcbcae --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c @@ -0,0 +1,429 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ + +#include +#include + +// POSSIBLE DPLL API EXTENSIONS: +// 1) Expose clock quality: MSECQ->local_ssm_code, MSECQ->local_enhanced_ssm_code +// Proposed enum: +// QL_DNU, +// QL_EEC1, +// QL_eEEC, +// QL_SSU_B, +// QL_SSU_A, +// QL_PRC, +// QL_ePRC, +// QL_PRTC, +// QL_ePRTC, +// 2) Expose possibility to do holdover: MSEES->ho_acq +// 3) DPLL Implementation hw-speficic values (debug?): MSEES->oper_freq_measure + +/* This structure represents a reference to DPLL, one is created + * per mdev instance. + */ +struct mlx5_dpll { + struct dpll_device *dpll; + struct dpll_pin *dpll_pin; + struct mlx5_core_dev *mdev; + struct workqueue_struct *wq; + struct delayed_work work; + struct { + bool valid; + enum dpll_lock_status lock_status; + enum dpll_pin_state pin_state; + } last; + struct notifier_block mdev_nb; + struct net_device *tracking_netdev; +}; + +static int mlx5_dpll_clock_id_get(struct mlx5_core_dev *mdev, u64 *clock_id) +{ + u32 out[MLX5_ST_SZ_DW(msecq_reg)] = {}; + u32 in[MLX5_ST_SZ_DW(msecq_reg)] = {}; + int err; + + err = mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), + MLX5_REG_MSECQ, 0, 0); + if (err) + return err; + *clock_id = MLX5_GET64(msecq_reg, out, local_clock_identity); + return 0; +} + +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) +{ + u32 out[MLX5_ST_SZ_DW(msees_reg)] = {}; + u32 in[MLX5_ST_SZ_DW(msees_reg)] = {}; + int err; + + MLX5_SET(msees_reg, in, local_port, 1); + err = mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), + MLX5_REG_MSEES, 0, 0); + if (err) + return err; + if (admin_status) + *admin_status = MLX5_GET(msees_reg, out, admin_status); + if (oper_status) + *oper_status = MLX5_GET(msees_reg, out, oper_status); + return 0; +} + +static int +mlx5_dpll_synce_status_set(struct mlx5_core_dev *mdev, + enum mlx5_msees_admin_status admin_status) +{ + u32 out[MLX5_ST_SZ_DW(msees_reg)] = {}; + u32 in[MLX5_ST_SZ_DW(msees_reg)] = {}; + + MLX5_SET(msees_reg, in, local_port, 1); + MLX5_SET(msees_reg, in, field_select, + MLX5_MSEES_FIELD_SELECT_ENABLE | + MLX5_MSEES_FIELD_SELECT_ADMIN_STATUS); + MLX5_SET(msees_reg, in, admin_status, admin_status); + MLX5_SET(msees_reg, in, admin_freq_measure, + admin_status == MLX5_MSEES_ADMIN_STATUS_TRACK); + return mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), + MLX5_REG_MSEES, 0, 0); +} + +static enum dpll_lock_status +mlx5_dpll_lock_status_from_oper_status(enum mlx5_msees_oper_status oper_status) +{ + switch (oper_status) { + case MLX5_MSEES_OPER_STATUS_SELF_TRACK: + fallthrough; + case MLX5_MSEES_OPER_STATUS_OTHER_TRACK: + return DPLL_LOCK_STATUS_LOCKED; + case MLX5_MSEES_OPER_STATUS_HOLDOVER: + return DPLL_LOCK_STATUS_HOLDOVER; + default: + return DPLL_LOCK_STATUS_UNLOCKED; + } +} + +static int mlx5_dpll_device_lock_status_get(const struct dpll_device *dpll, + enum dpll_lock_status *status, + struct netlink_ext_ack *extack) +{ + struct mlx5_dpll *mdpll = dpll_priv(dpll); + enum mlx5_msees_oper_status oper_status; + int err; + + err = mlx5_dpll_synce_status_get(mdpll->mdev, NULL, &oper_status); + if (err) + return err; + + *status = mlx5_dpll_lock_status_from_oper_status(oper_status); + return 0; +} + +static int mlx5_dpll_device_mode_get(const struct dpll_device *dpll, + u32 *mode, struct netlink_ext_ack *extack) +{ + *mode = DPLL_MODE_MANUAL; + return 0; +} + +static bool mlx5_dpll_device_mode_supported(const struct dpll_device *dpll, + enum dpll_mode mode, + struct netlink_ext_ack *extack) +{ + return mode == DPLL_MODE_MANUAL; +} + +static const struct dpll_device_ops mlx5_dpll_device_ops = { + .lock_status_get = mlx5_dpll_device_lock_status_get, + .mode_get = mlx5_dpll_device_mode_get, + .mode_supported = mlx5_dpll_device_mode_supported, +}; + +static int mlx5_dpll_pin_direction_get(const struct dpll_pin *pin, + const struct dpll_device *dpll, + enum dpll_pin_direction *direction, + struct netlink_ext_ack *extack) +{ + *direction = DPLL_PIN_DIRECTION_SOURCE; + return 0; +} + +static enum dpll_pin_state +mlx5_dpll_pin_state_from_admin_status(enum mlx5_msees_admin_status admin_status) +{ + return admin_status == MLX5_MSEES_ADMIN_STATUS_TRACK ? + DPLL_PIN_STATE_CONNECTED : DPLL_PIN_STATE_DISCONNECTED; +} + +static int mlx5_dpll_state_on_dpll_get(const struct dpll_pin *pin, + const struct dpll_device *dpll, + enum dpll_pin_state *state, + struct netlink_ext_ack *extack) +{ + struct mlx5_dpll *mdpll = dpll_pin_on_dpll_priv(dpll, pin); + enum mlx5_msees_admin_status admin_status; + int err; + + err = mlx5_dpll_synce_status_get(mdpll->mdev, &admin_status, NULL); + if (err) + return err; + *state = mlx5_dpll_pin_state_from_admin_status(admin_status); + return 0; +} + +static int mlx5_dpll_state_on_dpll_set(const struct dpll_pin *pin, + const struct dpll_device *dpll, + enum dpll_pin_state state, + struct netlink_ext_ack *extack) +{ + struct mlx5_dpll *mdpll = dpll_pin_on_dpll_priv(dpll, pin); + + return mlx5_dpll_synce_status_set(mdpll->mdev, + state == DPLL_PIN_STATE_CONNECTED ? + MLX5_MSEES_ADMIN_STATUS_TRACK : + MLX5_MSEES_ADMIN_STATUS_FREE_RUNNING); +} + +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, +}; + +static const struct dpll_pin_properties mlx5_dpll_pin_properties = { + .description = "n/a", + .type = DPLL_PIN_TYPE_SYNCE_ETH_PORT, + .capabilities = DPLL_PIN_CAPS_STATE_CAN_CHANGE, +}; + +#define MLX5_DPLL_PERIODIC_WORK_INTERVAL 500 /* ms */ + +static void mlx5_dpll_periodic_work_queue(struct mlx5_dpll *mdpll) +{ + queue_delayed_work(mdpll->wq, &mdpll->work, + msecs_to_jiffies(MLX5_DPLL_PERIODIC_WORK_INTERVAL)); +} + +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; + enum dpll_lock_status lock_status; + enum dpll_pin_state pin_state, + + err = mlx5_dpll_synce_status_get(mdpll->mdev, &admin_status, + &oper_status); + if (err) + goto err_out; + lock_status = mlx5_dpll_lock_status_from_oper_status(oper_status); + pin_state = mlx5_dpll_pin_state_from_admin_status(admin_status); + + if (!mdpll->last.valid) + goto invalid_out; + + if (mdpll->last.lock_status != lock_status) + dpll_device_notify(mdpll->dpll, DPLL_A_LOCK_STATUS); + if (mdpll->last.pin_state != pin_state) + dpll_pin_notify(mdpll->dpll, mdpll->dpll_pin, DPLL_A_PIN_STATE); + +invalid_out: + mdpll->last.lock_status = lock_status; + mdpll->last.pin_state = pin_state; + mdpll->last.valid = true; +err_out: + mlx5_dpll_periodic_work_queue(mdpll); +} + +static void mlx5_dpll_netdev_dpll_pin_set(struct mlx5_dpll *mdpll, + struct net_device *netdev) +{ + if (mdpll->tracking_netdev) + return; + netdev_dpll_pin_set(netdev, mdpll->dpll_pin); + mdpll->tracking_netdev = netdev; +} + +static void mlx5_dpll_netdev_dpll_pin_clear(struct mlx5_dpll *mdpll) +{ + if (!mdpll->tracking_netdev) + return; + netdev_dpll_pin_clear(mdpll->tracking_netdev); + mdpll->tracking_netdev = NULL; +} + +static int mlx5_dpll_mdev_notifier_event(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct mlx5_dpll *mdpll = container_of(nb, struct mlx5_dpll, mdev_nb); + struct net_device *netdev = data; + + switch (event) { + case MLX5_DRIVER_EVENT_UPLINK_NETDEV: + if (netdev) + mlx5_dpll_netdev_dpll_pin_set(mdpll, netdev); + else + mlx5_dpll_netdev_dpll_pin_clear(mdpll); + break; + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + +static void mlx5_dpll_mdev_netdev_track(struct mlx5_dpll *mdpll, + struct mlx5_core_dev *mdev) +{ + mdpll->mdev_nb.notifier_call = mlx5_dpll_mdev_notifier_event; + mlx5_blocking_notifier_register(mdev, &mdpll->mdev_nb); + mlx5_core_uplink_netdev_event_replay(mdev); +} + +static void mlx5_dpll_mdev_netdev_untrack(struct mlx5_dpll *mdpll, + struct mlx5_core_dev *mdev) +{ + mlx5_blocking_notifier_unregister(mdev, &mdpll->mdev_nb); + mlx5_dpll_netdev_dpll_pin_clear(mdpll); +} + +static int mlx5_dpll_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); + struct mlx5_core_dev *mdev = edev->mdev; + struct mlx5_dpll *mdpll; + u64 clock_id; + int err; + + err = mlx5_dpll_synce_status_set(mdev, + MLX5_MSEES_ADMIN_STATUS_FREE_RUNNING); + if (err) + return err; + + err = mlx5_dpll_clock_id_get(mdev, &clock_id); + if (err) + return err; + + mdpll = kzalloc(sizeof(*mdpll), GFP_KERNEL); + if (!mdpll) + return -ENOMEM; + mdpll->mdev = mdev; + auxiliary_set_drvdata(adev, mdpll); + + /* Multiple mdev instances might share one DPLL device. */ + mdpll->dpll = dpll_device_get(clock_id, 0, DPLL_TYPE_EEC, THIS_MODULE); + if (IS_ERR(mdpll->dpll)) { + err = PTR_ERR(mdpll->dpll); + goto err_free_mdpll; + } + + err = dpll_device_register(mdpll->dpll, &mlx5_dpll_device_ops, + mdpll, &adev->dev); + if (err) + goto err_put_dpll_device; + + /* Multiple mdev instances might share one DPLL pin. */ + mdpll->dpll_pin = dpll_pin_get(clock_id, mlx5_get_dev_index(mdev), + THIS_MODULE, &mlx5_dpll_pin_properties); + if (IS_ERR(mdpll->dpll_pin)) { + err = PTR_ERR(mdpll->dpll_pin); + goto err_unregister_dpll_device; + } + + err = dpll_pin_register(mdpll->dpll, mdpll->dpll_pin, + &mlx5_dpll_pins_ops, mdpll, NULL); + if (err) + goto err_put_dpll_pin; + + mdpll->wq = create_singlethread_workqueue("mlx5_dpll"); + if (!mdpll->wq) { + err = -ENOMEM; + goto err_unregister_dpll_pin; + } + + mlx5_dpll_mdev_netdev_track(mdpll, mdev); + + INIT_DELAYED_WORK(&mdpll->work, &mlx5_dpll_periodic_work); + mlx5_dpll_periodic_work_queue(mdpll); + + return 0; + +err_unregister_dpll_pin: + dpll_pin_unregister(mdpll->dpll, mdpll->dpll_pin, + &mlx5_dpll_pins_ops, mdpll); +err_put_dpll_pin: + dpll_pin_put(mdpll->dpll_pin); +err_unregister_dpll_device: + dpll_device_unregister(mdpll->dpll, &mlx5_dpll_device_ops, mdpll); +err_put_dpll_device: + dpll_device_put(mdpll->dpll); +err_free_mdpll: + kfree(mdpll); + return err; +} + +static void mlx5_dpll_remove(struct auxiliary_device *adev) +{ + struct mlx5_dpll *mdpll = auxiliary_get_drvdata(adev); + struct mlx5_core_dev *mdev = mdpll->mdev; + + cancel_delayed_work(&mdpll->work); + mlx5_dpll_mdev_netdev_untrack(mdpll, mdev); + destroy_workqueue(mdpll->wq); + dpll_pin_unregister(mdpll->dpll, mdpll->dpll_pin, + &mlx5_dpll_pins_ops, mdpll); + dpll_pin_put(mdpll->dpll_pin); + dpll_device_unregister(mdpll->dpll, &mlx5_dpll_device_ops, mdpll); + dpll_device_put(mdpll->dpll); + kfree(mdpll); + + mlx5_dpll_synce_status_set(mdev, + MLX5_MSEES_ADMIN_STATUS_FREE_RUNNING); +} + +static int mlx5_dpll_suspend(struct auxiliary_device *adev, pm_message_t state) +{ + return 0; +} + +static int mlx5_dpll_resume(struct auxiliary_device *adev) +{ + return 0; +} + +static const struct auxiliary_device_id mlx5_dpll_id_table[] = { + { .name = MLX5_ADEV_NAME ".dpll", }, + {}, +}; + +MODULE_DEVICE_TABLE(auxiliary, mlx5_dpll_id_table); + +static struct auxiliary_driver mlx5_dpll_driver = { + .name = "dpll", + .probe = mlx5_dpll_probe, + .remove = mlx5_dpll_remove, + .suspend = mlx5_dpll_suspend, + .resume = mlx5_dpll_resume, + .id_table = mlx5_dpll_id_table, +}; + +static int __init mlx5_dpll_init(void) +{ + return auxiliary_driver_register(&mlx5_dpll_driver); +} + +static void __exit mlx5_dpll_exit(void) +{ + auxiliary_driver_unregister(&mlx5_dpll_driver); +} + +module_init(mlx5_dpll_init); +module_exit(mlx5_dpll_exit); + +MODULE_AUTHOR("Jiri Pirko "); +MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) DPLL driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 7a898113b6b7..3cfa30b86878 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -154,6 +154,8 @@ enum { MLX5_REG_MCC = 0x9062, MLX5_REG_MCDA = 0x9063, MLX5_REG_MCAM = 0x907f, + MLX5_REG_MSECQ = 0x9155, + MLX5_REG_MSEES = 0x9156, MLX5_REG_MIRC = 0x9162, MLX5_REG_SBCAM = 0xB01F, MLX5_REG_RESOURCE_DUMP = 0xC000, diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index e47d6c58da35..6ce11b43bf39 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -10143,7 +10143,9 @@ struct mlx5_ifc_mcam_access_reg_bits2 { u8 mirc[0x1]; u8 regs_97_to_96[0x2]; - u8 regs_95_to_64[0x20]; + u8 regs_95_to_87[0x09]; + u8 synce_registers[0x2]; + u8 regs_84_to_64[0x15]; u8 regs_63_to_32[0x20]; @@ -12505,4 +12507,59 @@ struct mlx5_ifc_modify_page_track_obj_in_bits { struct mlx5_ifc_page_track_bits obj_context; }; +struct mlx5_ifc_msecq_reg_bits { + u8 reserved_at_0[0x20]; + + u8 reserved_at_20[0x12]; + u8 network_option[0x2]; + u8 local_ssm_code[0x4]; + u8 local_enhanced_ssm_code[0x8]; + + u8 local_clock_identity[0x40]; + + u8 reserved_at_80[0x180]; +}; + +enum { + MLX5_MSEES_FIELD_SELECT_ENABLE = BIT(0), + MLX5_MSEES_FIELD_SELECT_ADMIN_STATUS = BIT(1), + MLX5_MSEES_FIELD_SELECT_ADMIN_FREQ_MEASURE = BIT(2), +}; + +enum mlx5_msees_admin_status { + MLX5_MSEES_ADMIN_STATUS_FREE_RUNNING = 0x0, + MLX5_MSEES_ADMIN_STATUS_TRACK = 0x1, +}; + +enum mlx5_msees_oper_status { + MLX5_MSEES_OPER_STATUS_FREE_RUNNING = 0x0, + MLX5_MSEES_OPER_STATUS_SELF_TRACK = 0x1, + MLX5_MSEES_OPER_STATUS_OTHER_TRACK = 0x2, + MLX5_MSEES_OPER_STATUS_HOLDOVER = 0x3, + MLX5_MSEES_OPER_STATUS_FAIL_HOLDOVER = 0x4, + MLX5_MSEES_OPER_STATUS_FAIL_FREE_RUNNING = 0x5, +}; + +struct mlx5_ifc_msees_reg_bits { + u8 reserved_at_0[0x8]; + u8 local_port[0x8]; + u8 pnat[0x2]; + u8 lp_msb[0x2]; + u8 reserved_at_14[0xc]; + + u8 field_select[0x20]; + + u8 admin_status[0x4]; + u8 oper_status[0x4]; + u8 ho_acq[0x1]; + u8 reserved_at_49[0xc]; + u8 admin_freq_measure[0x1]; + u8 oper_freq_measure[0x1]; + u8 failure_reason[0x9]; + + u8 frequency_diff[0x20]; + + u8 reserved_at_80[0x180]; +}; + #endif /* MLX5_IFC_H */