From patchwork Thu Sep 9 00:17:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 509131 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=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 E1459C433F5 for ; Thu, 9 Sep 2021 00:18:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C8596610C8 for ; Thu, 9 Sep 2021 00:18:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348517AbhIIATJ (ORCPT ); Wed, 8 Sep 2021 20:19:09 -0400 Received: from mail-eopbgr80078.outbound.protection.outlook.com ([40.107.8.78]:42468 "EHLO EUR04-VI1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1348223AbhIIATG (ORCPT ); Wed, 8 Sep 2021 20:19:06 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=VLUNoETa1lxDz8d99LQH6Tgejxbi4Jees7e1LbzVZoUEc6bNEknZ03xhtNhbYYuGFutO02TwOiwN6t3TBBeGiAkvsejKbH3jeItaK6+IF4H0gTHcq598EpTSVwspxW8IEJ3ykm3gC3yinv8ZSmNmCQuCwSo3J4mpjow/OeILoCNqdlOEPnSapB9Lkg4+PFR1wY07zRmtIv7GZuI1En7Eqx/m5qItrB4q9LROsEQKS7hQiDbwHlrbf2G6ZVtx9fh4I8/eOsVkKBSqhq9+eKb/v2t8tb6sZ0hLHTQwY6xlqXoauiDUNIJ6mK/HdqcHdyjXcVB4XQo2C9EcnuYSU7oacw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=9aMxHzkYxYn0+rnlIUEa1CYSrVZLKo5KGhX827QeHFw=; b=E76eFkqAuFoSfgtq7cM5F4QnkTBMGfDS0H88ChHqqo3uHbqE3A5MSc6f9ussGB1izSRFxVGMtrtiGEMeNnMSDV0/CH/ZeD8o5CcRuSDE4vZGxx7sr71/VQO32zkbgtAFPhF9iJ71FBZtOIx+Vib76MbX3O6U6nrxYvw9xzEjzWPCkvaZw7371EvVVZqvT/pfWj7HxZ1LfP4lULPljNz/iZk3EoQV7dlT8ZChXdc9hKbU+XT7r90hwpVlDLK3Px8pASZlifQ+Qys7ouZ+lrJxyeQpm3u9Okaq2q/ca3IBnJFWlZjy3SUBk9FCLr6ygnibGCLZ6m/Wmdvq/wHCMk34FQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass header.d=nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=9aMxHzkYxYn0+rnlIUEa1CYSrVZLKo5KGhX827QeHFw=; b=YxkdhD9zC9cyU0wcTTzQSVTl1L6ocguz5ujN6kera6Bk4kt5sIyZ0azddcrZaCa2j1mwq5kNmrRe/19vKQvQMpsr7WPx2u4wPwtka+VgqCiAjVTIBdv1KI8PEzDej5F21TQEjSu4mYO2uEvOBzybSmf49nPltkA9BwZeDeb4XTc= Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none; vger.kernel.org; dmarc=none action=none header.from=nxp.com; Received: from VI1PR04MB5136.eurprd04.prod.outlook.com (2603:10a6:803:55::19) by VE1PR04MB6511.eurprd04.prod.outlook.com (2603:10a6:803:11f::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4500.14; Thu, 9 Sep 2021 00:17:51 +0000 Received: from VI1PR04MB5136.eurprd04.prod.outlook.com ([fe80::109:1995:3e6b:5bd0]) by VI1PR04MB5136.eurprd04.prod.outlook.com ([fe80::109:1995:3e6b:5bd0%2]) with mapi id 15.20.4478.026; Thu, 9 Sep 2021 00:17:50 +0000 From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Florian Fainelli , Andrew Lunn , Vivien Didelot , Vladimir Oltean Subject: [RFC PATCH net 1/2] net: dsa: sja1105: split out the probing code into a separate driver Date: Thu, 9 Sep 2021 03:17:35 +0300 Message-Id: <20210909001736.3769910-2-vladimir.oltean@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210909001736.3769910-1-vladimir.oltean@nxp.com> References: <20210909001736.3769910-1-vladimir.oltean@nxp.com> X-ClientProxiedBy: VI1PR04CA0058.eurprd04.prod.outlook.com (2603:10a6:802:2::29) To VI1PR04MB5136.eurprd04.prod.outlook.com (2603:10a6:803:55::19) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from localhost.localdomain (82.78.148.104) by VI1PR04CA0058.eurprd04.prod.outlook.com (2603:10a6:802:2::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4500.14 via Frontend Transport; Thu, 9 Sep 2021 00:17:50 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: d491e025-80f2-40f4-2d21-08d973274286 X-MS-TrafficTypeDiagnostic: VE1PR04MB6511: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:1388; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: RF71ncWdNSayXsl3IK5NuNfomWvS1gnf68YhKJIlwFeiy4keTHu3koTT5o2GSEdnrHddR5p0mL2hub6kPRy9qiNvDhmo+IbmemJATH4Ju+zwCh3sE/k+x0xKR1iSuD7Y74iZXyDNv7HQZAoj+2/Y56HPrYflY9WyZPr9pcveVSASPKZwbXRRgWsmm6uDq35XZqnkA6R5w5FU2lkyqr6SQ5oJRlzXCWxAvXQgoPYxNPGCDzG8nAzERDOK0pDPAP4bXq9KAR0h7wY62rG8QgsTrOzYmV5QxVPFG+Qzd8hGK6GRD+XV3JlKZ/hccslGR6yHfmCqtq+A9u2ZoyomUq83mheTqyXXGR1em8RVc5WwVFPHg4sEnzdgd0299qmZKq7vKbuakC8ZLut0cwPUdGp9ZpVDn8p+FvE677sZwfhsWfgRdhMGfob1CJJ8rfqOY5XUODRS+gSb/VN3ke+UfET1hrOllEwjD5SqwLnY6jv9lxwO2hUBrqHqcNMifEJQyJysbCfS64vsDNt9pKwUJkwhfjdQzEeZS2NCV/YKfHsJAVaGszYRMmNRZrP3mTj0AJYSZulcoKp/q+9x7pSz+N3NRZHDfI6KY4G7RvT/PpfmBUaauUMFgs8bY7Qc6RFuT6B2PqfORvzndlCf8My3cEWUXji73eE18Jgsf9cMR6oKcQ0LByFB5F6C/hJ2IRukwqHl/be/KSBdvUBfY5f849oJ9VqfURbx1X/7ew+xVb6susJPUWFlqmf0f45dMjDHhQbYE69PMqAat+o1gAvlsOa2s+SuN/TycqJV9vcwdqWtSiw= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR04MB5136.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(4636009)(366004)(38350700002)(38100700002)(1076003)(4326008)(8676002)(2906002)(6506007)(66946007)(83380400001)(2616005)(956004)(66556008)(966005)(6486002)(26005)(6512007)(8936002)(66476007)(5660300002)(6666004)(36756003)(6916009)(52116002)(86362001)(44832011)(316002)(508600001)(186003)(30864003)(54906003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: Fy2h9HceJ0cwrxPE/BdHo9fjil3vhPBHfuzp2pl+vpSUuZna1Cm9JRgzlqxh1vtHjNjYvWwAKW+agGZ3OvIGk6iNTLI4IfeHNX4WeviUPqwKhWEAgITRggOMAghGhbMyHIeq4w5QBJBZOW3M9RgDrg4fS2NgW/0LotVy4MzZxOboclWmGTpP0v8OY1jTTh1vlRjsxgzcKV8eBPiFXGxjtJ9wJXq5qzlxEPxmzLLFf+tTKs9jFXmnzGKwVr2QbxVgCG8gyVwgzISy1zjHDkyNsoRTLGKcVvAdrBNHQ4ZKOVK9iTv2NlxSga5snRZzy5oU7pkifzVW8ddE+hpV7hth6OTKrzfHgcMsa6Hxu+gBEsuPMa9auWu+5Ukxh5bOyLBUBm4/EHAuqvrmjpa1HkVDMdOlduoCJpfnlrv2h7e6OoGmve0M2fhdcZQx9ffoKUwvs5Dl/TXjDJWlDOWlSd6488qBNX+jfHdxPy5sJovWsZn5HN9hGPKdULxGoNPZWLPIE2DTjGpfsA9wiTAr7rnZLfXYsH+n64jv1nFBa7Tv69E/vvm1hk7GurXRxLdXzok8cRsiSpfe42AUkPxwAY/LxABmMipawg/vqoWGs0HTKVRmcJrI7m4yGSQs9KljysUrMXYHkEiVrmXlQQc6kksVRIkG+O0EdB3trLJat8UNM4L+hpv7Df77SfIvSze9chF+2bfVTEDOy95a3mIdzE1HuzMo3kh5NXdyki59ONRLm10cdrGFBloAAwRK71e4L+S6HSzWoWLRSJaiAX9tBr7mP9jUE5xCCw2mFPr4hJE63VTHEOd53LAWQ3cxb+wC2KDyms+9IEC5td6UNp/4iSAtT8WO3/PjpLtniQLNNzprIK4sBrTJs1cToug8FymFoj/z1L9gL9WryszVRvIFZDrprdIScb7CmYaikhsJyhantjZuj4RVMo38NBfXmVfwBYhVESyxYx8g2xsIQAeXPtWD7tNCkYvDHWyoFcKJf7ppFgfOn00RnjoyEwG5WUto7KtZZtNEEOhUAYkqfrI4DM+OtRhDUAc2IKnSw9DnXmR/Tqtrgd6e8I0c0U/aGXeUg+DrVzJpwrx1uKyT/6b2ZOAWZP+otGlAkLUERo1sV3VSSzuWD+JwQc1R8m4S9/zL7Wa9QHosD0/SKxv4BabGQYJXIfy8HkNCJxoIpTX+fAlhtFWzwOLVxDWE45EhSNM8Da83/NJPioQGVIGubwfT/0VUtn+089GxNUoMzJUqxWCnLN1vx5frO+/iG4ondDEhz8uz0o9On5Hl+8LXM4m9wNG4AJkjxNFj1Guxj7dfOX8zXRTmUlX234vIy6j9tXNiRdRi X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: d491e025-80f2-40f4-2d21-08d973274286 X-MS-Exchange-CrossTenant-AuthSource: VI1PR04MB5136.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Sep 2021 00:17:50.8932 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: HS5IC1GDPkDN4HXfcOpRBa4YmvfuiP1MdKwGwiZP/6bHopYWGZeaQSlU33Z7BadkyejCVlQFd9kJ/mLOB+LF8g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VE1PR04MB6511 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The tag_sja1105.ko depends on the sja1105_switch_ops being exported by the kernel before it can be inserted as a module, but at the same time, it must be inserted into the kernel before the sja1105 driver can probe. Solve this circular dependency by adding a third kernel module, which is only responsible for probing the hardware and depends on the driver which provides sja1105_switch_ops and interacts with DSA and with the hardware at runtime, generally speaking. Fixes: 994d2cbb08ca ("net: dsa: tag_sja1105: be dsa_loop-safe") Link: https://lore.kernel.org/netdev/20210908220834.d7gmtnwrorhharna@skbuf/ Suggested-by: Florian Fainelli Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/Kconfig | 4 + drivers/net/dsa/sja1105/Makefile | 2 + drivers/net/dsa/sja1105/sja1105_main.c | 316 ----------------- drivers/net/dsa/sja1105/sja1105_probe.c | 322 ++++++++++++++++++ drivers/net/dsa/sja1105/sja1105_spi.c | 12 + .../net/dsa/sja1105/sja1105_static_config.c | 1 + 6 files changed, 341 insertions(+), 316 deletions(-) create mode 100644 drivers/net/dsa/sja1105/sja1105_probe.c diff --git a/drivers/net/dsa/sja1105/Kconfig b/drivers/net/dsa/sja1105/Kconfig index 1291bba3f3b6..33f948d9ea18 100644 --- a/drivers/net/dsa/sja1105/Kconfig +++ b/drivers/net/dsa/sja1105/Kconfig @@ -23,6 +23,10 @@ tristate "NXP SJA1105 Ethernet switch family support" - SJA1110C (Gen. 3, SGMII, TT-Ethernet, 100base-TX PHY, 7 ports) - SJA1110D (Gen. 3, SGMII, TT-Ethernet, no 100base-TX PHY, 7 ports) +config NET_DSA_SJA1105_PROBE +tristate "Actual driver that probes the hardware" + depends on NET_DSA_SJA1105 + config NET_DSA_SJA1105_PTP bool "Support for the PTP clock on the NXP SJA1105 Ethernet switch" depends on NET_DSA_SJA1105 diff --git a/drivers/net/dsa/sja1105/Makefile b/drivers/net/dsa/sja1105/Makefile index 40d69e6c0bae..73b4281f8218 100644 --- a/drivers/net/dsa/sja1105/Makefile +++ b/drivers/net/dsa/sja1105/Makefile @@ -23,3 +23,5 @@ endif ifdef CONFIG_NET_DSA_SJA1105_VL sja1105-objs += sja1105_vl.o endif + +obj-$(CONFIG_NET_DSA_SJA1105_PROBE) += sja1105_probe.o diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 2f8cc6686c38..01ef4839f631 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -10,12 +10,8 @@ #include #include #include -#include #include #include -#include -#include -#include #include #include #include @@ -27,17 +23,6 @@ #define SJA1105_UNKNOWN_MULTICAST 0x010000000000ull -static void sja1105_hw_reset(struct gpio_desc *gpio, unsigned int pulse_len, - unsigned int startup_delay) -{ - gpiod_set_value_cansleep(gpio, 1); - /* Wait for minimum reset pulse length */ - msleep(pulse_len); - gpiod_set_value_cansleep(gpio, 0); - /* Wait until chip is ready after reset */ - msleep(startup_delay); -} - static void sja1105_port_allow_traffic(struct sja1105_l2_forwarding_entry *l2_fwd, int from, int to, bool allow) @@ -1095,103 +1080,6 @@ static int sja1105_static_config_load(struct sja1105_private *priv) return sja1105_static_config_upload(priv); } -static int sja1105_parse_rgmii_delays(struct sja1105_private *priv) -{ - struct dsa_switch *ds = priv->ds; - int port; - - for (port = 0; port < ds->num_ports; port++) { - if (!priv->fixed_link[port]) - continue; - - if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_RXID || - priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID) - priv->rgmii_rx_delay[port] = true; - - if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_TXID || - priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID) - priv->rgmii_tx_delay[port] = true; - - if ((priv->rgmii_rx_delay[port] || priv->rgmii_tx_delay[port]) && - !priv->info->setup_rgmii_delay) - return -EINVAL; - } - return 0; -} - -static int sja1105_parse_ports_node(struct sja1105_private *priv, - struct device_node *ports_node) -{ - struct device *dev = &priv->spidev->dev; - struct device_node *child; - - for_each_available_child_of_node(ports_node, child) { - struct device_node *phy_node; - phy_interface_t phy_mode; - u32 index; - int err; - - /* Get switch port number from DT */ - if (of_property_read_u32(child, "reg", &index) < 0) { - dev_err(dev, "Port number not defined in device tree " - "(property \"reg\")\n"); - of_node_put(child); - return -ENODEV; - } - - /* Get PHY mode from DT */ - err = of_get_phy_mode(child, &phy_mode); - if (err) { - dev_err(dev, "Failed to read phy-mode or " - "phy-interface-type property for port %d\n", - index); - of_node_put(child); - return -ENODEV; - } - - phy_node = of_parse_phandle(child, "phy-handle", 0); - if (!phy_node) { - if (!of_phy_is_fixed_link(child)) { - dev_err(dev, "phy-handle or fixed-link " - "properties missing!\n"); - of_node_put(child); - return -ENODEV; - } - /* phy-handle is missing, but fixed-link isn't. - * So it's a fixed link. Default to PHY role. - */ - priv->fixed_link[index] = true; - } else { - of_node_put(phy_node); - } - - priv->phy_mode[index] = phy_mode; - } - - return 0; -} - -static int sja1105_parse_dt(struct sja1105_private *priv) -{ - struct device *dev = &priv->spidev->dev; - struct device_node *switch_node = dev->of_node; - struct device_node *ports_node; - int rc; - - ports_node = of_get_child_by_name(switch_node, "ports"); - if (!ports_node) - ports_node = of_get_child_by_name(switch_node, "ethernet-ports"); - if (!ports_node) { - dev_err(dev, "Incorrect bindings: absent \"ports\" node\n"); - return -ENODEV; - } - - rc = sja1105_parse_ports_node(priv, ports_node); - of_node_put(ports_node); - - return rc; -} - /* Convert link speed from SJA1105 to ethtool encoding */ static int sja1105_port_speed_to_ethtool(struct sja1105_private *priv, u64 speed) @@ -3168,208 +3056,4 @@ const struct dsa_switch_ops sja1105_switch_ops = { }; EXPORT_SYMBOL_GPL(sja1105_switch_ops); -static const struct of_device_id sja1105_dt_ids[]; - -static int sja1105_check_device_id(struct sja1105_private *priv) -{ - const struct sja1105_regs *regs = priv->info->regs; - u8 prod_id[SJA1105_SIZE_DEVICE_ID] = {0}; - struct device *dev = &priv->spidev->dev; - const struct of_device_id *match; - u32 device_id; - u64 part_no; - int rc; - - rc = sja1105_xfer_u32(priv, SPI_READ, regs->device_id, &device_id, - NULL); - if (rc < 0) - return rc; - - rc = sja1105_xfer_buf(priv, SPI_READ, regs->prod_id, prod_id, - SJA1105_SIZE_DEVICE_ID); - if (rc < 0) - return rc; - - sja1105_unpack(prod_id, &part_no, 19, 4, SJA1105_SIZE_DEVICE_ID); - - for (match = sja1105_dt_ids; match->compatible[0]; match++) { - const struct sja1105_info *info = match->data; - - /* Is what's been probed in our match table at all? */ - if (info->device_id != device_id || info->part_no != part_no) - continue; - - /* But is it what's in the device tree? */ - if (priv->info->device_id != device_id || - priv->info->part_no != part_no) { - dev_warn(dev, "Device tree specifies chip %s but found %s, please fix it!\n", - priv->info->name, info->name); - /* It isn't. No problem, pick that up. */ - priv->info = info; - } - - return 0; - } - - dev_err(dev, "Unexpected {device ID, part number}: 0x%x 0x%llx\n", - device_id, part_no); - - return -ENODEV; -} - -static int sja1105_probe(struct spi_device *spi) -{ - struct device *dev = &spi->dev; - struct sja1105_private *priv; - size_t max_xfer, max_msg; - struct dsa_switch *ds; - int rc; - - if (!dev->of_node) { - dev_err(dev, "No DTS bindings for SJA1105 driver\n"); - return -EINVAL; - } - - priv = devm_kzalloc(dev, sizeof(struct sja1105_private), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - /* Configure the optional reset pin and bring up switch */ - priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(priv->reset_gpio)) - dev_dbg(dev, "reset-gpios not defined, ignoring\n"); - else - sja1105_hw_reset(priv->reset_gpio, 1, 1); - - /* Populate our driver private structure (priv) based on - * the device tree node that was probed (spi) - */ - priv->spidev = spi; - spi_set_drvdata(spi, priv); - - /* Configure the SPI bus */ - spi->bits_per_word = 8; - rc = spi_setup(spi); - if (rc < 0) { - dev_err(dev, "Could not init SPI\n"); - return rc; - } - - /* In sja1105_xfer, we send spi_messages composed of two spi_transfers: - * a small one for the message header and another one for the current - * chunk of the packed buffer. - * Check that the restrictions imposed by the SPI controller are - * respected: the chunk buffer is smaller than the max transfer size, - * and the total length of the chunk plus its message header is smaller - * than the max message size. - * We do that during probe time since the maximum transfer size is a - * runtime invariant. - */ - max_xfer = spi_max_transfer_size(spi); - max_msg = spi_max_message_size(spi); - - /* We need to send at least one 64-bit word of SPI payload per message - * in order to be able to make useful progress. - */ - if (max_msg < SJA1105_SIZE_SPI_MSG_HEADER + 8) { - dev_err(dev, "SPI master cannot send large enough buffers, aborting\n"); - return -EINVAL; - } - - priv->max_xfer_len = SJA1105_SIZE_SPI_MSG_MAXLEN; - if (priv->max_xfer_len > max_xfer) - priv->max_xfer_len = max_xfer; - if (priv->max_xfer_len > max_msg - SJA1105_SIZE_SPI_MSG_HEADER) - priv->max_xfer_len = max_msg - SJA1105_SIZE_SPI_MSG_HEADER; - - priv->info = of_device_get_match_data(dev); - - /* Detect hardware device */ - rc = sja1105_check_device_id(priv); - if (rc < 0) { - dev_err(dev, "Device ID check failed: %d\n", rc); - return rc; - } - - dev_info(dev, "Probed switch chip: %s\n", priv->info->name); - - ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL); - if (!ds) - return -ENOMEM; - - ds->dev = dev; - ds->num_ports = priv->info->num_ports; - ds->ops = &sja1105_switch_ops; - ds->priv = priv; - priv->ds = ds; - - mutex_init(&priv->ptp_data.lock); - mutex_init(&priv->mgmt_lock); - - rc = sja1105_parse_dt(priv); - if (rc < 0) { - dev_err(ds->dev, "Failed to parse DT: %d\n", rc); - return rc; - } - - /* Error out early if internal delays are required through DT - * and we can't apply them. - */ - rc = sja1105_parse_rgmii_delays(priv); - if (rc < 0) { - dev_err(ds->dev, "RGMII delay not supported\n"); - return rc; - } - - if (IS_ENABLED(CONFIG_NET_SCH_CBS)) { - priv->cbs = devm_kcalloc(dev, priv->info->num_cbs_shapers, - sizeof(struct sja1105_cbs_entry), - GFP_KERNEL); - if (!priv->cbs) - return -ENOMEM; - } - - return dsa_register_switch(priv->ds); -} - -static int sja1105_remove(struct spi_device *spi) -{ - struct sja1105_private *priv = spi_get_drvdata(spi); - struct dsa_switch *ds = priv->ds; - - dsa_unregister_switch(ds); - - return 0; -} - -static const struct of_device_id sja1105_dt_ids[] = { - { .compatible = "nxp,sja1105e", .data = &sja1105e_info }, - { .compatible = "nxp,sja1105t", .data = &sja1105t_info }, - { .compatible = "nxp,sja1105p", .data = &sja1105p_info }, - { .compatible = "nxp,sja1105q", .data = &sja1105q_info }, - { .compatible = "nxp,sja1105r", .data = &sja1105r_info }, - { .compatible = "nxp,sja1105s", .data = &sja1105s_info }, - { .compatible = "nxp,sja1110a", .data = &sja1110a_info }, - { .compatible = "nxp,sja1110b", .data = &sja1110b_info }, - { .compatible = "nxp,sja1110c", .data = &sja1110c_info }, - { .compatible = "nxp,sja1110d", .data = &sja1110d_info }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, sja1105_dt_ids); - -static struct spi_driver sja1105_driver = { - .driver = { - .name = "sja1105", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(sja1105_dt_ids), - }, - .probe = sja1105_probe, - .remove = sja1105_remove, -}; - -module_spi_driver(sja1105_driver); - -MODULE_AUTHOR("Vladimir Oltean "); -MODULE_AUTHOR("Georg Waibel "); -MODULE_DESCRIPTION("SJA1105 Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/dsa/sja1105/sja1105_probe.c b/drivers/net/dsa/sja1105/sja1105_probe.c new file mode 100644 index 000000000000..debb9bcd788c --- /dev/null +++ b/drivers/net/dsa/sja1105/sja1105_probe.c @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright 2021 NXP */ +#include +#include +#include +#include +#include +#include "sja1105.h" + +static void sja1105_hw_reset(struct gpio_desc *gpio, unsigned int pulse_len, + unsigned int startup_delay) +{ + gpiod_set_value_cansleep(gpio, 1); + /* Wait for minimum reset pulse length */ + msleep(pulse_len); + gpiod_set_value_cansleep(gpio, 0); + /* Wait until chip is ready after reset */ + msleep(startup_delay); +} + +static int sja1105_parse_rgmii_delays(struct sja1105_private *priv) +{ + struct dsa_switch *ds = priv->ds; + int port; + + for (port = 0; port < ds->num_ports; port++) { + if (!priv->fixed_link[port]) + continue; + + if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_RXID || + priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID) + priv->rgmii_rx_delay[port] = true; + + if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_TXID || + priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID) + priv->rgmii_tx_delay[port] = true; + + if ((priv->rgmii_rx_delay[port] || priv->rgmii_tx_delay[port]) && + !priv->info->setup_rgmii_delay) + return -EINVAL; + } + return 0; +} + +static int sja1105_parse_ports_node(struct sja1105_private *priv, + struct device_node *ports_node) +{ + struct device *dev = &priv->spidev->dev; + struct device_node *child; + + for_each_available_child_of_node(ports_node, child) { + struct device_node *phy_node; + phy_interface_t phy_mode; + u32 index; + int err; + + /* Get switch port number from DT */ + if (of_property_read_u32(child, "reg", &index) < 0) { + dev_err(dev, "Port number not defined in device tree " + "(property \"reg\")\n"); + of_node_put(child); + return -ENODEV; + } + + /* Get PHY mode from DT */ + err = of_get_phy_mode(child, &phy_mode); + if (err) { + dev_err(dev, "Failed to read phy-mode or " + "phy-interface-type property for port %d\n", + index); + of_node_put(child); + return -ENODEV; + } + + phy_node = of_parse_phandle(child, "phy-handle", 0); + if (!phy_node) { + if (!of_phy_is_fixed_link(child)) { + dev_err(dev, "phy-handle or fixed-link " + "properties missing!\n"); + of_node_put(child); + return -ENODEV; + } + /* phy-handle is missing, but fixed-link isn't. + * So it's a fixed link. Default to PHY role. + */ + priv->fixed_link[index] = true; + } else { + of_node_put(phy_node); + } + + priv->phy_mode[index] = phy_mode; + } + + return 0; +} + +static int sja1105_parse_dt(struct sja1105_private *priv) +{ + struct device *dev = &priv->spidev->dev; + struct device_node *switch_node = dev->of_node; + struct device_node *ports_node; + int rc; + + ports_node = of_get_child_by_name(switch_node, "ports"); + if (!ports_node) + ports_node = of_get_child_by_name(switch_node, "ethernet-ports"); + if (!ports_node) { + dev_err(dev, "Incorrect bindings: absent \"ports\" node\n"); + return -ENODEV; + } + + rc = sja1105_parse_ports_node(priv, ports_node); + of_node_put(ports_node); + + return rc; +} + +static const struct of_device_id sja1105_dt_ids[]; + +static int sja1105_check_device_id(struct sja1105_private *priv) +{ + const struct sja1105_regs *regs = priv->info->regs; + u8 prod_id[SJA1105_SIZE_DEVICE_ID] = {0}; + struct device *dev = &priv->spidev->dev; + const struct of_device_id *match; + u32 device_id; + u64 part_no; + int rc; + + rc = sja1105_xfer_u32(priv, SPI_READ, regs->device_id, &device_id, + NULL); + if (rc < 0) + return rc; + + rc = sja1105_xfer_buf(priv, SPI_READ, regs->prod_id, prod_id, + SJA1105_SIZE_DEVICE_ID); + if (rc < 0) + return rc; + + sja1105_unpack(prod_id, &part_no, 19, 4, SJA1105_SIZE_DEVICE_ID); + + for (match = sja1105_dt_ids; match->compatible[0]; match++) { + const struct sja1105_info *info = match->data; + + /* Is what's been probed in our match table at all? */ + if (info->device_id != device_id || info->part_no != part_no) + continue; + + /* But is it what's in the device tree? */ + if (priv->info->device_id != device_id || + priv->info->part_no != part_no) { + dev_warn(dev, "Device tree specifies chip %s but found %s, please fix it!\n", + priv->info->name, info->name); + /* It isn't. No problem, pick that up. */ + priv->info = info; + } + + return 0; + } + + dev_err(dev, "Unexpected {device ID, part number}: 0x%x 0x%llx\n", + device_id, part_no); + + return -ENODEV; +} + +static int sja1105_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct sja1105_private *priv; + size_t max_xfer, max_msg; + struct dsa_switch *ds; + int rc; + + if (!dev->of_node) { + dev_err(dev, "No DTS bindings for SJA1105 driver\n"); + return -EINVAL; + } + + priv = devm_kzalloc(dev, sizeof(struct sja1105_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* Configure the optional reset pin and bring up switch */ + priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(priv->reset_gpio)) + dev_dbg(dev, "reset-gpios not defined, ignoring\n"); + else + sja1105_hw_reset(priv->reset_gpio, 1, 1); + + /* Populate our driver private structure (priv) based on + * the device tree node that was probed (spi) + */ + priv->spidev = spi; + spi_set_drvdata(spi, priv); + + /* Configure the SPI bus */ + spi->bits_per_word = 8; + rc = spi_setup(spi); + if (rc < 0) { + dev_err(dev, "Could not init SPI\n"); + return rc; + } + + /* In sja1105_xfer, we send spi_messages composed of two spi_transfers: + * a small one for the message header and another one for the current + * chunk of the packed buffer. + * Check that the restrictions imposed by the SPI controller are + * respected: the chunk buffer is smaller than the max transfer size, + * and the total length of the chunk plus its message header is smaller + * than the max message size. + * We do that during probe time since the maximum transfer size is a + * runtime invariant. + */ + max_xfer = spi_max_transfer_size(spi); + max_msg = spi_max_message_size(spi); + + /* We need to send at least one 64-bit word of SPI payload per message + * in order to be able to make useful progress. + */ + if (max_msg < SJA1105_SIZE_SPI_MSG_HEADER + 8) { + dev_err(dev, "SPI master cannot send large enough buffers, aborting\n"); + return -EINVAL; + } + + priv->max_xfer_len = SJA1105_SIZE_SPI_MSG_MAXLEN; + if (priv->max_xfer_len > max_xfer) + priv->max_xfer_len = max_xfer; + if (priv->max_xfer_len > max_msg - SJA1105_SIZE_SPI_MSG_HEADER) + priv->max_xfer_len = max_msg - SJA1105_SIZE_SPI_MSG_HEADER; + + priv->info = of_device_get_match_data(dev); + + /* Detect hardware device */ + rc = sja1105_check_device_id(priv); + if (rc < 0) { + dev_err(dev, "Device ID check failed: %d\n", rc); + return rc; + } + + dev_info(dev, "Probed switch chip: %s\n", priv->info->name); + + ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL); + if (!ds) + return -ENOMEM; + + ds->dev = dev; + ds->num_ports = priv->info->num_ports; + ds->ops = &sja1105_switch_ops; + ds->priv = priv; + priv->ds = ds; + + mutex_init(&priv->ptp_data.lock); + mutex_init(&priv->mgmt_lock); + + rc = sja1105_parse_dt(priv); + if (rc < 0) { + dev_err(ds->dev, "Failed to parse DT: %d\n", rc); + return rc; + } + + /* Error out early if internal delays are required through DT + * and we can't apply them. + */ + rc = sja1105_parse_rgmii_delays(priv); + if (rc < 0) { + dev_err(ds->dev, "RGMII delay not supported\n"); + return rc; + } + + if (IS_ENABLED(CONFIG_NET_SCH_CBS)) { + priv->cbs = devm_kcalloc(dev, priv->info->num_cbs_shapers, + sizeof(struct sja1105_cbs_entry), + GFP_KERNEL); + if (!priv->cbs) + return -ENOMEM; + } + + return dsa_register_switch(priv->ds); +} + +static int sja1105_remove(struct spi_device *spi) +{ + struct sja1105_private *priv = spi_get_drvdata(spi); + struct dsa_switch *ds = priv->ds; + + dsa_unregister_switch(ds); + + return 0; +} + +static const struct of_device_id sja1105_dt_ids[] = { + { .compatible = "nxp,sja1105e", .data = &sja1105e_info }, + { .compatible = "nxp,sja1105t", .data = &sja1105t_info }, + { .compatible = "nxp,sja1105p", .data = &sja1105p_info }, + { .compatible = "nxp,sja1105q", .data = &sja1105q_info }, + { .compatible = "nxp,sja1105r", .data = &sja1105r_info }, + { .compatible = "nxp,sja1105s", .data = &sja1105s_info }, + { .compatible = "nxp,sja1110a", .data = &sja1110a_info }, + { .compatible = "nxp,sja1110b", .data = &sja1110b_info }, + { .compatible = "nxp,sja1110c", .data = &sja1110c_info }, + { .compatible = "nxp,sja1110d", .data = &sja1110d_info }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, sja1105_dt_ids); + +static struct spi_driver sja1105_driver = { + .driver = { + .name = "sja1105", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(sja1105_dt_ids), + }, + .probe = sja1105_probe, + .remove = sja1105_remove, +}; + +module_spi_driver(sja1105_driver); + +MODULE_AUTHOR("Vladimir Oltean "); +MODULE_AUTHOR("Georg Waibel "); +MODULE_DESCRIPTION("SJA1105 Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index d60a530d0272..420c21bfd6b5 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -118,6 +118,7 @@ int sja1105_xfer_buf(const struct sja1105_private *priv, { return sja1105_xfer(priv, rw, reg_addr, buf, len, NULL); } +EXPORT_SYMBOL_GPL(sja1105_xfer_buf); /* If @rw is: * - SPI_WRITE: creates and sends an SPI write message at absolute @@ -172,6 +173,7 @@ int sja1105_xfer_u32(const struct sja1105_private *priv, return rc; } +EXPORT_SYMBOL_GPL(sja1105_xfer_u32); static int sja1105et_reset_cmd(struct dsa_switch *ds) { @@ -601,6 +603,7 @@ const struct sja1105_info sja1105e_info = { .supports_rgmii = {true, true, true, true, true}, .name = "SJA1105E", }; +EXPORT_SYMBOL_GPL(sja1105e_info); const struct sja1105_info sja1105t_info = { .device_id = SJA1105T_DEVICE_ID, @@ -633,6 +636,7 @@ const struct sja1105_info sja1105t_info = { .supports_rgmii = {true, true, true, true, true}, .name = "SJA1105T", }; +EXPORT_SYMBOL_GPL(sja1105t_info); const struct sja1105_info sja1105p_info = { .device_id = SJA1105PR_DEVICE_ID, @@ -666,6 +670,7 @@ const struct sja1105_info sja1105p_info = { .supports_rgmii = {true, true, true, true, true}, .name = "SJA1105P", }; +EXPORT_SYMBOL_GPL(sja1105p_info); const struct sja1105_info sja1105q_info = { .device_id = SJA1105QS_DEVICE_ID, @@ -699,6 +704,7 @@ const struct sja1105_info sja1105q_info = { .supports_rgmii = {true, true, true, true, true}, .name = "SJA1105Q", }; +EXPORT_SYMBOL_GPL(sja1105q_info); const struct sja1105_info sja1105r_info = { .device_id = SJA1105PR_DEVICE_ID, @@ -735,6 +741,7 @@ const struct sja1105_info sja1105r_info = { .supports_sgmii = {false, false, false, false, true}, .name = "SJA1105R", }; +EXPORT_SYMBOL_GPL(sja1105r_info); const struct sja1105_info sja1105s_info = { .device_id = SJA1105QS_DEVICE_ID, @@ -771,6 +778,7 @@ const struct sja1105_info sja1105s_info = { .supports_sgmii = {false, false, false, false, true}, .name = "SJA1105S", }; +EXPORT_SYMBOL_GPL(sja1105s_info); const struct sja1105_info sja1110a_info = { .device_id = SJA1110_DEVICE_ID, @@ -821,6 +829,7 @@ const struct sja1105_info sja1110a_info = { SJA1105_PHY_BASE_T1}, .name = "SJA1110A", }; +EXPORT_SYMBOL_GPL(sja1110a_info); const struct sja1105_info sja1110b_info = { .device_id = SJA1110_DEVICE_ID, @@ -871,6 +880,7 @@ const struct sja1105_info sja1110b_info = { SJA1105_NO_PHY}, .name = "SJA1110B", }; +EXPORT_SYMBOL_GPL(sja1110b_info); const struct sja1105_info sja1110c_info = { .device_id = SJA1110_DEVICE_ID, @@ -921,6 +931,7 @@ const struct sja1105_info sja1110c_info = { SJA1105_NO_PHY}, .name = "SJA1110C", }; +EXPORT_SYMBOL_GPL(sja1110c_info); const struct sja1105_info sja1110d_info = { .device_id = SJA1110_DEVICE_ID, @@ -971,3 +982,4 @@ const struct sja1105_info sja1110d_info = { SJA1105_NO_PHY}, .name = "SJA1110D", }; +EXPORT_SYMBOL_GPL(sja1110d_info); diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.c b/drivers/net/dsa/sja1105/sja1105_static_config.c index 7a422ef4deb6..d5bca0d43b21 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.c +++ b/drivers/net/dsa/sja1105/sja1105_static_config.c @@ -52,6 +52,7 @@ void sja1105_unpack(const void *buf, u64 *val, int start, int end, size_t len) start, end); dump_stack(); } +EXPORT_SYMBOL_GPL(sja1105_unpack); void sja1105_packing(void *buf, u64 *val, int start, int end, size_t len, enum packing_op op) From patchwork Thu Sep 9 00:17:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 508724 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=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, 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 235F0C433EF for ; Thu, 9 Sep 2021 00:18:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0293A6108B for ; Thu, 9 Sep 2021 00:17:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348469AbhIIATG (ORCPT ); Wed, 8 Sep 2021 20:19:06 -0400 Received: from mail-eopbgr80078.outbound.protection.outlook.com ([40.107.8.78]:42468 "EHLO EUR04-VI1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1348431AbhIIATE (ORCPT ); Wed, 8 Sep 2021 20:19:04 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Hw5KwlgiSUXVcYBIflcF4zU/A6frh4M+xIaV3axsknah9F/g5lc6+wQlwLbDlu7gaIFVxRsl3eWYl/mO3uKb93VZ43Ov+tJBV94nr4vfQXPBCBPZSMNlvyKPwtLnzi4SvR4VSAAb5Pq4z+6ctzW4KxSuoEmT+j0+JjYhZ5mLUZrKvUVms1XQLkTtrAdk6MdsM8mqqYOz5ClxWTJCxzogvETAdWSyqLL0jOEquQQ/D4T0aF2Ft9JSElSzk4Ze12Jh5FMlCB6M6y7abUsbs1+h3ChWBHuJ4xuoIBy4vcSFx9ua9W8cDjxENG+8owFO0khtMxXENu4LuVz+ZrrJPwYLnw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=ssr7Xgr0lkbvdSo0zfYDc6el3rZjWW6R4Vf2tZ7mQSQ=; b=gWkF+gELBbSF28Prw5jnNsUXndio29ApkMfPqsGsHvTSbwx7UsDEn4HIS7fdzJ1S9yVcPItw8rWuyAL9ZhHrza/92QF9euUS+7ay7a4NNom75KemNl6b2a1c6fFzAkcIFd4e8QWoqQu/RKV3IMyzlP2sNHrhL1Xex0k0QADLjt/bV7mHUkJNSPlr2DUZtzQxGe8SYSaN/rld8VOcbW4OT9pOZLy9G9syDAJAzeL0weny/zkybg8NIBQg1JllYNg0r6yH9H0Z92Qvr/ttmesDShTVJNKsdeQ4zsIdP/P14tcORaOGu6/kjstgOUAfWBdc3ffMJGdailvAfJDzi+gAQw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass header.d=nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ssr7Xgr0lkbvdSo0zfYDc6el3rZjWW6R4Vf2tZ7mQSQ=; b=jmot30/xyhF+h1dSjEncJGXBOiW7drictpHDXWOhcPizKZQC0l865g+ijhSONqIoLvWYZvhb6tdVy/6Ukr7fy0vAmOXNeApVor4Qms3IQfg80RmS9XULUqGm9BRAywrHfL+gWu1P/GjO05Zhf3XpE2/F9XAgMn8pW6Zz2xgqWA4= Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none; vger.kernel.org; dmarc=none action=none header.from=nxp.com; Received: from VI1PR04MB5136.eurprd04.prod.outlook.com (2603:10a6:803:55::19) by VE1PR04MB6511.eurprd04.prod.outlook.com (2603:10a6:803:11f::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4500.14; Thu, 9 Sep 2021 00:17:51 +0000 Received: from VI1PR04MB5136.eurprd04.prod.outlook.com ([fe80::109:1995:3e6b:5bd0]) by VI1PR04MB5136.eurprd04.prod.outlook.com ([fe80::109:1995:3e6b:5bd0%2]) with mapi id 15.20.4478.026; Thu, 9 Sep 2021 00:17:51 +0000 From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Florian Fainelli , Andrew Lunn , Vivien Didelot , Vladimir Oltean Subject: [RFC PATCH net 2/2] net: dsa: move sja1110_process_meta_tstamp inside the tagging protocol driver Date: Thu, 9 Sep 2021 03:17:36 +0300 Message-Id: <20210909001736.3769910-3-vladimir.oltean@nxp.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210909001736.3769910-1-vladimir.oltean@nxp.com> References: <20210909001736.3769910-1-vladimir.oltean@nxp.com> X-ClientProxiedBy: VI1PR04CA0058.eurprd04.prod.outlook.com (2603:10a6:802:2::29) To VI1PR04MB5136.eurprd04.prod.outlook.com (2603:10a6:803:55::19) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from localhost.localdomain (82.78.148.104) by VI1PR04CA0058.eurprd04.prod.outlook.com (2603:10a6:802:2::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4500.14 via Frontend Transport; Thu, 9 Sep 2021 00:17:51 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: e142508a-3b3b-4c1f-cb46-08d9732742e5 X-MS-TrafficTypeDiagnostic: VE1PR04MB6511: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:8882; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: lJNKz6gwGRPNDdjgyONm15Q9wD5yjn/53gZQ1betJ/ueZRm1E6Kzy8Ddf4zoyZG3AaVWm7VAdIBfuF5Zhp8Ij4J/RJ12SNbflflR7aDpwR/HfpPuiZRt+wO7PuSGOUbeSXYN6rwZIABCm0yi24WfubwEUictAcC/TyfT4/3UgxJLIY0dZjAwp5DqBwRyor3IhrcJ5WnU02E9k5vknWileFvBfMwqtmpDz+0dja756nuOnaD0epXIEoIs9KVL1gO2zRcCSFAuJ8+onHGrwF0HrQCspjmqbbrVjAiOMn6kRoep+u8GI6fn9HJN7h2fYcSg4ZX0tzbs9oxcJyXG8XLvrb1qKBGPklMU7SM1W3ODD6dQQnfqDQazM+E7QtPSEA7eqVW7b42dZBopejWK4PbLMGEd0hBeyMmZdZOFvgtDLwbUzIVWEGxX7QG1nwuvtvV7Ju1kWX5E1yBCoz7tp6Te7bgXpGZSJc2E/G+mrTbLwl0ElFrpGgZ1YYKzB9tLQrhMYuatOUKYXLoMeDNXGUQrTjR8qJ6J5AKYgNGjwe2xH0c1X/DG8hVi3MRGU6SVcXULQtx3CSra6cfz4AgylaVFg0RikCaaAuRK0YE0mFHKipnad1JL5mq2AJH7xEsRZmKsd/LvJFIvfurttC02WzA29sjOzB91K2wMgykKQpf2fwH0lTs+L3cjsaliLtkKi880F/UmAZSQUqolyHcpChcPgYkzEHGxIEV1PAVRbPIhQEcYL3M1YYL4ysiEp9KPdaDPAOIAMzg71kO/MOnLsOhv4Zc4h6Hs7kcbCYsIX0OPeiU= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR04MB5136.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(4636009)(366004)(38350700002)(38100700002)(1076003)(4326008)(8676002)(2906002)(6506007)(66946007)(83380400001)(2616005)(956004)(66556008)(966005)(6486002)(26005)(6512007)(8936002)(66476007)(5660300002)(6666004)(36756003)(6916009)(52116002)(86362001)(44832011)(316002)(508600001)(186003)(30864003)(54906003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: CorfYVT1XHvtc5BsHXple1ia5hBQqbdbN2miZWsS96QlMk9LKYWXNnS22jmnp7t7v70Zf5U9zZKndyNeCHbtRyORxOuWaeAgCLPiFcGLlGqU44pnKyjHj6AEHCwcNwzy/ZIMcxl30YcV3lPahTUcuDoEseVbSZAG7py7d/DUAhMlgDZUkSm+Gg9gI5hgkNnxLqDHDuQz9/3CuZPbDhEOh/X+VuhMxTaPeQzus9jiXyhCwNaj5ZCYL6RtXz2n033VK8fBCzKeAI68o9CIjZrrCc8QbkGJVOIzyXtmJ4C2ACmKLRCAMPdIb/h2NEk6FH01n7t7oKp0hFOFqhIYXaF5jN5UvdGWGv2tMrr2DXibWKLRM0NSAtZrVxEoGWhhn3FpvaltGgR8HZ5DtUxOmR2f0gVZGObXpMVoB9gFThQCNTjHGC/StYYSU5ZxLKQ7bp+WPhwE7hwglHjNx3mzI0HCI8oOt5v3A9zgQoGHw+80pxCtwsfm+UnGCQJ3gif/Ip1taivTfewUI4g0ctyF1MQJ0SsMBqwcsBy4jfFxecWaySe3/x21oqc+IagIO5BNkVvzV9K6wB/HdBbgb9sOX27qvXc7G4plT6Gwwt7d1wZQQMHSQnXS3txvB3Z1fQEcHjna0MhEDJcgx1nbvTDR4hIuIMOy2AKw4bHbnSxoQYEIF1AEH0O44ao6QqRMedGlEiMtUF6vIiMGqatoh0i2CVeq1rNZi6PtKIPcLUgpywyr7HC/lOn0GkEdx43APuBv6k55nVrCII6ibhQSvz4f2s/Grr7oh7A/DUCsbaGcE/Zh1knptJmk4Om0Wad2N3pqOLYTM54R4wBDg15au/5bCJXB0lrZAU1KSMP9TvHs5UMiWrFPrUBKqdgjTOBF3+VvQbtrURGoV5efhXtt3IPAk/5XjvuN8q97tY3+B78+Lj93go7E6+cO30VxyG3jR4GXR/QVlI8DAnP8QX+Ss0PtGmmJoTLahWG1Mv472ldhqchuG7RQ7yMpiJt2PdNb5LXHMckWDL/TDDtZ7/SSpFm8p869hoGYenjSqo1BkEkcTdPRNcpfj4stmpcteEedZFKZ7a6HJeXlQYFnPOEguIrnSwOePySaTmkamU+Ko6/KaahBRfxl8QnDcb38DyLz3EL/NyiUk49r82ipSBK6hAxT+sJpzSBT+oMqyquftjiDrHpqo6e9UuaeiOSCrW1aBlTStIe2Pb4EeWL8uBhfPCrV37XwJxfUYmqV1iN+SSlz5oIlFxhRfqNsNQADJf78N+NQlDMcZvgKOdrmHzykFb1+h4g0oDpA07HaHRqt0nWyd84yFqdW2cBoPAX2T/K6DcY1MQlu X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: e142508a-3b3b-4c1f-cb46-08d9732742e5 X-MS-Exchange-CrossTenant-AuthSource: VI1PR04MB5136.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Sep 2021 00:17:51.4939 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 56k4SjjVunV/ay3ZT1wA3VCfWtXr3m1CUlB+IBIQFGQLTO0QXpdTtHPHvvlAbkMMIqeqRB58WYiEohSWi1TTbQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VE1PR04MB6511 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The DSA driver-facing API for PTP timestamping relies on the assumption that two-step TX timestamps are provided by the hardware in an out-of-band manner, typically by raising an interrupt and making that timestamp available inside some sort of FIFO which is to be accessed over SPI/MDIO/etc. So the API puts .port_txtstamp into dsa_switch_ops, because it is expected that the switch driver needs to save some state (like put the skb into a queue until its TX timestamp arrives). On SJA1110, TX timestamps are provided by the switch as Ethernet packets, so this makes them be received and processed by the tagging protocol driver. This in itself is great, because the timestamps are full 64-bit and do not require reconstruction, and since Ethernet is the fastest I/O method available to/from the switch, PTP timestamps arrive very quickly, no matter how bottlenecked the SPI connection is, because SPI interaction is not needed at all. The problem is that DSA's code structure and strict isolation between the tagging protocol driver and the switch driver breaks the natural code organization. When the tagging protocol driver receives a packet which is classified as a metadata packet containing timestamps, it passes those timestamps one by one to the switch driver, which then proceeds to compare them based on the recorded timestamp ID that was generated in .port_txtstamp. The communication between the tagging protocol and the switch driver is done through a method exported by the switch driver, sja1110_process_meta_tstamp. To satisfy build requirements, we force a dependency to build the tagging protocol driver as a module when the switch driver is a module. The problem is that it turns out DSA tagging protocols really must not depend on the switch driver, because this creates a circular dependency at insmod time, and the switch driver will effectively not load when the tagging protocol driver is missing. To solve this, move the skb queue from struct sja1105_private :: struct sja1105_ptp_data to struct sja1105_private :: struct sja1105_tagger_data. The latter is a data structure for which hacks have already been put into place to be able to create persistent storage per switch that is accessible from the tagging protocol driver (see sja1105_setup_ports). With the skb queue directly accessible from the tagging protocol driver, we can now move sja1110_process_meta_tstamp into the tagging driver itself, and avoid exporting a symbol. Fixes: 566b18c8b752 ("net: dsa: sja1105: implement TX timestamping for SJA1110") Link: https://lore.kernel.org/netdev/20210908220834.d7gmtnwrorhharna@skbuf/ Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105_ptp.c | 45 ++++----------------------- drivers/net/dsa/sja1105/sja1105_ptp.h | 19 ----------- include/linux/dsa/sja1105.h | 29 +++++++++-------- net/dsa/tag_sja1105.c | 43 +++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 73 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c index 691f6dd7e669..54396992a919 100644 --- a/drivers/net/dsa/sja1105/sja1105_ptp.c +++ b/drivers/net/dsa/sja1105/sja1105_ptp.c @@ -64,6 +64,7 @@ enum sja1105_ptp_clk_mode { static int sja1105_change_rxtstamping(struct sja1105_private *priv, bool on) { + struct sja1105_tagger_data *tagger_data = &priv->tagger_data; struct sja1105_ptp_data *ptp_data = &priv->ptp_data; struct sja1105_general_params_entry *general_params; struct sja1105_table *table; @@ -79,7 +80,7 @@ static int sja1105_change_rxtstamping(struct sja1105_private *priv, priv->tagger_data.stampable_skb = NULL; } ptp_cancel_worker_sync(ptp_data->clock); - skb_queue_purge(&ptp_data->skb_txtstamp_queue); + skb_queue_purge(&tagger_data->skb_txtstamp_queue); skb_queue_purge(&ptp_data->skb_rxtstamp_queue); return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING); @@ -452,40 +453,6 @@ bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port, return priv->info->rxtstamp(ds, port, skb); } -void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id, - enum sja1110_meta_tstamp dir, u64 tstamp) -{ - struct sja1105_private *priv = ds->priv; - struct sja1105_ptp_data *ptp_data = &priv->ptp_data; - struct sk_buff *skb, *skb_tmp, *skb_match = NULL; - struct skb_shared_hwtstamps shwt = {0}; - - /* We don't care about RX timestamps on the CPU port */ - if (dir == SJA1110_META_TSTAMP_RX) - return; - - spin_lock(&ptp_data->skb_txtstamp_queue.lock); - - skb_queue_walk_safe(&ptp_data->skb_txtstamp_queue, skb, skb_tmp) { - if (SJA1105_SKB_CB(skb)->ts_id != ts_id) - continue; - - __skb_unlink(skb, &ptp_data->skb_txtstamp_queue); - skb_match = skb; - - break; - } - - spin_unlock(&ptp_data->skb_txtstamp_queue.lock); - - if (WARN_ON(!skb_match)) - return; - - shwt.hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(tstamp)); - skb_complete_tx_timestamp(skb_match, &shwt); -} -EXPORT_SYMBOL_GPL(sja1110_process_meta_tstamp); - /* In addition to cloning the skb which is done by the common * sja1105_port_txtstamp, we need to generate a timestamp ID and save the * packet to the TX timestamping queue. @@ -494,7 +461,6 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb) { struct sk_buff *clone = SJA1105_SKB_CB(skb)->clone; struct sja1105_private *priv = ds->priv; - struct sja1105_ptp_data *ptp_data = &priv->ptp_data; struct sja1105_port *sp = &priv->ports[port]; u8 ts_id; @@ -510,7 +476,7 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb) spin_unlock(&sp->data->meta_lock); - skb_queue_tail(&ptp_data->skb_txtstamp_queue, clone); + skb_queue_tail(&sp->data->skb_txtstamp_queue, clone); } /* Called from dsa_skb_tx_timestamp. This callback is just to clone @@ -953,7 +919,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds) /* Only used on SJA1105 */ skb_queue_head_init(&ptp_data->skb_rxtstamp_queue); /* Only used on SJA1110 */ - skb_queue_head_init(&ptp_data->skb_txtstamp_queue); + skb_queue_head_init(&tagger_data->skb_txtstamp_queue); spin_lock_init(&tagger_data->meta_lock); ptp_data->clock = ptp_clock_register(&ptp_data->caps, ds->dev); @@ -971,6 +937,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds) void sja1105_ptp_clock_unregister(struct dsa_switch *ds) { struct sja1105_private *priv = ds->priv; + struct sja1105_tagger_data *tagger_data = &priv->tagger_data; struct sja1105_ptp_data *ptp_data = &priv->ptp_data; if (IS_ERR_OR_NULL(ptp_data->clock)) @@ -978,7 +945,7 @@ void sja1105_ptp_clock_unregister(struct dsa_switch *ds) del_timer_sync(&ptp_data->extts_timer); ptp_cancel_worker_sync(ptp_data->clock); - skb_queue_purge(&ptp_data->skb_txtstamp_queue); + skb_queue_purge(&tagger_data->skb_txtstamp_queue); skb_queue_purge(&ptp_data->skb_rxtstamp_queue); ptp_clock_unregister(ptp_data->clock); ptp_data->clock = NULL; diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.h b/drivers/net/dsa/sja1105/sja1105_ptp.h index 3c874bb4c17b..3ae6b9fdd492 100644 --- a/drivers/net/dsa/sja1105/sja1105_ptp.h +++ b/drivers/net/dsa/sja1105/sja1105_ptp.h @@ -8,21 +8,6 @@ #if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) -/* Timestamps are in units of 8 ns clock ticks (equivalent to - * a fixed 125 MHz clock). - */ -#define SJA1105_TICK_NS 8 - -static inline s64 ns_to_sja1105_ticks(s64 ns) -{ - return ns / SJA1105_TICK_NS; -} - -static inline s64 sja1105_ticks_to_ns(s64 ticks) -{ - return ticks * SJA1105_TICK_NS; -} - /* Calculate the first base_time in the future that satisfies this * relationship: * @@ -77,10 +62,6 @@ struct sja1105_ptp_data { struct timer_list extts_timer; /* Used only on SJA1105 to reconstruct partial timestamps */ struct sk_buff_head skb_rxtstamp_queue; - /* Used on SJA1110 where meta frames are generated only for - * 2-step TX timestamps - */ - struct sk_buff_head skb_txtstamp_queue; struct ptp_clock_info caps; struct ptp_clock *clock; struct sja1105_ptp_cmd cmd; diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h index 171106202fe5..0485ab2fcc46 100644 --- a/include/linux/dsa/sja1105.h +++ b/include/linux/dsa/sja1105.h @@ -48,6 +48,10 @@ struct sja1105_tagger_data { spinlock_t meta_lock; unsigned long state; u8 ts_id; + /* Used on SJA1110 where meta frames are generated only for + * 2-step TX timestamps + */ + struct sk_buff_head skb_txtstamp_queue; }; struct sja1105_skb_cb { @@ -69,25 +73,20 @@ struct sja1105_port { bool hwts_tx_en; }; -enum sja1110_meta_tstamp { - SJA1110_META_TSTAMP_TX = 0, - SJA1110_META_TSTAMP_RX = 1, -}; - -#if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) - -void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id, - enum sja1110_meta_tstamp dir, u64 tstamp); - -#else +/* Timestamps are in units of 8 ns clock ticks (equivalent to + * a fixed 125 MHz clock). + */ +#define SJA1105_TICK_NS 8 -static inline void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, - u8 ts_id, enum sja1110_meta_tstamp dir, - u64 tstamp) +static inline s64 ns_to_sja1105_ticks(s64 ns) { + return ns / SJA1105_TICK_NS; } -#endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) */ +static inline s64 sja1105_ticks_to_ns(s64 ticks) +{ + return ticks * SJA1105_TICK_NS; +} #if IS_ENABLED(CONFIG_NET_DSA_SJA1105) diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index c054f48541c8..2edede9ddac9 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "dsa_priv.h" @@ -53,6 +54,11 @@ #define SJA1110_TX_TRAILER_LEN 4 #define SJA1110_MAX_PADDING_LEN 15 +enum sja1110_meta_tstamp { + SJA1110_META_TSTAMP_TX = 0, + SJA1110_META_TSTAMP_RX = 1, +}; + /* Similar to is_link_local_ether_addr(hdr->h_dest) but also covers PTP */ static inline bool sja1105_is_link_local(const struct sk_buff *skb) { @@ -520,6 +526,43 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, is_meta); } +static void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, + u8 ts_id, enum sja1110_meta_tstamp dir, + u64 tstamp) +{ + struct sk_buff *skb, *skb_tmp, *skb_match = NULL; + struct dsa_port *dp = dsa_to_port(ds, port); + struct skb_shared_hwtstamps shwt = {0}; + struct sja1105_port *sp = dp->priv; + + if (!dsa_port_is_sja1105(dp)) + return; + + /* We don't care about RX timestamps on the CPU port */ + if (dir == SJA1110_META_TSTAMP_RX) + return; + + spin_lock(&sp->data->skb_txtstamp_queue.lock); + + skb_queue_walk_safe(&sp->data->skb_txtstamp_queue, skb, skb_tmp) { + if (SJA1105_SKB_CB(skb)->ts_id != ts_id) + continue; + + __skb_unlink(skb, &sp->data->skb_txtstamp_queue); + skb_match = skb; + + break; + } + + spin_unlock(&sp->data->skb_txtstamp_queue.lock); + + if (WARN_ON(!skb_match)) + return; + + shwt.hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(tstamp)); + skb_complete_tx_timestamp(skb_match, &shwt); +} + static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header) { u8 *buf = dsa_etype_header_pos_rx(skb) + SJA1110_HEADER_LEN;