From patchwork Thu May 24 06:56:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 136710 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp1823659lji; Wed, 23 May 2018 23:56:43 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpbg0vgu7cQqNiC9aE6SpilW2bSh1DTqomkZzUB/0c4NWOdhTlNBADJQXTUmdhbb1ULapQt X-Received: by 2002:a62:4387:: with SMTP id l7-v6mr5926731pfi.55.1527145003665; Wed, 23 May 2018 23:56:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527145003; cv=none; d=google.com; s=arc-20160816; b=ky+BE/QV0W92F5yK55X2RKVvhwh17yyA5/ggnZbgkUR/ge1UGFO0hFkHPzy+dH721d 6tBAHsKVtC2TkbI4TqJuWfbsz5hWGp3pgR9e+3Q7Uf/7p7TjgE1PQNOI4y/iegjT8z5l NPBxvkfCb3rdS3j6+U8eksd7+kRy/GwPcTcG933VBhqNE0YWiAGrL/SGs+91RoHlgW1G KGXsTPbYljDWyEKyGp/HUIN8APBV4ZLMi+XzPlPSaJuiIy7nb85jSj85nWssh7dl+xJs K/F8au+5mSMS8bmzODJZiqOX5ugK5dIkU50kes3hJOih42lSRqszCOYCt/9BLK6vlMYC 9eZw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=29PIGM2eyn+ush/uq6iK4StKtF4RvOP2hGCCyTLy7Lw=; b=HVyv6wE/e9wsmZhrl7uFSOnsdwLkkc4XH+5mTUytZF1fWxhNgIIXIscUDuXfZ9aqLT 6PSWieUa6sMtwh5LKEUlK203SBTvRfJW2J0/YpU9Fz6J+MV0F/2++ltjlD2A2/AeUdcP RmvlSDrICbS0+Bd2o7AVvYbtirHeiuBRGp8NGLEULU1WckYfOXEcgVrAAvj5osYE1sQz DbCdSHwcQogsTZTbfYWE2tnCK+h5otv9ycengzR6Q0OeUMjz1UcmjueXUOgJ5NZNzEj9 VZs4D0XHYJbeXuwkm5UriGDjJkhRMV8lxqvNhE1SJffHmXYtKmPl8WAQJ8ohzpvCOeYE lrUQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Mk5lqLu/; spf=pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=netdev-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v2-v6si8349741plo.577.2018.05.23.23.56.43; Wed, 23 May 2018 23:56:43 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Mk5lqLu/; spf=pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=netdev-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935624AbeEXG4m (ORCPT + 9 others); Thu, 24 May 2018 02:56:42 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:39352 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935614AbeEXG4i (ORCPT ); Thu, 24 May 2018 02:56:38 -0400 Received: by mail-wm0-f67.google.com with SMTP id f8-v6so1997159wmc.4 for ; Wed, 23 May 2018 23:56:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=29PIGM2eyn+ush/uq6iK4StKtF4RvOP2hGCCyTLy7Lw=; b=Mk5lqLu/sYUZ1wTSMHndtMB6ymFHeJ/BYZoUThM1y3r/0ZpEg5SV4a968vdbXxy7Bh merlB+valB7twzoeLijdSKcUMAIm2jdyn1YNnVYonP7030z7PSsEnoCCYMorfzvs+siM DEuvFvZLe2UKm4spYi09VGhcnvnVT9aCKqEco= 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=29PIGM2eyn+ush/uq6iK4StKtF4RvOP2hGCCyTLy7Lw=; b=g3r1R4qF7a3sY5T4lU0dV9Lb/O37/0t5NtWIO92ZaFnStQWgLLfq/uaeRyHdKc09vq UYJBeah3HV/IOKBKreIvlZFj8oJc9idzz1ww98EVtCjQApruXFS3EAqVYByE4DnMNbnU 18M7K65zmlIr44n6bjl38ED5I4FVvNvlM2+8emA0cGBQjzxBq4T/TXP2NETNB6jY/O0u Y1q2aJzNGv42nwvehIZ9hD+6f0S5agTduOmPpgK812fp3x6oITpisRirbYv8RvEWDmkh /xsW5clV7ySaxZt+R6UI8+xeXmsOFrMtLumVLrxe6cPPOFZOeCAqlf2dcjVxKQdqcnzk LuEw== X-Gm-Message-State: ALKqPwcI6JaT7H4vnbfO1NSHQv94YND8yZc+4/bm+KSbxPiepKN+ug2g I8OfB9qEvp4APosGBDL95fYa6i63G0M= X-Received: by 2002:a1c:c013:: with SMTP id q19-v6mr6059965wmf.49.1527144996509; Wed, 23 May 2018 23:56:36 -0700 (PDT) Received: from localhost.localdomain ([2a02:587:460a:f200:b540:ba10:add4:9422]) by smtp.gmail.com with ESMTPSA id t198-v6sm4795257wmt.23.2018.05.23.23.56.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 23 May 2018 23:56:35 -0700 (PDT) From: Ilias Apalodimas To: netdev@vger.kernel.org, grygorii.strashko@ti.com, ivan.khoronzhuk@linaro.org, nsekhar@ti.com, jiri@resnulli.us, ivecera@redhat.com Cc: francois.ozog@linaro.org, yogeshs@ti.com, spatton@ti.com, Ilias Apalodimas Subject: [PATCH 1/4] cpsw: move common headers definitions to cpsw_priv.h Date: Thu, 24 May 2018 09:56:21 +0300 Message-Id: <1527144984-31236-2-git-send-email-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1527144984-31236-1-git-send-email-ilias.apalodimas@linaro.org> References: <1527144984-31236-1-git-send-email-ilias.apalodimas@linaro.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Signed-off-by: Ilias Apalodimas --- drivers/net/ethernet/ti/cpsw.c | 111 +--------------------------- drivers/net/ethernet/ti/cpsw_priv.h | 141 ++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 110 deletions(-) create mode 100644 drivers/net/ethernet/ti/cpsw_priv.h -- 2.7.4 diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 3037127..b16e7cf 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -41,6 +41,7 @@ #include "cpsw.h" #include "cpsw_ale.h" +#include "cpsw_priv.h" #include "cpts.h" #include "davinci_cpdma.h" @@ -88,7 +89,6 @@ do { \ #define CPSW_VERSION_3 0x19010f #define CPSW_VERSION_4 0x190112 -#define HOST_PORT_NUM 0 #define CPSW_ALE_PORTS_NUM 3 #define SLIVER_SIZE 0x40 @@ -309,16 +309,6 @@ struct cpsw_ss_regs { #define CPSW_MAX_BLKS_TX_SHIFT 4 #define CPSW_MAX_BLKS_RX 5 -struct cpsw_host_regs { - u32 max_blks; - u32 blk_cnt; - u32 tx_in_ctl; - u32 port_vlan; - u32 tx_pri_map; - u32 cpdma_tx_pri_map; - u32 cpdma_rx_chan_map; -}; - struct cpsw_sliver_regs { u32 id_ver; u32 mac_control; @@ -370,105 +360,6 @@ struct cpsw_hw_stats { u32 rxdmaoverruns; }; -struct cpsw_slave_data { - struct device_node *phy_node; - char phy_id[MII_BUS_ID_SIZE]; - int phy_if; - u8 mac_addr[ETH_ALEN]; - u16 dual_emac_res_vlan; /* Reserved VLAN for DualEMAC */ -}; - -struct cpsw_platform_data { - struct cpsw_slave_data *slave_data; - u32 ss_reg_ofs; /* Subsystem control register offset */ - u32 channels; /* number of cpdma channels (symmetric) */ - u32 slaves; /* number of slave cpgmac ports */ - u32 active_slave; /* time stamping, ethtool and SIOCGMIIPHY slave */ - u32 ale_entries; /* ale table size */ - u32 bd_ram_size; /*buffer descriptor ram size */ - u32 mac_control; /* Mac control register */ - u16 default_vlan; /* Def VLAN for ALE lookup in VLAN aware mode*/ - bool dual_emac; /* Enable Dual EMAC mode */ -}; - -struct cpsw_slave { - void __iomem *regs; - struct cpsw_sliver_regs __iomem *sliver; - int slave_num; - u32 mac_control; - struct cpsw_slave_data *data; - struct phy_device *phy; - struct net_device *ndev; - u32 port_vlan; -}; - -static inline u32 slave_read(struct cpsw_slave *slave, u32 offset) -{ - return readl_relaxed(slave->regs + offset); -} - -static inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset) -{ - writel_relaxed(val, slave->regs + offset); -} - -struct cpsw_vector { - struct cpdma_chan *ch; - int budget; -}; - -struct cpsw_common { - struct device *dev; - struct cpsw_platform_data data; - struct napi_struct napi_rx; - struct napi_struct napi_tx; - struct cpsw_ss_regs __iomem *regs; - struct cpsw_wr_regs __iomem *wr_regs; - u8 __iomem *hw_stats; - struct cpsw_host_regs __iomem *host_port_regs; - u32 version; - u32 coal_intvl; - u32 bus_freq_mhz; - int rx_packet_max; - struct cpsw_slave *slaves; - struct cpdma_ctlr *dma; - struct cpsw_vector txv[CPSW_MAX_QUEUES]; - struct cpsw_vector rxv[CPSW_MAX_QUEUES]; - struct cpsw_ale *ale; - bool quirk_irq; - bool rx_irq_disabled; - bool tx_irq_disabled; - u32 irqs_table[IRQ_NUM]; - struct cpts *cpts; - int rx_ch_num, tx_ch_num; - int speed; - int usage_count; -}; - -struct cpsw_priv { - struct net_device *ndev; - struct device *dev; - u32 msg_enable; - u8 mac_addr[ETH_ALEN]; - bool rx_pause; - bool tx_pause; - u32 emac_port; - struct cpsw_common *cpsw; -}; - -struct cpsw_stats { - char stat_string[ETH_GSTRING_LEN]; - int type; - int sizeof_stat; - int stat_offset; -}; - -enum { - CPSW_STATS, - CPDMA_RX_STATS, - CPDMA_TX_STATS, -}; - #define CPSW_STAT(m) CPSW_STATS, \ sizeof(((struct cpsw_hw_stats *)0)->m), \ offsetof(struct cpsw_hw_stats, m) diff --git a/drivers/net/ethernet/ti/cpsw_priv.h b/drivers/net/ethernet/ti/cpsw_priv.h new file mode 100644 index 0000000..3b02a83 --- /dev/null +++ b/drivers/net/ethernet/ti/cpsw_priv.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include + +#define HOST_PORT_NUM 0 +#define IRQ_NUM 2 +#define CPSW_MAX_QUEUES 8 + +#define CPSW_VERSION_1 0x19010a +#define CPSW_VERSION_2 0x19010c +#define CPSW_VERSION_3 0x19010f +#define CPSW_VERSION_4 0x190112 + +/* CPSW_PORT_V1 */ +#define CPSW1_MAX_BLKS 0x00 /* Maximum FIFO Blocks */ +#define CPSW1_BLK_CNT 0x04 /* FIFO Block Usage Count (Read Only) */ +#define CPSW1_TX_IN_CTL 0x08 /* Transmit FIFO Control */ +#define CPSW1_PORT_VLAN 0x0c /* VLAN Register */ +#define CPSW1_TX_PRI_MAP 0x10 /* Tx Header Priority to Switch Pri Mapping */ +#define CPSW1_TS_CTL 0x14 /* Time Sync Control */ +#define CPSW1_TS_SEQ_LTYPE 0x18 /* Time Sync Sequence ID Offset and Msg Type */ +#define CPSW1_TS_VLAN 0x1c /* Time Sync VLAN1 and VLAN2 */ + +/* CPSW_PORT_V2 */ +#define CPSW2_CONTROL 0x00 /* Control Register */ +#define CPSW2_MAX_BLKS 0x08 /* Maximum FIFO Blocks */ +#define CPSW2_BLK_CNT 0x0c /* FIFO Block Usage Count (Read Only) */ +#define CPSW2_TX_IN_CTL 0x10 /* Transmit FIFO Control */ +#define CPSW2_PORT_VLAN 0x14 /* VLAN Register */ +#define CPSW2_TX_PRI_MAP 0x18 /* Tx Header Priority to Switch Pri Mapping */ +#define CPSW2_TS_SEQ_MTYPE 0x1c /* Time Sync Sequence ID Offset and Msg Type */ + +struct cpsw_slave_data { + struct device_node *phy_node; + char phy_id[MII_BUS_ID_SIZE]; + int phy_if; + u8 mac_addr[ETH_ALEN]; + u16 dual_emac_res_vlan; /* Reserved VLAN for DualEMAC */ +}; + +struct cpsw_platform_data { + struct cpsw_slave_data *slave_data; + u32 ss_reg_ofs; /* Subsystem control register offset */ + u32 channels; /* number of cpdma channels (symmetric) */ + u32 slaves; /* number of slave cpgmac ports */ + u32 active_slave; /* time stamping, ethtool and SIOCGMIIPHY slave */ + u32 ale_entries; /* ale table size */ + u32 bd_ram_size; /*buffer descriptor ram size */ + u32 mac_control; /* Mac control register */ + u16 default_vlan; /* Def VLAN for ALE lookup in VLAN aware mode*/ + bool dual_emac; /* Enable Dual EMAC mode */ +}; + +struct cpsw_slave { + void __iomem *regs; + struct cpsw_sliver_regs __iomem *sliver; + int slave_num; + u32 mac_control; + struct cpsw_slave_data *data; + struct phy_device *phy; + struct net_device *ndev; + u32 port_vlan; +}; + +struct cpsw_vector { + struct cpdma_chan *ch; + int budget; +}; + +struct cpsw_common { + struct device *dev; + struct cpsw_platform_data data; + struct napi_struct napi_rx; + struct napi_struct napi_tx; + struct cpsw_ss_regs __iomem *regs; + struct cpsw_wr_regs __iomem *wr_regs; + u8 __iomem *hw_stats; + struct cpsw_host_regs __iomem *host_port_regs; + u32 version; + u32 coal_intvl; + u32 bus_freq_mhz; + int rx_packet_max; + struct cpsw_slave *slaves; + struct cpdma_ctlr *dma; + struct cpsw_vector txv[CPSW_MAX_QUEUES]; + struct cpsw_vector rxv[CPSW_MAX_QUEUES]; + struct cpsw_ale *ale; + bool quirk_irq; + bool rx_irq_disabled; + bool tx_irq_disabled; + u32 irqs_table[IRQ_NUM]; + struct cpts *cpts; + int rx_ch_num, tx_ch_num; + int speed; + int usage_count; +}; + +struct cpsw_priv { + struct net_device *ndev; + struct device *dev; + u32 msg_enable; + u8 mac_addr[ETH_ALEN]; + bool rx_pause; + bool tx_pause; + u8 port_state[3]; + u32 emac_port; + struct cpsw_common *cpsw; +}; + +struct cpsw_stats { + char stat_string[ETH_GSTRING_LEN]; + int type; + int sizeof_stat; + int stat_offset; +}; + +enum { + CPSW_STATS, + CPDMA_RX_STATS, + CPDMA_TX_STATS, +}; + +struct cpsw_host_regs { + u32 max_blks; + u32 blk_cnt; + u32 tx_in_ctl; + u32 port_vlan; + u32 tx_pri_map; + u32 cpdma_tx_pri_map; + u32 cpdma_rx_chan_map; +}; + +static inline u32 slave_read(struct cpsw_slave *slave, u32 offset) +{ + return readl_relaxed(slave->regs + offset); +} + +static inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset) +{ + writel_relaxed(val, slave->regs + offset); +} From patchwork Thu May 24 06:56:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 136711 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp1823707lji; Wed, 23 May 2018 23:56:49 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrnyFrQuguzERIFze8zXrQJVcalDHE5ejOMyzGQmymQqo7sLOwe453yani+jz4cpZuzQ94L X-Received: by 2002:a65:5002:: with SMTP id f2-v6mr4705875pgo.38.1527145009031; Wed, 23 May 2018 23:56:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527145009; cv=none; d=google.com; s=arc-20160816; b=Huxg1O8bGBUtbfB+kRv+b3gys+VeOC9kbpndRMOYtNs6jW2gjaNMhkCJ00aSos0cuA uyTXJAaO2o/Ph+CsMvHhReg0KXXBuF/Vx/KK8Rqaw/ouOBgSy7oUjCtBRfiDtWBbpVDX DN4pipd0SLzfKROnU5ORpMPrjtOy18AB6cYX1Yterc89OrZGfC4EMemS10m97FQLmzLh QQuHsOrGZgaWqmlyR0n1P7q/8xf8k7gRc129znfbN/asT9yLKBxMOcGiFz2kfFYapTtj wvpNPv6yHJ8IMof4sawYNAYDtRayfvM73x1BOJyzjbTwDBH8A3ar/voWgdA6rVAZNp1q 57ow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=6DZQ8MU0f2IdRnyACXRr/kFKgxcXpV6iT3dSNDS4xn4=; b=gPtrnJocMN/jDMGcUFge/nUly2azBWWalPZTeGD4ywNO+QextFdO7fIZnCrnqSWFsn bWymF9IogCbM4/5JW5X8YL51SDl5P5z8GezBCwjeML1gKJW4TvhFJTf8prkM8mNkli/2 vIjlqNle3+zrcOzW7EwdvZuQRdK0BdbFfsngK1IWRCYP0UpnI+SAO2UuHkGhgrwoRtdn zxjWqostsFqnhZboWhHMtxWkqvzdMekk1YCBud1tmLk2B2pI2e5Rzsxs0rl7NEYQrc+J fU53/rdPXBBDWr5J6G3/YD5gxR0Tl9+LCt5cTXKlJ3s1yB/IxSkjxYnJbvFRNWF44vvk 5f2A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kDfjPZW1; spf=pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=netdev-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v2-v6si8349741plo.577.2018.05.23.23.56.48; Wed, 23 May 2018 23:56:49 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kDfjPZW1; spf=pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=netdev-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964820AbeEXG4q (ORCPT + 9 others); Thu, 24 May 2018 02:56:46 -0400 Received: from mail-wr0-f196.google.com ([209.85.128.196]:32772 "EHLO mail-wr0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935530AbeEXG4j (ORCPT ); Thu, 24 May 2018 02:56:39 -0400 Received: by mail-wr0-f196.google.com with SMTP id a15-v6so997966wrm.0 for ; Wed, 23 May 2018 23:56:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6DZQ8MU0f2IdRnyACXRr/kFKgxcXpV6iT3dSNDS4xn4=; b=kDfjPZW1h37BSBMLzM2Gj3ycGPjzrG4Q7RfYzsDvbhmUpzzCAE7qgPptftOO9aSD3V 04rBIEI/oYl/CTBgqq69SPKFmphS44xCZMVOE3llULXDzO2HZgHh0Z0Uii+Ms0ScOx5x gojwgg6gIePXfF4kZ6zdjHkCLkT+rS205AVN4= 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=6DZQ8MU0f2IdRnyACXRr/kFKgxcXpV6iT3dSNDS4xn4=; b=KwPrpZdWoTb68iHecz31vcliSlBqLGmPNqKoVm6u3sz10Vc+Dg4c8RY0bM8dDZAJ0K uWSvaIWeK0A5VuUwU/TmmrANZyWY3pwFmww4yjGZoxGW/V+2oTPgYw8Ux1RHdf/1eLCf w8P533T/lzYkkrpbjHwGIZxBuTDJYxJqimwA3GxjHLB8jFaQwvkX+cGBwe10hAkFlPRE BZrKqiKwg6EmO5t0cITGq8Phc6MBS/lWCOp+DCGRhGsCFrRQ/lKFtu40RJ38oZzXXoSF CalmVWr4E+S7EAQaTWJt6vfqdEdfBI5gpdv1sNQBMmdRFPWd3/91VWjJgddgI0mq0bJr j+rA== X-Gm-Message-State: ALKqPwf/LVN48kkkQyHYa/kIl/ZvYCWggiPp/2D1gMqAZT91zXMyTV2c 3vgKu7pZTxCWpiw1FCsLobby55ecHCM= X-Received: by 2002:adf:a645:: with SMTP id k63-v6mr1914966wrc.231.1527144998291; Wed, 23 May 2018 23:56:38 -0700 (PDT) Received: from localhost.localdomain ([2a02:587:460a:f200:b540:ba10:add4:9422]) by smtp.gmail.com with ESMTPSA id t198-v6sm4795257wmt.23.2018.05.23.23.56.36 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 23 May 2018 23:56:37 -0700 (PDT) From: Ilias Apalodimas To: netdev@vger.kernel.org, grygorii.strashko@ti.com, ivan.khoronzhuk@linaro.org, nsekhar@ti.com, jiri@resnulli.us, ivecera@redhat.com Cc: francois.ozog@linaro.org, yogeshs@ti.com, spatton@ti.com, Ilias Apalodimas Subject: [PATCH 2/4] cpsw_ale: add support functions for switchdev Date: Thu, 24 May 2018 09:56:22 +0300 Message-Id: <1527144984-31236-3-git-send-email-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1527144984-31236-1-git-send-email-ilias.apalodimas@linaro.org> References: <1527144984-31236-1-git-send-email-ilias.apalodimas@linaro.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Signed-off-by: Ilias Apalodimas --- drivers/net/ethernet/ti/cpsw_ale.c | 129 +++++++++++++++++++++++++++++++++++++ drivers/net/ethernet/ti/cpsw_ale.h | 8 +++ 2 files changed, 137 insertions(+) -- 2.7.4 diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c index 93dc05c..0b7383f 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.c +++ b/drivers/net/ethernet/ti/cpsw_ale.c @@ -409,6 +409,41 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask, } EXPORT_SYMBOL_GPL(cpsw_ale_del_mcast); +static int cpsw_ale_read_mc(struct cpsw_ale *ale, u8 *addr, int flags, u16 vid) +{ + u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; + int idx; + + idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0); + if (idx >= 0) + cpsw_ale_read(ale, idx, ale_entry); + + return cpsw_ale_get_port_mask(ale_entry, ale->port_mask_bits); +} + +int cpsw_ale_mcast_add_modify(struct cpsw_ale *ale, u8 *addr, int port_mask, + int flags, u16 vid, int mcast_state) +{ + int mcast_members, ret; + + mcast_members = cpsw_ale_read_mc(ale, addr, flags, vid) | port_mask; + ret = cpsw_ale_add_mcast(ale, addr, mcast_members, flags, vid, 0); + + return ret; +} + +int cpsw_ale_mcast_del_modify(struct cpsw_ale *ale, u8 *addr, int port_mask, + int flags, u16 vid) +{ + int mcast_members, ret; + + mcast_members = cpsw_ale_read_mc(ale, addr, flags, vid) & ~port_mask; + ret = cpsw_ale_del_mcast(ale, addr, mcast_members, flags, vid); + + return ret; +} +EXPORT_SYMBOL_GPL(cpsw_ale_mcast_del_modify); + /* ALE NetCP NU switch specific vlan functions */ static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry, int reg_mcast, int unreg_mcast) @@ -424,6 +459,52 @@ static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry, writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx)); } +static int cpsw_ale_read_untagged(struct cpsw_ale *ale, u16 vid) +{ + u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; + int idx; + + idx = cpsw_ale_match_vlan(ale, vid); + if (idx >= 0) + cpsw_ale_read(ale, idx, ale_entry); + + return cpsw_ale_get_vlan_untag_force(ale_entry, ale->vlan_field_bits); +} + +/* returns mask of current members for specificed vlan */ +static int cpsw_ale_read_vlan_members(struct cpsw_ale *ale, u16 vid) +{ + u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; + int idx; + + idx = cpsw_ale_match_vlan(ale, vid); + if (idx >= 0) + cpsw_ale_read(ale, idx, ale_entry); + + return cpsw_ale_get_vlan_member_list(ale_entry, ale->vlan_field_bits); +} + +/* returns mask of registered/unregistered multicast registration */ +static int cpsw_ale_read_reg_unreg_mc(struct cpsw_ale *ale, u16 vid, bool unreg) +{ + u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; + int idx; + int ret; + + idx = cpsw_ale_match_vlan(ale, vid); + if (idx >= 0) + cpsw_ale_read(ale, idx, ale_entry); + + if (unreg) + ret = cpsw_ale_get_vlan_unreg_mcast(ale_entry, + ale->vlan_field_bits); + else + ret = cpsw_ale_get_vlan_reg_mcast(ale_entry, + ale->vlan_field_bits); + + return ret; +} + int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag, int reg_mcast, int unreg_mcast) { @@ -482,6 +563,54 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask) } EXPORT_SYMBOL_GPL(cpsw_ale_del_vlan); +int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask, + int untag_mask, int reg_mask, int unreg_mask) +{ + int ret = 0; + int vlan_members = cpsw_ale_read_vlan_members(ale, vid) & ~port_mask; + int reg_mcast_members = + cpsw_ale_read_reg_unreg_mc(ale, vid, 0) & ~port_mask; + int unreg_mcast_members = + cpsw_ale_read_reg_unreg_mc(ale, vid, 1) & ~port_mask; + int untag_members = cpsw_ale_read_untagged(ale, vid) & ~port_mask; + + vlan_members |= port_mask; + untag_members |= untag_mask; + reg_mcast_members |= reg_mask; + unreg_mcast_members |= unreg_mask; + + ret = cpsw_ale_add_vlan(ale, vid, vlan_members, untag_members, + reg_mcast_members, unreg_mcast_members); + if (ret) { + dev_err(ale->params.dev, "Unable to add vlan\n"); + return ret; + } + dev_dbg(ale->params.dev, "port mask 0x%x untag 0x%x\n", vlan_members, + untag_mask); + + return ret; +} +EXPORT_SYMBOL_GPL(cpsw_ale_vlan_add_modify); + +int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask) +{ + int ret = 0; + int vlan_members; + + vlan_members = cpsw_ale_read_vlan_members(ale, vid); + vlan_members &= ~port_mask; + + ret = cpsw_ale_del_vlan(ale, vid, vlan_members); + if (ret) { + dev_err(ale->params.dev, "Unable to del vlan\n"); + return ret; + } + dev_dbg(ale->params.dev, "port mask 0x%x\n", port_mask); + + return ret; +} +EXPORT_SYMBOL_GPL(cpsw_ale_vlan_del_modify); + void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti) { u32 ale_entry[ALE_ENTRY_WORDS]; diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h index d4fe901..bc29616 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.h +++ b/drivers/net/ethernet/ti/cpsw_ale.h @@ -123,4 +123,12 @@ int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control, int value); void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data); +int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask, + int untag_mask, int reg_mcast, int unreg_mcast); +int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask); +int cpsw_ale_mcast_add_modify(struct cpsw_ale *ale, u8 *addr, int port_mask, + int flags, u16 vid, int mcast_state); +int cpsw_ale_mcast_del_modify(struct cpsw_ale *ale, u8 *addr, int port, + int flags, u16 vid); + #endif From patchwork Thu May 24 06:56:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 136712 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp1823739lji; Wed, 23 May 2018 23:56:51 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqW313hs8gmLITVnRmg+T3gXZCefNFK2AJUh7OWPEvE9SJyFJFCvOnG4V6vNTLTGKFUuInU X-Received: by 2002:a63:7f07:: with SMTP id a7-v6mr4788407pgd.173.1527145011213; Wed, 23 May 2018 23:56:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527145011; cv=none; d=google.com; s=arc-20160816; b=zd2V3DLazj9Ut5OrgRMYpSgbHjZ5J88WyOQze/5PMoyzttOvXH4Yoq/HLYV0KpHBkH uMdGWGDtn4BdmpEpOEZvQCnGI8IXejJAAfvSmf55nnqd/vXh/pmPHcdr+Jh/o6FYsogW aSfDLt7VkGhNZLO0ehBuoVIVsh9/vYOaukfCcyK5NWnIk81qwjyZ1PcSDlmrrHJR5o0x 4+Y21ZXxd89NXaGnGB6kFnF7qAPP2suu3NGm4dJ0IxRRH7w/oM22hAtBFL8Q3N2cP5uY cIBp8ec3G0yEm8jZ5i2K2v2G+LWTBOErguu6tO6fs3kcqTlAE9NdCPXGZQBW83N0FWHC C4uQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=ZYsWLC9UknldjSMzM5uWFFbZjt/mkoaIVMNBunWcTn8=; b=Sv9RW4QObB99e5qGcOj8Tl7RU2uVjPa3zOgzs+VDgbG8k+/FQzFta7P4b2FKTHzyA2 WoWnfqy6iLt01J7+Qayd6vJzzXI8vVGy1g3U6qsvjcKnlVSzhBWJKz8LZsT7EwUa4hp+ RgdDpu/Bpk35JqEQ7JvxKE0aQPfqeo0uAEXhfE+d44GJDZrIcuTcUuMWdNwQsVtFMbeT wNLZlUbs/to9r+DOQfl7ql2KY5xP/lxrzr+qSJMOInvsRvPC4Udzq61SX7VqBfy1OhS6 UwXE+TwkU1JyWCWOxwbPjWG+vyCcYBJFXv8DV4i7ORZSrhlOPq9c6EyKkOC+L+YdgAHE Uu5A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YSCW1d2S; spf=pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=netdev-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v2-v6si8349741plo.577.2018.05.23.23.56.51; Wed, 23 May 2018 23:56:51 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YSCW1d2S; spf=pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=netdev-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964876AbeEXG4t (ORCPT + 9 others); Thu, 24 May 2018 02:56:49 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:38156 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935619AbeEXG4l (ORCPT ); Thu, 24 May 2018 02:56:41 -0400 Received: by mail-wm0-f65.google.com with SMTP id m129-v6so1993418wmb.3 for ; Wed, 23 May 2018 23:56:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ZYsWLC9UknldjSMzM5uWFFbZjt/mkoaIVMNBunWcTn8=; b=YSCW1d2SpQu/CBNUAggNHT4Jk3iWuMbzfErkxZHhrsX6ZSJkDVMo1AN+SO2kQ0+mDC Re1kw5H5HOAFNg+z9oFP1ganwPjBFnQayr9mFAHk0xJRC06Nmub4plIS+uqKKWYOBL6k gDb3f8ztyQLuFt0XQSG5iucHfpyjGTxcbmNsU= 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=ZYsWLC9UknldjSMzM5uWFFbZjt/mkoaIVMNBunWcTn8=; b=I+gMm7B8AJzLfLe8AIniHPlG189NRSs/kvMVu3L5zjzYjjmhXv4dfXQsVlGQ0VhUFK /Eicoydc2xBr4e/ZRpPAhivgUhei5YOiHilqd15aLjJXkqlS1qxhgfkE+cDdwTGG4I60 tEKzYjNrqgCnD5gPUEMU9dWzcLQWO81wNYu783EguNut4jmdX25PFdoUL/w+7J6+3mq+ 9AoqlFNtQhgaz+J9701P/EbDzAy56IUtYb3zeMMF/jQbuEHPKyDf50qfipGj9kKwwIha jaJ/izqiOmIdRWrMLyPH/t4RUT3fb6wNqmYWKUCbLBzXd0H1obqtg5HjskIyahLrA7cv PbKw== X-Gm-Message-State: ALKqPwdF7fSCic0Bbf+ASS0iBQd1EHtg6kETSpiDn6KTS94AmCFyzuJQ cxDcZNiHpaQH+Y9eCRdJ9nCCIyiqiSE= X-Received: by 2002:a1c:91c4:: with SMTP id t187-v6mr5750818wmd.19.1527145000073; Wed, 23 May 2018 23:56:40 -0700 (PDT) Received: from localhost.localdomain ([2a02:587:460a:f200:b540:ba10:add4:9422]) by smtp.gmail.com with ESMTPSA id t198-v6sm4795257wmt.23.2018.05.23.23.56.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 23 May 2018 23:56:39 -0700 (PDT) From: Ilias Apalodimas To: netdev@vger.kernel.org, grygorii.strashko@ti.com, ivan.khoronzhuk@linaro.org, nsekhar@ti.com, jiri@resnulli.us, ivecera@redhat.com Cc: francois.ozog@linaro.org, yogeshs@ti.com, spatton@ti.com, Ilias Apalodimas Subject: [PATCH 3/4] cpsw_switchdev: add switchdev support files Date: Thu, 24 May 2018 09:56:23 +0300 Message-Id: <1527144984-31236-4-git-send-email-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1527144984-31236-1-git-send-email-ilias.apalodimas@linaro.org> References: <1527144984-31236-1-git-send-email-ilias.apalodimas@linaro.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Signed-off-by: Ilias Apalodimas --- drivers/net/ethernet/ti/Kconfig | 9 + drivers/net/ethernet/ti/Makefile | 1 + drivers/net/ethernet/ti/cpsw_switchdev.c | 299 +++++++++++++++++++++++++++++++ drivers/net/ethernet/ti/cpsw_switchdev.h | 4 + 4 files changed, 313 insertions(+) create mode 100644 drivers/net/ethernet/ti/cpsw_switchdev.c create mode 100644 drivers/net/ethernet/ti/cpsw_switchdev.h -- 2.7.4 diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index 48a541e..b22ae7d 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -73,6 +73,15 @@ config TI_CPSW To compile this driver as a module, choose M here: the module will be called cpsw. +config TI_CPSW_SWITCHDEV + bool "TI CPSW switchdev support" + depends on TI_CPSW + depends on NET_SWITCHDEV + help + Enable switchdev support on TI's CPSW Ethernet Switch. + + This will allow you to configure the switch using standard tools. + config TI_CPTS bool "TI Common Platform Time Sync (CPTS) Support" depends on TI_CPSW || TI_KEYSTONE_NETCP diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index 0be551d..3926c6a 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o obj-$(CONFIG_TI_CPSW_ALE) += cpsw_ale.o obj-$(CONFIG_TI_CPTS_MOD) += cpts.o obj-$(CONFIG_TI_CPSW) += ti_cpsw.o +ti_cpsw-objs:= cpsw_switchdev.o ti_cpsw-y := cpsw.o obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o diff --git a/drivers/net/ethernet/ti/cpsw_switchdev.c b/drivers/net/ethernet/ti/cpsw_switchdev.c new file mode 100644 index 0000000..bf8c1bf --- /dev/null +++ b/drivers/net/ethernet/ti/cpsw_switchdev.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Texas Instruments switchdev Driver + * + * Copyright (C) 2018 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include "cpsw.h" +#include "cpsw_priv.h" +#include "cpsw_ale.h" + +static u32 cpsw_switchdev_get_ver(struct net_device *ndev) +{ + struct cpsw_priv *priv = netdev_priv(ndev); + struct cpsw_common *cpsw = priv->cpsw; + + return cpsw->version; +} + +static int cpsw_port_attr_set(struct net_device *dev, + const struct switchdev_attr *attr, + struct switchdev_trans *trans) +{ + return -EOPNOTSUPP; +} + +static int cpsw_port_attr_get(struct net_device *dev, + struct switchdev_attr *attr) +{ + u32 cpsw_ver; + int err = 0; + + switch (attr->id) { + case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: + cpsw_ver = cpsw_switchdev_get_ver(dev); + attr->u.ppid.id_len = sizeof(cpsw_ver); + memcpy(&attr->u.ppid.id, &cpsw_ver, attr->u.ppid.id_len); + break; + default: + return -EOPNOTSUPP; + } + + return err; +} + +static u16 cpsw_get_pvid(struct cpsw_priv *priv) +{ + struct cpsw_common *cpsw = priv->cpsw; + u32 __iomem *port_vlan_reg; + u32 pvid; + + if (priv->emac_port) { + int reg = CPSW2_PORT_VLAN; + + if (cpsw->version == CPSW_VERSION_1) + reg = CPSW1_PORT_VLAN; + pvid = slave_read(cpsw->slaves + (priv->emac_port - 1), reg); + } else { + port_vlan_reg = &cpsw->host_port_regs->port_vlan; + pvid = readl(port_vlan_reg); + } + + pvid = pvid & 0xfff; + + return pvid; +} + +static void cpsw_set_pvid(struct cpsw_priv *priv, u16 vid, bool cfi, u32 cos) +{ + struct cpsw_common *cpsw = priv->cpsw; + void __iomem *port_vlan_reg; + u32 pvid; + + pvid = vid; + pvid |= cfi ? BIT(12) : 0; + pvid |= (cos & 0x7) << 13; + + if (priv->emac_port) { + int reg = CPSW2_PORT_VLAN; + + if (cpsw->version == CPSW_VERSION_1) + reg = CPSW1_PORT_VLAN; + /* no barrier */ + slave_write(cpsw->slaves + (priv->emac_port - 1), pvid, reg); + } else { + /* CPU port */ + port_vlan_reg = &cpsw->host_port_regs->port_vlan; + writel(pvid, port_vlan_reg); + } +} + +static int cpsw_port_vlan_add(struct cpsw_priv *priv, bool untag, bool pvid, + u16 vid) +{ + struct cpsw_common *cpsw = priv->cpsw; + int port_mask = BIT(priv->emac_port); + int unreg_mcast_mask = 0; + int reg_mcast_mask = 0; + int untag_mask = 0; + int ret = 0; + + if (priv->ndev->flags & IFF_ALLMULTI) + unreg_mcast_mask = port_mask; + + if (priv->ndev->flags & IFF_MULTICAST) + reg_mcast_mask = port_mask; + + if (untag) + untag_mask = port_mask; + + ret = cpsw_ale_vlan_add_modify(cpsw->ale, vid, port_mask, untag_mask, + reg_mcast_mask, unreg_mcast_mask); + if (ret) { + dev_err(priv->dev, "Unable to add vlan\n"); + return ret; + } + + if (!pvid) + return ret; + + cpsw_set_pvid(priv, vid, 0, 0); + + dev_dbg(priv->dev, "VID: %u dev: %s port: %u\n", vid, + priv->ndev->name, priv->emac_port); + + return ret; +} + +static int cpsw_port_vlan_del(struct cpsw_priv *priv, u16 vid) +{ + struct cpsw_common *cpsw = priv->cpsw; + int port_mask = BIT(priv->emac_port); + int ret = 0; + + ret = cpsw_ale_vlan_del_modify(cpsw->ale, vid, port_mask); + if (ret != 0) + return ret; + + ret = cpsw_ale_del_ucast(cpsw->ale, priv->mac_addr, + HOST_PORT_NUM, ALE_VLAN, vid); + + if (vid == cpsw_get_pvid(priv)) + cpsw_set_pvid(priv, 0, 0, 0); + + if (ret != 0) { + dev_dbg(priv->dev, "Failed to delete unicast entry\n"); + ret = 0; + } + + ret = cpsw_ale_del_mcast(cpsw->ale, priv->ndev->broadcast, + 0, ALE_VLAN, vid); + if (ret != 0) { + dev_dbg(priv->dev, "Failed to delete multicast entry\n"); + ret = 0; + } + + return ret; +} + +static int cpsw_port_vlans_add(struct cpsw_priv *priv, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans) +{ + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; + u16 vid; + + if (switchdev_trans_ph_prepare(trans)) + return 0; + + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { + int err; + + err = cpsw_port_vlan_add(priv, untagged, pvid, vid); + if (err) + return err; + } + + return 0; +} + +static int cpsw_port_vlans_del(struct cpsw_priv *priv, + const struct switchdev_obj_port_vlan *vlan) + +{ + u16 vid; + + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { + int err; + + err = cpsw_port_vlan_del(priv, vid); + if (err) + return err; + } + + return 0; +} + +static int cpsw_port_mdb_add(struct cpsw_priv *priv, + struct switchdev_obj_port_mdb *mdb, + struct switchdev_trans *trans) +{ + struct cpsw_common *cpsw = priv->cpsw; + int port_mask; + int err; + + if (switchdev_trans_ph_prepare(trans)) + return 0; + + port_mask = BIT(priv->emac_port); + err = cpsw_ale_mcast_add_modify(cpsw->ale, mdb->addr, port_mask, + ALE_VLAN, mdb->vid, 0); + + return err; +} + +static int cpsw_port_mdb_del(struct cpsw_priv *priv, + struct switchdev_obj_port_mdb *mdb) + +{ + struct cpsw_common *cpsw = priv->cpsw; + int del_mask; + int err; + + del_mask = BIT(priv->emac_port); + err = cpsw_ale_mcast_del_modify(cpsw->ale, mdb->addr, del_mask, + ALE_VLAN, mdb->vid); + + return err; +} + +static int cpsw_port_obj_add(struct net_device *ndev, + const struct switchdev_obj *obj, + struct switchdev_trans *trans) +{ + struct switchdev_obj_port_vlan *vlan = SWITCHDEV_OBJ_PORT_VLAN(obj); + struct switchdev_obj_port_mdb *mdb = SWITCHDEV_OBJ_PORT_MDB(obj); + struct cpsw_priv *priv = netdev_priv(ndev); + int err = 0; + + switch (obj->id) { + case SWITCHDEV_OBJ_ID_PORT_VLAN: + err = cpsw_port_vlans_add(priv, vlan, trans); + break; + case SWITCHDEV_OBJ_ID_PORT_MDB: + err = cpsw_port_mdb_add(priv, mdb, trans); + break; + default: + err = -EOPNOTSUPP; + break; + } + + return err; +} + +static int cpsw_port_obj_del(struct net_device *ndev, + const struct switchdev_obj *obj) +{ + struct switchdev_obj_port_vlan *vlan = SWITCHDEV_OBJ_PORT_VLAN(obj); + struct cpsw_priv *priv = netdev_priv(ndev); + int err = 0; + + switch (obj->id) { + case SWITCHDEV_OBJ_ID_PORT_VLAN: + err = cpsw_port_vlans_del(priv, vlan); + break; + case SWITCHDEV_OBJ_ID_PORT_MDB: + err = cpsw_port_mdb_del(priv, SWITCHDEV_OBJ_PORT_MDB(obj)); + break; + default: + err = -EOPNOTSUPP; + break; + } + + return err; +} + +static const struct switchdev_ops cpsw_port_switchdev_ops = { + .switchdev_port_attr_set = cpsw_port_attr_set, + .switchdev_port_attr_get = cpsw_port_attr_get, + .switchdev_port_obj_add = cpsw_port_obj_add, + .switchdev_port_obj_del = cpsw_port_obj_del, +}; + +void cpsw_port_switchdev_init(struct net_device *ndev) +{ + ndev->switchdev_ops = &cpsw_port_switchdev_ops; +} diff --git a/drivers/net/ethernet/ti/cpsw_switchdev.h b/drivers/net/ethernet/ti/cpsw_switchdev.h new file mode 100644 index 0000000..4940462 --- /dev/null +++ b/drivers/net/ethernet/ti/cpsw_switchdev.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include + +void cpsw_port_switchdev_init(struct net_device *ndev); From patchwork Thu May 24 06:56:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 136713 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp1823832lji; Wed, 23 May 2018 23:56:58 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqj7wO3he1zeuNeuXBNq3dg9AZUStlPwWFLLGBmNgataqHaqF5rTbHBj3qIJoitQ4kmR3I4 X-Received: by 2002:a17:902:205:: with SMTP id 5-v6mr5914937plc.301.1527145017936; Wed, 23 May 2018 23:56:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527145017; cv=none; d=google.com; s=arc-20160816; b=NWNKdxN5FqkEk8W9M/nuEN+Wm7ppOAkm8YhF+gvbus6UCTuMr/4bNubHBj5QEIsCzW wDLLl65JVLZShHWjMchQfVHNazk3gDH/KIXyHUS5wTrN8TpRkoIVMXX2i4eLc5UU2D8P hHR+fxB0aYJMaZBeWyXaCsAq4mHsy59xy7jTHugx/96k1AGs2+/I+etgEmGuRBOFLC8R wwvwlnjU8foi8fmNExJXSRU6Owump6e3m3RPnCe/k7TbcZvJVx82cafV5O7tBWxgM7+f l171X9J4TKoZOtEOtlmSN0idq0ty7bTnayyHbUiHvRhSLn5HpHEo4ijPRD049KDh4mSl bxqw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=8u/I+n89hCLNDXJEQR2aCNF+xwiQPZRq9MDBKkfkPnE=; b=O2npsJ225YJStuy7lB8KAIWJ1rZMAhAVw/fSx9r5gMJj7nQ5HrgN+1UJkanW765TuO zofPhH5baffeQqbIXzYXFS3iMxzod+Lei6YoHgpY9rFVKCV7889vhduakGZT7Um9wyPe 3BSGgFFqHr5jjna1sn+kHlRbGcFKW9Tj6KPMtxdNqKtRvL9kHGT6kXMS3uwz/6IcwXE0 w/3SV3pMtD5VqIoiuKroqX5ZLONNdXu3Yb0hAtlHwtIhYSiQcseRjB1XsVKXYeii2+WP 8fmeJxszHt93uAYTgSw2ukdPbvBIQcSjr6gXx8MJ2T9SNHTxaMM3JT6GXB5pkBWfj6Oj XeMw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=OjI7IdlP; spf=pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=netdev-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v2-v6si8349741plo.577.2018.05.23.23.56.57; Wed, 23 May 2018 23:56:57 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=OjI7IdlP; spf=pass (google.com: best guess record for domain of netdev-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=netdev-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964879AbeEXG4z (ORCPT + 9 others); Thu, 24 May 2018 02:56:55 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:38167 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935614AbeEXG4o (ORCPT ); Thu, 24 May 2018 02:56:44 -0400 Received: by mail-wm0-f66.google.com with SMTP id m129-v6so1993678wmb.3 for ; Wed, 23 May 2018 23:56:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8u/I+n89hCLNDXJEQR2aCNF+xwiQPZRq9MDBKkfkPnE=; b=OjI7IdlPh+uJjmBMA2co0yRWit3VVZys1ZTeVU3cwww8TbJXObwXwi+WVLQpifTl6B Xe5O020dc+thqPHc6w0Iprxe9+8RLni2fH+lMPYYm5xCIXBtyLKG6hm8K3YgJkK/5MF5 qBgVMd3xkNKd4PKUmLAi6XVtLjsGeZrCo8jRw= 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=8u/I+n89hCLNDXJEQR2aCNF+xwiQPZRq9MDBKkfkPnE=; b=K0ESFVoPrEb/n6DO+13jnnA+6us9QuYvS1pTyM0PKpr+LvdIeFMP23pwriBmpvvOxG oQmNRNF8ozAVUBxFhfyIJkNZ9vSH54UUjA61oxTnEhfmSncLzxAt5+VHde8McVFcSPoR OSnm8lpyZv61Nm14DSiAFkM2a6g2X2pF7r6f3cUT59jR/GZg+nyFgbRr9yEwETWkCTHo X9UymkbvHFVJmRxIdbCKeuQolwKv/VdAUUTQrKlW+0sT+RcbxM0nAQtpuJYprp/A0oxS x4DVKyBopiWeGJq7DUly3ybckClYRl/nPRqMqTo4CZtw9AoarS+lF5oKhjVyTJUQqLFQ /oeg== X-Gm-Message-State: ALKqPwd/b5EJGz8NLmOiCArmSgRjO1SNvi9DloQ9bbTPd2D+e1olaGU/ L+eMhgaJUktuAUbE3KqKPc0Gn9iLryA= X-Received: by 2002:a1c:2cc2:: with SMTP id s185-v6mr5725541wms.62.1527145002039; Wed, 23 May 2018 23:56:42 -0700 (PDT) Received: from localhost.localdomain ([2a02:587:460a:f200:b540:ba10:add4:9422]) by smtp.gmail.com with ESMTPSA id t198-v6sm4795257wmt.23.2018.05.23.23.56.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 23 May 2018 23:56:41 -0700 (PDT) From: Ilias Apalodimas To: netdev@vger.kernel.org, grygorii.strashko@ti.com, ivan.khoronzhuk@linaro.org, nsekhar@ti.com, jiri@resnulli.us, ivecera@redhat.com Cc: francois.ozog@linaro.org, yogeshs@ti.com, spatton@ti.com, Ilias Apalodimas Subject: [PATCH 4/4] cpsw: add switchdev support Date: Thu, 24 May 2018 09:56:24 +0300 Message-Id: <1527144984-31236-5-git-send-email-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1527144984-31236-1-git-send-email-ilias.apalodimas@linaro.org> References: <1527144984-31236-1-git-send-email-ilias.apalodimas@linaro.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Signed-off-by: Ilias Apalodimas --- drivers/net/ethernet/ti/cpsw.c | 503 +++++++++++++++++++++++++++++++----- drivers/net/ethernet/ti/cpsw_priv.h | 9 +- 2 files changed, 450 insertions(+), 62 deletions(-) -- 2.7.4 diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index b16e7cf..8f8ebd8 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -18,12 +18,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -42,6 +40,7 @@ #include "cpsw.h" #include "cpsw_ale.h" #include "cpsw_priv.h" +#include "cpsw_switchdev.h" #include "cpts.h" #include "davinci_cpdma.h" @@ -146,9 +145,6 @@ do { \ #define CPSW_CMINTMAX_INTVL (1000 / CPSW_CMINTMIN_CNT) #define CPSW_CMINTMIN_INTVL ((1000 / CPSW_CMINTMAX_CNT) + 1) -#define cpsw_slave_index(cpsw, priv) \ - ((cpsw->data.dual_emac) ? priv->emac_port : \ - cpsw->data.active_slave) #define IRQ_NUM 2 #define CPSW_MAX_QUEUES 8 #define CPSW_CPDMA_DESCS_POOL_SIZE_DEFAULT 256 @@ -360,6 +356,13 @@ struct cpsw_hw_stats { u32 rxdmaoverruns; }; +struct cpsw_switchdev_event_work { + struct work_struct work; + struct switchdev_notifier_fdb_info fdb_info; + struct cpsw_priv *priv; + unsigned long event; +}; + #define CPSW_STAT(m) CPSW_STATS, \ sizeof(((struct cpsw_hw_stats *)0)->m), \ offsetof(struct cpsw_hw_stats, m) @@ -433,18 +436,22 @@ static const struct cpsw_stats cpsw_gstrings_ch_stats[] = { struct cpsw_slave *slave; \ struct cpsw_common *cpsw = (priv)->cpsw; \ int n; \ - if (cpsw->data.dual_emac) \ - (func)((cpsw)->slaves + priv->emac_port, ##arg);\ - else \ + if (cpsw->data.switch_mode) { \ + if (priv->emac_port == HOST_PORT_NUM) \ + break; \ + (func)((cpsw)->slaves + (priv->emac_port - 1), \ + ##arg);\ + } else { \ for (n = cpsw->data.slaves, \ slave = cpsw->slaves; \ n; n--) \ (func)(slave++, ##arg); \ + } \ } while (0) #define cpsw_dual_emac_src_port_detect(cpsw, status, ndev, skb) \ do { \ - if (!cpsw->data.dual_emac) \ + if (!cpsw->data.switch_mode) \ break; \ if (CPDMA_RX_SOURCE_PORT(status) == 1) { \ ndev = cpsw->slaves[0].ndev; \ @@ -456,11 +463,13 @@ static const struct cpsw_stats cpsw_gstrings_ch_stats[] = { } while (0) #define cpsw_add_mcast(cpsw, priv, addr) \ do { \ - if (cpsw->data.dual_emac) { \ + if (cpsw->data.switch_mode) { \ struct cpsw_slave *slave = cpsw->slaves + \ - priv->emac_port; \ + (priv->emac_port - 1); \ int slave_port = cpsw_get_slave_port( \ slave->slave_num); \ + if (priv->emac_port == HOST_PORT_NUM) \ + break; \ cpsw_ale_add_mcast(cpsw->ale, addr, \ 1 << slave_port | ALE_PORT_HOST, \ ALE_VLAN, slave->port_vlan, 0); \ @@ -476,13 +485,41 @@ static inline int cpsw_get_slave_port(u32 slave_num) return slave_num + 1; } +static int cpsw_is_dual_mac(u8 switch_mode) +{ + return switch_mode == CPSW_DUAL_EMAC; +} + +static int cpsw_is_switchdev(u8 switch_mode) +{ + return switch_mode == CPSW_SWITCHDEV; +} + +static int cpsw_is_switch(u8 switch_mode) +{ + return switch_mode == CPSW_TI_SWITCH; +} + +static int cpsw_slave_index(struct cpsw_priv *priv) +{ + struct cpsw_common *cpsw = priv->cpsw; + +#if IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV) + if (priv->emac_port == HOST_PORT_NUM) + return -1; +#endif + + return cpsw->data.switch_mode ? priv->emac_port - 1 : + cpsw->data.active_slave; +} + static void cpsw_set_promiscious(struct net_device *ndev, bool enable) { struct cpsw_common *cpsw = ndev_to_cpsw(ndev); struct cpsw_ale *ale = cpsw->ale; int i; - if (cpsw->data.dual_emac) { + if (cpsw_is_dual_mac(cpsw->data.switch_mode)) { bool flag = false; /* Enabling promiscuous mode for one interface will be @@ -508,7 +545,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) cpsw_ale_control_set(ale, 0, ALE_BYPASS, 0); dev_dbg(&ndev->dev, "promiscuity disabled\n"); } - } else { + } else if (cpsw_is_switch(cpsw->data.switch_mode)) { if (enable) { unsigned long timeout = jiffies + HZ; @@ -548,6 +585,18 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) } dev_dbg(&ndev->dev, "promiscuity disabled\n"); } + } else if (cpsw_is_switchdev(cpsw->data.switch_mode)) { + /* When interfaces are placed into a bridge they'll switch to + * promiscuous mode. In switchdev case ALE_P0_UNI_FLOOD is + * changed whether the cpu port participates in the bridge + */ + struct cpsw_priv *priv = netdev_priv(ndev); + int slave_idx = cpsw_slave_index(priv); + int slave_num; + + slave_num = cpsw_get_slave_port(slave_idx); + cpsw_ale_control_set(ale, slave_num, ALE_PORT_NOLEARN, 0); + cpsw_ale_control_set(ale, slave_num, ALE_PORT_NO_SA_UPDATE, 0); } } @@ -555,10 +604,11 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev) { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; + int slave_no = cpsw_slave_index(priv); int vid; - if (cpsw->data.dual_emac) - vid = cpsw->slaves[priv->emac_port].port_vlan; + if (cpsw_is_dual_mac(cpsw->data.switch_mode)) + vid = cpsw->slaves[slave_no].port_vlan; else vid = cpsw->data.default_vlan; @@ -629,8 +679,9 @@ static void cpsw_tx_handler(void *token, int len, int status) static void cpsw_rx_vlan_encap(struct sk_buff *skb) { struct cpsw_priv *priv = netdev_priv(skb->dev); - struct cpsw_common *cpsw = priv->cpsw; u32 rx_vlan_encap_hdr = *((u32 *)skb->data); + struct cpsw_common *cpsw = priv->cpsw; + int slave_no = cpsw_slave_index(priv); u16 vtag, vid, prio, pkt_type; /* Remove VLAN header encapsulation word */ @@ -651,8 +702,8 @@ static void cpsw_rx_vlan_encap(struct sk_buff *skb) if (!vid) return; /* Ignore default vlans in dual mac mode */ - if (cpsw->data.dual_emac && - vid == cpsw->slaves[priv->emac_port].port_vlan) + if (cpsw_is_dual_mac(cpsw->data.switch_mode) && + vid == cpsw->slaves[slave_no].port_vlan) return; prio = (rx_vlan_encap_hdr >> @@ -681,9 +732,9 @@ static void cpsw_rx_handler(void *token, int len, int status) cpsw_dual_emac_src_port_detect(cpsw, status, ndev, skb); if (unlikely(status < 0) || unlikely(!netif_running(ndev))) { - /* In dual emac mode check for all interfaces */ - if (cpsw->data.dual_emac && cpsw->usage_count && - (status >= 0)) { + /* In any other that switch mode check for all interfaces */ + if (!cpsw_is_switch(cpsw->data.switch_mode) && + cpsw->usage_count && status >= 0) { /* The packet received is for the interface which * is already down and the other interface is up * and running, instead of freeing which results @@ -699,6 +750,11 @@ static void cpsw_rx_handler(void *token, int len, int status) return; } +#if IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV) + if (cpsw_is_switchdev(cpsw->data.switch_mode)) + skb->offload_fwd_mark = 1; +#endif + new_skb = netdev_alloc_skb_ip_align(ndev, cpsw->rx_packet_max); if (new_skb) { skb_copy_queue_mapping(new_skb, skb); @@ -1206,11 +1262,10 @@ static inline int cpsw_tx_packet_submit(struct cpsw_priv *priv, struct sk_buff *skb, struct cpdma_chan *txch) { - struct cpsw_common *cpsw = priv->cpsw; - skb_tx_timestamp(skb); + return cpdma_chan_submit(txch, skb, skb->data, skb->len, - priv->emac_port + cpsw->data.dual_emac); + priv->emac_port); } static inline void cpsw_add_dual_emac_def_ale_entries( @@ -1283,7 +1338,7 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) slave_port = cpsw_get_slave_port(slave->slave_num); - if (cpsw->data.dual_emac) + if (cpsw_is_dual_mac(cpsw->data.switch_mode)) cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port); else cpsw_ale_add_mcast(cpsw->ale, priv->ndev->broadcast, @@ -1362,8 +1417,8 @@ static void cpsw_init_host_port(struct cpsw_priv *priv) control_reg = readl(&cpsw->regs->control); control_reg |= CPSW_VLAN_AWARE | CPSW_RX_VLAN_ENCAP; writel(control_reg, &cpsw->regs->control); - fifo_mode = (cpsw->data.dual_emac) ? CPSW_FIFO_DUAL_MAC_MODE : - CPSW_FIFO_NORMAL_MODE; + fifo_mode = cpsw_is_dual_mac(cpsw->data.switch_mode) ? + CPSW_FIFO_DUAL_MAC_MODE : CPSW_FIFO_NORMAL_MODE; writel(fifo_mode, &cpsw->host_port_regs->tx_in_ctl); /* setup host port priority mapping */ @@ -1374,7 +1429,7 @@ static void cpsw_init_host_port(struct cpsw_priv *priv) cpsw_ale_control_set(cpsw->ale, HOST_PORT_NUM, ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); - if (!cpsw->data.dual_emac) { + if (!cpsw_is_dual_mac(cpsw->data.switch_mode)) { cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr, HOST_PORT_NUM, 0, 0); cpsw_ale_add_mcast(cpsw->ale, priv->ndev->broadcast, @@ -1474,14 +1529,19 @@ static int cpsw_ndo_open(struct net_device *ndev) /* Initialize host and slave ports */ if (!cpsw->usage_count) cpsw_init_host_port(priv); - for_each_slave(priv, cpsw_slave_open, priv); - /* Add default VLAN */ - if (!cpsw->data.dual_emac) - cpsw_add_default_vlan(priv); - else - cpsw_ale_add_vlan(cpsw->ale, cpsw->data.default_vlan, - ALE_ALL_PORTS, ALE_ALL_PORTS, 0, 0); + if (!IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV) || + (IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV) && + priv->emac_port != HOST_PORT_NUM)) { + for_each_slave(priv, cpsw_slave_open, priv); + + /* Add default VLAN */ + if (cpsw_is_dual_mac(cpsw->data.switch_mode)) + cpsw_ale_add_vlan(cpsw->ale, cpsw->data.default_vlan, + ALE_ALL_PORTS, ALE_ALL_PORTS, 0, 0); + else + cpsw_add_default_vlan(priv); + } /* initialize shared resources for every ndev */ if (!cpsw->usage_count) { @@ -1575,6 +1635,13 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb, struct cpdma_chan *txch; int ret, q_idx; +#if IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV) + if (priv->emac_port == HOST_PORT_NUM) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } +#endif + if (skb_padto(skb, CPSW_MIN_PACKET_SIZE)) { cpsw_err(priv, tx_err, "packet pad failed\n"); ndev->stats.tx_dropped++; @@ -1655,8 +1722,12 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv) struct cpsw_slave *slave; struct cpsw_common *cpsw = priv->cpsw; u32 ctrl, mtype; + int slave_no = cpsw_slave_index(priv); + + if (slave_no < 0) + return; - slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; + slave = &cpsw->slaves[slave_no]; ctrl = slave_read(slave, CPSW2_CONTROL); switch (cpsw->version) { @@ -1791,11 +1862,14 @@ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { struct cpsw_priv *priv = netdev_priv(dev); struct cpsw_common *cpsw = priv->cpsw; - int slave_no = cpsw_slave_index(cpsw, priv); + int slave_no = cpsw_slave_index(priv); if (!netif_running(dev)) return -EINVAL; + if (slave_no < 0) + return -EOPNOTSUPP; + switch (cmd) { case SIOCSHWTSTAMP: return cpsw_hwtstamp_set(dev, req); @@ -1832,6 +1906,7 @@ static int cpsw_ndo_set_mac_address(struct net_device *ndev, void *p) struct cpsw_priv *priv = netdev_priv(ndev); struct sockaddr *addr = (struct sockaddr *)p; struct cpsw_common *cpsw = priv->cpsw; + int slave_no = cpsw_slave_index(priv); int flags = 0; u16 vid = 0; int ret; @@ -1845,8 +1920,8 @@ static int cpsw_ndo_set_mac_address(struct net_device *ndev, void *p) return ret; } - if (cpsw->data.dual_emac) { - vid = cpsw->slaves[priv->emac_port].port_vlan; + if (cpsw_is_dual_mac(cpsw->data.switch_mode)) { + vid = cpsw->slaves[slave_no].port_vlan; flags = ALE_VLAN; } @@ -1884,8 +1959,11 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv, u32 port_mask; struct cpsw_common *cpsw = priv->cpsw; - if (cpsw->data.dual_emac) { - port_mask = (1 << (priv->emac_port + 1)) | ALE_PORT_HOST; + if (cpsw_is_switchdev(cpsw->data.switch_mode)) + return -EOPNOTSUPP; + + if (cpsw_is_dual_mac(cpsw->data.switch_mode)) { + port_mask = (1 << priv->emac_port) | ALE_PORT_HOST; if (priv->ndev->flags & IFF_ALLMULTI) unreg_mcast_mask = port_mask; @@ -1929,6 +2007,9 @@ static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev, struct cpsw_common *cpsw = priv->cpsw; int ret; + if (cpsw_is_switchdev(cpsw->data.switch_mode)) + return 0; + if (vid == cpsw->data.default_vlan) return 0; @@ -1938,7 +2019,7 @@ static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev, return ret; } - if (cpsw->data.dual_emac) { + if (cpsw_is_dual_mac(cpsw->data.switch_mode)) { /* In dual EMAC, reserved VLAN id should not be used for * creating VLAN interfaces as this can break the dual * EMAC port separation @@ -1965,6 +2046,9 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, struct cpsw_common *cpsw = priv->cpsw; int ret; + if (cpsw_is_switchdev(cpsw->data.switch_mode)) + return 0; + if (vid == cpsw->data.default_vlan) return 0; @@ -1974,7 +2058,7 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, return ret; } - if (cpsw->data.dual_emac) { + if (cpsw_is_dual_mac(cpsw->data.switch_mode)) { int i; for (i = 0; i < cpsw->data.slaves; i++) { @@ -1999,6 +2083,24 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, return ret; } +static int cpsw_ndo_get_phys_port_name(struct net_device *ndev, char *name, + size_t len) +{ + struct cpsw_priv *priv = netdev_priv(ndev); + struct cpsw_common *cpsw = priv->cpsw; + int err; + + if (!cpsw_is_switchdev(cpsw->data.switch_mode)) + return -EOPNOTSUPP; + + err = snprintf(name, len, "p%d", priv->emac_port); + + if (err >= len) + return -EINVAL; + + return 0; +} + static int cpsw_ndo_set_tx_maxrate(struct net_device *ndev, int queue, u32 rate) { struct cpsw_priv *priv = netdev_priv(ndev); @@ -2065,6 +2167,7 @@ static const struct net_device_ops cpsw_netdev_ops = { #endif .ndo_vlan_rx_add_vid = cpsw_ndo_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid, + .ndo_get_phys_port_name = cpsw_ndo_get_phys_port_name, }; static int cpsw_get_regs_len(struct net_device *ndev) @@ -2152,7 +2255,10 @@ static int cpsw_get_link_ksettings(struct net_device *ndev, { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; - int slave_no = cpsw_slave_index(cpsw, priv); + int slave_no = cpsw_slave_index(priv); + + if (slave_no < 0) + return -EOPNOTSUPP; if (!cpsw->slaves[slave_no].phy) return -EOPNOTSUPP; @@ -2166,7 +2272,10 @@ static int cpsw_set_link_ksettings(struct net_device *ndev, { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; - int slave_no = cpsw_slave_index(cpsw, priv); + int slave_no = cpsw_slave_index(priv); + + if (slave_no < 0) + return -EOPNOTSUPP; if (cpsw->slaves[slave_no].phy) return phy_ethtool_ksettings_set(cpsw->slaves[slave_no].phy, @@ -2179,7 +2288,10 @@ static void cpsw_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; - int slave_no = cpsw_slave_index(cpsw, priv); + int slave_no = cpsw_slave_index(priv); + + if (slave_no < 0) + return; wol->supported = 0; wol->wolopts = 0; @@ -2192,7 +2304,10 @@ static int cpsw_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; - int slave_no = cpsw_slave_index(cpsw, priv); + int slave_no = cpsw_slave_index(priv); + + if (slave_no < 0) + return -EOPNOTSUPP; if (cpsw->slaves[slave_no].phy) return phy_ethtool_set_wol(cpsw->slaves[slave_no].phy, wol); @@ -2451,7 +2566,10 @@ static int cpsw_get_eee(struct net_device *ndev, struct ethtool_eee *edata) { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; - int slave_no = cpsw_slave_index(cpsw, priv); + int slave_no = cpsw_slave_index(priv); + + if (slave_no < 0) + return -EOPNOTSUPP; if (cpsw->slaves[slave_no].phy) return phy_ethtool_get_eee(cpsw->slaves[slave_no].phy, edata); @@ -2463,7 +2581,10 @@ static int cpsw_set_eee(struct net_device *ndev, struct ethtool_eee *edata) { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; - int slave_no = cpsw_slave_index(cpsw, priv); + int slave_no = cpsw_slave_index(priv); + + if (slave_no < 0) + return -EOPNOTSUPP; if (cpsw->slaves[slave_no].phy) return phy_ethtool_set_eee(cpsw->slaves[slave_no].phy, edata); @@ -2475,7 +2596,10 @@ static int cpsw_nway_reset(struct net_device *ndev) { struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_common *cpsw = priv->cpsw; - int slave_no = cpsw_slave_index(cpsw, priv); + int slave_no = cpsw_slave_index(priv); + + if (slave_no < 0) + return -EOPNOTSUPP; if (cpsw->slaves[slave_no].phy) return genphy_restart_aneg(cpsw->slaves[slave_no].phy); @@ -2626,7 +2750,11 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, data->mac_control = prop; if (of_property_read_bool(node, "dual_emac")) - data->dual_emac = 1; + data->switch_mode = CPSW_DUAL_EMAC; + + /* switchdev overrides DTS */ + if (IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV)) + data->switch_mode = CPSW_SWITCHDEV; /* * Populate all the child nodes here... @@ -2707,7 +2835,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, if (ret) return ret; } - if (data->dual_emac) { + if (cpsw_is_dual_mac(data->switch_mode)) { if (of_property_read_u32(slave_node, "dual_emac_res_vlan", &prop)) { dev_err(&pdev->dev, "Missing dual_emac_res_vlan in DT.\n"); @@ -2787,9 +2915,13 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv) } memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN); - priv_sl2->emac_port = 1; + priv_sl2->emac_port = 2; cpsw->slaves[1].ndev = ndev; ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + if (cpsw_is_switchdev(cpsw->data.switch_mode)) { + ndev->features |= NETIF_F_NETNS_LOCAL; + cpsw_port_switchdev_init(ndev); + } ndev->netdev_ops = &cpsw_netdev_ops; ndev->ethtool_ops = &cpsw_ethtool_ops; @@ -2806,6 +2938,49 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv) return ret; } +static int cpsw_probe_cpu_port(struct cpsw_common *cpsw) +{ + struct cpsw_priv *priv_sl2; + struct net_device *ndev; + int ret = 0; + + ndev = alloc_etherdev_mq(sizeof(struct cpsw_priv), CPSW_MAX_QUEUES); + if (!ndev) { + dev_err(cpsw->dev, "cpsw: error allocating net_device\n"); + return -ENOMEM; + } + + priv_sl2 = netdev_priv(ndev); + priv_sl2->cpsw = cpsw; + priv_sl2->ndev = ndev; + priv_sl2->dev = &ndev->dev; + priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG); + + random_ether_addr(priv_sl2->mac_addr); + dev_info(cpsw->dev, "cpu port: Random MACID = %pM\n", + priv_sl2->mac_addr); + + memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN); + + priv_sl2->emac_port = HOST_PORT_NUM; + ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_NETNS_LOCAL; + + ndev->netdev_ops = &cpsw_netdev_ops; + + /* register the network device */ + SET_NETDEV_DEV(ndev, cpsw->dev); + cpsw_port_switchdev_init(ndev); + ret = register_netdev(ndev); + if (ret) { + dev_err(cpsw->dev, "cpsw: error registering net device\n"); + free_netdev(ndev); + ret = -ENODEV; + } + cpsw->master = ndev; + + return ret; +} + #define CPSW_QUIRK_IRQ BIT(0) static const struct platform_device_id cpsw_devtype[] = { @@ -2844,6 +3019,187 @@ static const struct of_device_id cpsw_of_mtable[] = { }; MODULE_DEVICE_TABLE(of, cpsw_of_mtable); +static bool cpsw_port_dev_check(const struct net_device *dev) +{ + return dev->netdev_ops == &cpsw_netdev_ops; +} + +static void cpsw_fdb_offload_notify(struct net_device *ndev, + struct switchdev_notifier_fdb_info *rcv) +{ + struct switchdev_notifier_fdb_info info; + + info.addr = rcv->addr; + info.vid = rcv->vid; + call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, + ndev, &info.info); +} + +static void cpsw_switchdev_event_work(struct work_struct *work) +{ + struct cpsw_switchdev_event_work *switchdev_work = + container_of(work, struct cpsw_switchdev_event_work, work); + struct cpsw_priv *priv = switchdev_work->priv; + struct switchdev_notifier_fdb_info *fdb; + struct cpsw_common *cpsw = priv->cpsw; + + rtnl_lock(); + switch (switchdev_work->event) { + case SWITCHDEV_FDB_ADD_TO_DEVICE: + fdb = &switchdev_work->fdb_info; + cpsw_ale_add_ucast(cpsw->ale, (u8 *)fdb->addr, priv->emac_port, + ALE_VLAN | ALE_SECURE, fdb->vid); + cpsw_fdb_offload_notify(priv->ndev, fdb); + break; + case SWITCHDEV_FDB_DEL_TO_DEVICE: + fdb = &switchdev_work->fdb_info; + cpsw_ale_del_ucast(cpsw->ale, (u8 *)fdb->addr, priv->emac_port, + ALE_VLAN | ALE_SECURE, fdb->vid); + break; + default: + break; + } + rtnl_unlock(); + + kfree(switchdev_work->fdb_info.addr); + kfree(switchdev_work); + dev_put(priv->ndev); +} + +/* called under rcu_read_lock() */ +static int cpsw_switchdev_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *ndev = switchdev_notifier_info_to_dev(ptr); + struct switchdev_notifier_fdb_info *fdb_info = ptr; + struct cpsw_switchdev_event_work *switchdev_work; + struct cpsw_priv *priv = netdev_priv(ndev); + + if (!cpsw_port_dev_check(ndev)) + return NOTIFY_DONE; + + switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); + if (WARN_ON(!switchdev_work)) + return NOTIFY_BAD; + + INIT_WORK(&switchdev_work->work, cpsw_switchdev_event_work); + switchdev_work->priv = priv; + switchdev_work->event = event; + + switch (event) { + case SWITCHDEV_FDB_ADD_TO_DEVICE: + case SWITCHDEV_FDB_DEL_TO_DEVICE: + memcpy(&switchdev_work->fdb_info, ptr, + sizeof(switchdev_work->fdb_info)); + switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC); + ether_addr_copy((u8 *)switchdev_work->fdb_info.addr, + fdb_info->addr); + dev_hold(ndev); + break; + default: + kfree(switchdev_work); + return NOTIFY_DONE; + } + + queue_work(system_long_wq, &switchdev_work->work); + + return NOTIFY_DONE; +} + +static struct notifier_block cpsw_switchdev_notifier = { + .notifier_call = cpsw_switchdev_event, +}; + +static void cpsw_netdevice_port_link(struct net_device *ndev) +{ + struct cpsw_priv *priv = netdev_priv(ndev); + struct cpsw_common *cpsw = priv->cpsw; + + if (priv->emac_port != HOST_PORT_NUM) + return; + + cpsw_ale_control_set(cpsw->ale, HOST_PORT_NUM, ALE_P0_UNI_FLOOD, 1); +} + +static void cpsw_netdevice_port_unlink(struct net_device *ndev) +{ + struct cpsw_priv *priv = netdev_priv(ndev); + struct cpsw_common *cpsw = priv->cpsw; + + if (priv->emac_port != HOST_PORT_NUM) + return; + + cpsw_ale_control_set(cpsw->ale, HOST_PORT_NUM, ALE_P0_UNI_FLOOD, 0); +} + +/* netdev notifier */ +static int cpsw_netdevice_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *ndev = netdev_notifier_info_to_dev(ptr); + struct netdev_notifier_changeupper_info *info; + + switch (event) { + case NETDEV_CHANGEUPPER: + info = ptr; + if (!info->master) + goto out; + if (info->linking) + cpsw_netdevice_port_link(ndev); + else + cpsw_netdevice_port_unlink(ndev); + break; + default: + return NOTIFY_DONE; + } + +out: + return NOTIFY_DONE; +} + +static struct notifier_block cpsw_netdevice_nb __read_mostly = { + .notifier_call = cpsw_netdevice_event, +}; + +static int cpsw_register_notifiers(struct cpsw_priv *priv) +{ + int ret; + + ret = register_netdevice_notifier(&cpsw_netdevice_nb); + if (ret) { + cpsw_err(priv, probe, "can't register netdevice notifier\n"); + return ret; + } + + ret = register_switchdev_notifier(&cpsw_switchdev_notifier); + if (ret) { + cpsw_err(priv, probe, "can't register switchdev notifier\n"); + goto unreg_netdevice; + } + + return ret; + +unreg_netdevice: + ret = unregister_netdevice_notifier(&cpsw_netdevice_nb); + + return ret; +} + +static int cpsw_unregister_notifiers(struct cpsw_priv *priv) +{ + int ret; + + ret = unregister_switchdev_notifier(&cpsw_switchdev_notifier); + if (ret) + dev_err(priv->dev, "can't unregister switchdev notifier\n"); + + ret += unregister_netdevice_notifier(&cpsw_netdevice_nb); + if (ret) + dev_err(priv->dev, "can't unregister netdevice notifier\n"); + + return ret; +} + static int cpsw_probe(struct platform_device *pdev) { struct clk *clk; @@ -2935,7 +3291,11 @@ static int cpsw_probe(struct platform_device *pdev) cpsw->slaves[i].slave_num = i; cpsw->slaves[0].ndev = ndev; - priv->emac_port = 0; + + if (cpsw_is_switch(cpsw->data.switch_mode)) + priv->emac_port = HOST_PORT_NUM; + else + priv->emac_port = 1; clk = devm_clk_get(&pdev->dev, "fck"); if (IS_ERR(clk)) { @@ -3076,8 +3436,17 @@ static int cpsw_probe(struct platform_device *pdev) cpsw->quirk_irq = true; } - ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX; + if (cpsw_is_switchdev(cpsw->data.switch_mode)) { + ret = cpsw_probe_cpu_port(cpsw); + if (ret) { + cpsw_err(priv, probe, "error probe cpu interface\n"); + goto clean_dma_ret; + } + cpsw_port_switchdev_init(ndev); + ndev->features |= NETIF_F_NETNS_LOCAL; + } + ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX; ndev->netdev_ops = &cpsw_netdev_ops; ndev->ethtool_ops = &cpsw_ethtool_ops; netif_napi_add(ndev, &cpsw->napi_rx, cpsw_rx_poll, CPSW_POLL_WEIGHT); @@ -3093,7 +3462,7 @@ static int cpsw_probe(struct platform_device *pdev) goto clean_dma_ret; } - if (cpsw->data.dual_emac) { + if (!cpsw_is_switch(cpsw->data.switch_mode)) { ret = cpsw_probe_dual_emac(priv); if (ret) { cpsw_err(priv, probe, "error probe slave 2 emac interface\n"); @@ -3139,6 +3508,12 @@ static int cpsw_probe(struct platform_device *pdev) goto clean_dma_ret; } + if (cpsw_is_switchdev(cpsw->data.switch_mode)) { + ret = cpsw_register_notifiers(priv); + if (ret) + goto clean_dma_ret; + } + cpsw_notice(priv, probe, "initialized device (regs %pa, irq %d, pool size %d)\n", &ss_res->start, ndev->irq, dma_params.descs_pool_size); @@ -3164,7 +3539,8 @@ static int cpsw_probe(struct platform_device *pdev) static int cpsw_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); - struct cpsw_common *cpsw = ndev_to_cpsw(ndev); + struct cpsw_priv *priv = netdev_priv(ndev); + struct cpsw_common *cpsw = priv->cpsw; int ret; ret = pm_runtime_get_sync(&pdev->dev); @@ -3173,7 +3549,10 @@ static int cpsw_remove(struct platform_device *pdev) return ret; } - if (cpsw->data.dual_emac) + if (cpsw_is_switchdev(cpsw->data.switch_mode)) + ret = cpsw_unregister_notifiers(priv); + + if (cpsw->data.switch_mode) unregister_netdev(cpsw->slaves[1].ndev); unregister_netdev(ndev); @@ -3182,8 +3561,10 @@ static int cpsw_remove(struct platform_device *pdev) cpsw_remove_dt(pdev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - if (cpsw->data.dual_emac) + if (cpsw->data.switch_mode) free_netdev(cpsw->slaves[1].ndev); + if (cpsw->master) + free_netdev(cpsw->master); free_netdev(ndev); return 0; } @@ -3195,7 +3576,7 @@ static int cpsw_suspend(struct device *dev) struct net_device *ndev = platform_get_drvdata(pdev); struct cpsw_common *cpsw = ndev_to_cpsw(ndev); - if (cpsw->data.dual_emac) { + if (cpsw->data.switch_mode) { int i; for (i = 0; i < cpsw->data.slaves; i++) { @@ -3224,7 +3605,7 @@ static int cpsw_resume(struct device *dev) /* shut up ASSERT_RTNL() warning in netif_set_real_num_tx/rx_queues */ rtnl_lock(); - if (cpsw->data.dual_emac) { + if (cpsw->data.switch_mode) { int i; for (i = 0; i < cpsw->data.slaves; i++) { diff --git a/drivers/net/ethernet/ti/cpsw_priv.h b/drivers/net/ethernet/ti/cpsw_priv.h index 3b02a83..4be5ffc 100644 --- a/drivers/net/ethernet/ti/cpsw_priv.h +++ b/drivers/net/ethernet/ti/cpsw_priv.h @@ -30,6 +30,12 @@ #define CPSW2_TX_PRI_MAP 0x18 /* Tx Header Priority to Switch Pri Mapping */ #define CPSW2_TS_SEQ_MTYPE 0x1c /* Time Sync Sequence ID Offset and Msg Type */ +enum { + CPSW_TI_SWITCH, + CPSW_DUAL_EMAC, + CPSW_SWITCHDEV, +}; + struct cpsw_slave_data { struct device_node *phy_node; char phy_id[MII_BUS_ID_SIZE]; @@ -48,7 +54,7 @@ struct cpsw_platform_data { u32 bd_ram_size; /*buffer descriptor ram size */ u32 mac_control; /* Mac control register */ u16 default_vlan; /* Def VLAN for ALE lookup in VLAN aware mode*/ - bool dual_emac; /* Enable Dual EMAC mode */ + u8 switch_mode; /* Enable Dual EMAC/switchdev mode */ }; struct cpsw_slave { @@ -80,6 +86,7 @@ struct cpsw_common { u32 coal_intvl; u32 bus_freq_mhz; int rx_packet_max; + struct net_device *master; /* used for switchdev */ struct cpsw_slave *slaves; struct cpdma_ctlr *dma; struct cpsw_vector txv[CPSW_MAX_QUEUES];