From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 40997C04AB6 for ; Fri, 31 May 2019 05:56:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F0DC526424 for ; Fri, 31 May 2019 05:56:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DS24WnvK" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726181AbfEaF4p (ORCPT ); Fri, 31 May 2019 01:56:45 -0400 Received: from mail-pl1-f193.google.com ([209.85.214.193]:34293 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726773AbfEaF4e (ORCPT ); Fri, 31 May 2019 01:56:34 -0400 Received: by mail-pl1-f193.google.com with SMTP id w7so3540776plz.1; Thu, 30 May 2019 22:56:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Tc/JHyCsL6fQWc3tAzhFAYz6S2VbN73H6VZtWV7nMd0=; b=DS24WnvKRJC026tOdjqL79HjRXECwQsJ/uz9oKVUVFELejn8p8veA4gTpnCiciuL34 NbQEuwt6wJwdpN7zUUUk20yjs+ifg/KFezSKXbuBkhyVsTmKsdofuh82wNZ+vcGRyaGq GdqMy086BraC5LH1cMA4gZ57qDWa5fs1dTzgLNeC6nNpYC7/Zbyo+cvjC3QmNiaLRyCx 2ap5oCP+CBO47ePiChJciVXGE2R4cQltgarsNYWhATo1f79iycUp5q+sJ8mBiT9D100u IQR8r0hknqTD3Ey3nwBSd54XdcHe5/nc7HQdp6VDA0cKVzJloC0A0F2abvUe722N+ZMV YhTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Tc/JHyCsL6fQWc3tAzhFAYz6S2VbN73H6VZtWV7nMd0=; b=VmsoauYT+EXxLRxBiXXmvP3YpaZuYsWWAwkJ7DtcbTTbCxL4/SwtRiul8iJmw5ru7G dicg6fzxHVNBIxqrxQNyKcfGPOQ1B0yBgb/GOYyr+PYHU3y75aNaaxORDLQkj7W3cTyJ qfMwqD7D76WUo43Qc4FQc8XFhUWln/zXj21LbAQiPXJjlbg92YNQoIGTHgMIk3aPeGBE V1CCqJdZxOi47ZX8DtOzRYxGp7lqCD/0p965u6ZhCV1UYBXtAi62IwKN8URKpExZJzpk 3zr/cELibqF/J2csaT9I72qKTUDSIc7KIyE3AIW/Rxkg0YeeTrwLJ3vEjkII0PeC7OWl GNSQ== X-Gm-Message-State: APjAAAWMyiqrAcCixgt0vUe3PAuV/DoBmAT7JI/3qgIMs4a0xzC81rPx ywV9XyTt3gNsYdui4Z8zzVRjsqKV X-Google-Smtp-Source: APXvYqxIZxmlkGrSNq8MzA3qg8dUi/ImXY0NruJ5cEGVwybYrxG6bJMyl0K6JzYH83yGnLpJDzQyBg== X-Received: by 2002:a17:902:8c8f:: with SMTP id t15mr7350851plo.87.1559282192965; Thu, 30 May 2019 22:56:32 -0700 (PDT) Received: from localhost.localdomain (c-73-222-71-142.hsd1.ca.comcast.net. [73.222.71.142]) by smtp.gmail.com with ESMTPSA id u2sm4554184pjv.30.2019.05.30.22.56.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 30 May 2019 22:56:32 -0700 (PDT) From: Richard Cochran To: netdev@vger.kernel.org Cc: David Miller , devicetree@vger.kernel.org, Andrew Lunn , Florian Fainelli , Jacob Keller , Mark Rutland , Miroslav Lichvar , Rob Herring , Willem de Bruijn Subject: [PATCH V5 net-next 3/6] net: Add a layer for non-PHY MII time stamping drivers. Date: Thu, 30 May 2019 22:56:23 -0700 Message-Id: <51c6a6be3d4624ad3eafdd7b9c4e26af14bfc55f.1559281985.git.richardcochran@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org While PHY time stamping drivers can simply attach their interface directly to the PHY instance, stand alone drivers require support in order to manage their services. Non-PHY MII time stamping drivers have a control interface over another bus like I2C, SPI, UART, or via a memory mapped peripheral. The controller device will be associated with one or more time stamping channels, each of which sits snoops in on a MII bus. This patch provides a glue layer that will enable time stamping channels to find their controlling device. Signed-off-by: Richard Cochran --- drivers/net/phy/Makefile | 2 + drivers/net/phy/mii_timestamper.c | 121 ++++++++++++++++++++++++++++++++++++++ include/linux/mii_timestamper.h | 64 ++++++++++++++++++++ net/Kconfig | 7 ++- 4 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 drivers/net/phy/mii_timestamper.c diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index bac339e09042..4f7db9e23456 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -42,6 +42,8 @@ obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o +obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += mii_timestamper.o + obj-$(CONFIG_SFP) += sfp.o sfp-obj-$(CONFIG_SFP) += sfp-bus.o obj-y += $(sfp-obj-y) $(sfp-obj-m) diff --git a/drivers/net/phy/mii_timestamper.c b/drivers/net/phy/mii_timestamper.c new file mode 100644 index 000000000000..bdc9bf8dfce2 --- /dev/null +++ b/drivers/net/phy/mii_timestamper.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Support for generic time stamping devices on MII buses. +// Copyright (C) 2018 Richard Cochran +// + +#include + +static LIST_HEAD(mii_timestamping_devices); +static DEFINE_MUTEX(tstamping_devices_lock); + +struct mii_timestamping_desc { + struct list_head list; + struct mii_timestamping_ctrl *ctrl; + struct device *device; +}; + +/** + * register_mii_tstamp_controller() - registers an MII time stamping device. + * + * @device: The device to be registered. + * @ctrl: Pointer to device's control interface. + * + * Returns zero on success or non-zero on failure. + */ +int register_mii_tstamp_controller(struct device *device, + struct mii_timestamping_ctrl *ctrl) +{ + struct mii_timestamping_desc *desc; + + desc = kzalloc(sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + + INIT_LIST_HEAD(&desc->list); + desc->ctrl = ctrl; + desc->device = device; + + mutex_lock(&tstamping_devices_lock); + list_add_tail(&mii_timestamping_devices, &desc->list); + mutex_unlock(&tstamping_devices_lock); + + return 0; +} + +/** + * unregister_mii_tstamp_controller() - unregisters an MII time stamping device. + * + * @device: A device previously passed to register_mii_tstamp_controller(). + */ +void unregister_mii_tstamp_controller(struct device *device) +{ + struct mii_timestamping_desc *desc; + struct list_head *this, *next; + + mutex_lock(&tstamping_devices_lock); + list_for_each_safe(this, next, &mii_timestamping_devices) { + desc = list_entry(this, struct mii_timestamping_desc, list); + if (desc->device == device) { + list_del_init(&desc->list); + kfree(desc); + break; + } + } + mutex_unlock(&tstamping_devices_lock); +} + +/** + * register_mii_timestamper - Enables a given port of an MII time stamper. + * + * @node: The device tree node of the MII time stamp controller. + * @port: The index of the port to be enabled. + * + * Returns a valid interface on success or ERR_PTR otherwise. + */ +struct mii_timestamper *register_mii_timestamper(struct device_node *node, + unsigned int port) +{ + struct mii_timestamper *mii_ts = NULL; + struct mii_timestamping_desc *desc; + struct list_head *this; + + mutex_lock(&tstamping_devices_lock); + list_for_each(this, &mii_timestamping_devices) { + desc = list_entry(this, struct mii_timestamping_desc, list); + if (desc->device->of_node == node) { + mii_ts = desc->ctrl->probe_channel(desc->device, port); + if (!IS_ERR(mii_ts)) { + mii_ts->device = desc->device; + get_device(desc->device); + } + break; + } + } + mutex_unlock(&tstamping_devices_lock); + + return mii_ts ? mii_ts : ERR_PTR(-EPROBE_DEFER); +} + +/** + * unregister_mii_timestamper - Disables a given MII time stamper. + * + * @mii_ts: An interface obtained via register_mii_timestamper(). + * + */ +void unregister_mii_timestamper(struct mii_timestamper *mii_ts) +{ + struct mii_timestamping_desc *desc; + struct list_head *this; + + mutex_lock(&tstamping_devices_lock); + list_for_each(this, &mii_timestamping_devices) { + desc = list_entry(this, struct mii_timestamping_desc, list); + if (desc->device == mii_ts->device) { + desc->ctrl->release_channel(desc->device, mii_ts); + put_device(desc->device); + break; + } + } + mutex_unlock(&tstamping_devices_lock); +} diff --git a/include/linux/mii_timestamper.h b/include/linux/mii_timestamper.h index 8586eed2f3b9..74524f494cb2 100644 --- a/include/linux/mii_timestamper.h +++ b/include/linux/mii_timestamper.h @@ -8,6 +8,7 @@ #include #include +#include #include /** @@ -31,10 +32,15 @@ * the phy_device mutex. * * @ts_info: Handles ethtool queries for hardware time stamping. + * @device: Remembers the device to which the instance belongs. * * Drivers for PHY time stamping devices should embed their * mii_timestamper within a private structure, obtaining a reference * to it using container_of(). + * + * Drivers for non-PHY time stamping devices should return a pointer + * to a mii_timestamper from the probe_channel() callback of their + * mii_timestamping_ctrl interface. */ struct mii_timestamper { bool (*rxtstamp)(struct mii_timestamper *mii_ts, @@ -51,6 +57,64 @@ struct mii_timestamper { int (*ts_info)(struct mii_timestamper *mii_ts, struct ethtool_ts_info *ts_info); + + struct device *device; +}; + +/** + * struct mii_timestamping_ctrl - MII time stamping controller interface. + * + * @probe_channel: Callback into the controller driver announcing the + * presence of the 'port' channel. The 'device' field + * had been passed to register_mii_tstamp_controller(). + * The driver must return either a pointer to a valid + * MII timestamper instance or PTR_ERR. + * + * @release_channel: Releases an instance obtained via .probe_channel. + */ +struct mii_timestamping_ctrl { + struct mii_timestamper *(*probe_channel)(struct device *device, + unsigned int port); + void (*release_channel)(struct device *device, + struct mii_timestamper *mii_ts); }; +#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING + +int register_mii_tstamp_controller(struct device *device, + struct mii_timestamping_ctrl *ctrl); + +void unregister_mii_tstamp_controller(struct device *device); + +struct mii_timestamper *register_mii_timestamper(struct device_node *node, + unsigned int port); + +void unregister_mii_timestamper(struct mii_timestamper *mii_ts); + +#else + +static inline +int register_mii_tstamp_controller(struct device *device, + struct mii_timestamping_ctrl *ctrl) +{ + return -EOPNOTSUPP; +} + +static inline void unregister_mii_tstamp_controller(struct device *device) +{ +} + +static inline +struct mii_timestamper *register_mii_timestamper(struct device_node *node, + unsigned int port) +{ + return NULL; +} + +static inline void unregister_mii_timestamper(struct mii_timestamper *mii_ts) +{ +} + +#endif + #endif diff --git a/net/Kconfig b/net/Kconfig index d122f53c6fa2..203e6f5dafa7 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -110,9 +110,10 @@ config NETWORK_PHY_TIMESTAMPING bool "Timestamping in PHY devices" select NET_PTP_CLASSIFY help - This allows timestamping of network packets by PHYs with - hardware timestamping capabilities. This option adds some - overhead in the transmit and receive paths. + This allows timestamping of network packets by PHYs (or + other MII bus snooping devices) with hardware timestamping + capabilities. This option adds some overhead in the transmit + and receive paths. If you are unsure how to answer this question, answer N. -- 2.11.0