From patchwork Wed Nov 4 16:57:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ioana Ciornei X-Patchwork-Id: 318449 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=-12.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HK_RANDOM_FROM,INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable 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 3B082C2D0A3 for ; Wed, 4 Nov 2020 16:58:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D468920709 for ; Wed, 4 Nov 2020 16:58:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hWjW+68U" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731437AbgKDQ5c (ORCPT ); Wed, 4 Nov 2020 11:57:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731341AbgKDQ5b (ORCPT ); Wed, 4 Nov 2020 11:57:31 -0500 Received: from mail-ed1-x533.google.com (mail-ed1-x533.google.com [IPv6:2a00:1450:4864:20::533]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 265BFC0613D4; Wed, 4 Nov 2020 08:57:31 -0800 (PST) Received: by mail-ed1-x533.google.com with SMTP id k9so23188785edo.5; Wed, 04 Nov 2020 08:57:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+Wl8VQ83sJ0McXNO1lN782gGN4ABhecaZy/JTrLJ6Zw=; b=hWjW+68UB57IORwvWiTy0JQFHigoafHVyV6oAweE67n8AR8Tx6WqdD8ZxYClssmERG IbiIhb1gXk4K7+aMXtCSCO46/X/NWByPyU1pZqti9mCT06CnFjf5bqEZfnIOzL8MCaKo A4BaHX/8YN2MdD5dImYl7H3oOIpIzT/PjyfmrwiiJbrTp03/F87oFomOnrJwuVsrtQOl hMeUjMkYZcWrvjQKb07zXgCHy4K3f5zSICC2iZb4tdQ49OKYp2eR16bT1awYK6MpelmC /NvT0BX26ARZm4KJqwYqsm+fEFxZGvhG9c6JYiA7CjJTEsOi+/Gjl2Oncmy27lEO6cZq fgBA== 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:mime-version:content-transfer-encoding; bh=+Wl8VQ83sJ0McXNO1lN782gGN4ABhecaZy/JTrLJ6Zw=; b=pCEclfK6FCdfEuYRmxvxgC7OS++EiPDUbRyfxBtG/Tvmu4Cm/XPBCYxePcROmdUlKe zVQ8EbWCoRRm0FZYY1stykDWZnWy6gQDu2i12a85H8AQS0hxrQIPAcbRIMqAN3QvjkSQ 5LtiTYl2jq72i7kdSrJg08pXuGgLJVC827nSBSiwi8iVBnZDdjggjVMFBgaewVfP8pYz IN1J7D7PvguOA8SIjzs6t2NNN0Zrz42MECMX3O+x5Lf3VHlvAjdAAHorH2Tlz/Z2BjrW AOhXYsCkfdfC3lrSASiAkwlGM77Rf/sN66YRAbBchGxYvnt8OlpvwGe58xKXG9zQBVt3 d43Q== X-Gm-Message-State: AOAM530hJpoFTxyLiyGUfDdAinnGdm/TzzDtlTtkXPZBAD3ZgSu3W8Pk WSRtuj65wH1t/5FJvC2RRFI= X-Google-Smtp-Source: ABdhPJyCzO5WR//qs3JScPUHjiBMjmy1AV90OfWcdBoEG7YQK9Y3haKEh5mOh3E5dYjlQEA9gJ4ctQ== X-Received: by 2002:a05:6402:1d82:: with SMTP id dk2mr27218475edb.299.1604509049745; Wed, 04 Nov 2020 08:57:29 -0800 (PST) Received: from yoga-910.localhost ([188.25.2.177]) by smtp.gmail.com with ESMTPSA id l12sm1354748edt.46.2020.11.04.08.57.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Nov 2020 08:57:29 -0800 (PST) From: Ioana Ciornei To: Greg Kroah-Hartman , Andrew Lunn Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Ioana Ciornei Subject: [RFC 1/9] staging: dpaa2-switch: get control interface attributes Date: Wed, 4 Nov 2020 18:57:12 +0200 Message-Id: <20201104165720.2566399-2-ciorneiioana@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201104165720.2566399-1-ciorneiioana@gmail.com> References: <20201104165720.2566399-1-ciorneiioana@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ioana Ciornei Introduce a new structure to hold all necessary info related to an RX queue for the control interface and populate the FQ IDs. We only have one Rx queue and one Tx confirmation queue on the control interface, both shared by all the switch ports. Signed-off-by: Ioana Ciornei --- drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 9 +++++ drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 31 ++++++++++++++++ drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 21 +++++++++++ drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 43 ++++++++++++++++++++++ drivers/staging/fsl-dpaa2/ethsw/ethsw.h | 15 ++++++++ 5 files changed, 119 insertions(+) diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h index f100d503bd17..24c902eb63e3 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h @@ -73,6 +73,8 @@ #define DPSW_CMDID_IF_GET_PRIMARY_MAC_ADDR DPSW_CMD_ID(0x0A8) #define DPSW_CMDID_IF_SET_PRIMARY_MAC_ADDR DPSW_CMD_ID(0x0A9) +#define DPSW_CMDID_CTRL_IF_GET_ATTR DPSW_CMD_ID(0x0A0) + /* Macros for accessing command fields smaller than 1byte */ #define DPSW_MASK(field) \ GENMASK(DPSW_##field##_SHIFT + DPSW_##field##_SIZE - 1, \ @@ -368,6 +370,13 @@ struct dpsw_rsp_fdb_dump { __le16 num_entries; }; +struct dpsw_rsp_ctrl_if_get_attr { + __le64 pad; + __le32 rx_fqid; + __le32 rx_err_fqid; + __le32 tx_err_conf_fqid; +}; + struct dpsw_rsp_get_api_version { __le16 version_major; __le16 version_minor; diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c index f8bfe779bd30..996f13abfb1b 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c @@ -1182,6 +1182,37 @@ int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpsw_ctrl_if_get_attributes() - Obtain control interface attributes + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @attr: Returned control interface attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, + u16 token, struct dpsw_ctrl_if_attr *attr) +{ + struct dpsw_rsp_ctrl_if_get_attr *rsp_params; + struct fsl_mc_command cmd = { 0 }; + int err; + + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_GET_ATTR, + cmd_flags, token); + + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + rsp_params = (struct dpsw_rsp_ctrl_if_get_attr *)cmd.params; + attr->rx_fqid = le32_to_cpu(rsp_params->rx_fqid); + attr->rx_err_fqid = le32_to_cpu(rsp_params->rx_err_fqid); + attr->tx_err_conf_fqid = le32_to_cpu(rsp_params->tx_err_conf_fqid); + + return 0; +} + /** * dpsw_get_api_version() - Get Data Path Switch API version * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index ab63ee4f5cb7..fcc07991119d 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -175,6 +175,27 @@ int dpsw_get_attributes(struct fsl_mc_io *mc_io, u16 token, struct dpsw_attr *attr); +/** + * struct dpsw_ctrl_if_attr - Control interface attributes + * @rx_fqid: Receive FQID + * @rx_err_fqid: Receive error FQID + * @tx_err_conf_fqid: Transmit error and confirmation FQID + */ +struct dpsw_ctrl_if_attr { + u32 rx_fqid; + u32 rx_err_fqid; + u32 tx_err_conf_fqid; +}; + +int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, + u16 token, struct dpsw_ctrl_if_attr *attr); + +enum dpsw_queue_type { + DPSW_QUEUE_RX, + DPSW_QUEUE_TX_ERR_CONF, + DPSW_QUEUE_RX_ERR, +}; + /** * enum dpsw_action - Action selection for special/control frames * @DPSW_ACTION_DROP: Drop frame diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 20c6326e5dee..c22b9ad558c8 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1478,6 +1478,43 @@ static void dpaa2_switch_detect_features(struct ethsw_core *ethsw) ethsw->features |= ETHSW_FEATURE_MAC_ADDR; } +static int dpaa2_switch_setup_fqs(struct ethsw_core *ethsw) +{ + struct dpsw_ctrl_if_attr ctrl_if_attr; + struct device *dev = ethsw->dev; + int i = 0; + int err; + + err = dpsw_ctrl_if_get_attributes(ethsw->mc_io, 0, ethsw->dpsw_handle, + &ctrl_if_attr); + if (err) { + dev_err(dev, "dpsw_ctrl_if_get_attributes() = %d\n", err); + return err; + } + + ethsw->fq[i].fqid = ctrl_if_attr.rx_fqid; + ethsw->fq[i].ethsw = ethsw; + ethsw->fq[i++].type = DPSW_QUEUE_RX; + + ethsw->fq[i].fqid = ctrl_if_attr.tx_err_conf_fqid; + ethsw->fq[i].ethsw = ethsw; + ethsw->fq[i++].type = DPSW_QUEUE_TX_ERR_CONF; + + return 0; +} + +static int dpaa2_switch_ctrl_if_setup(struct ethsw_core *ethsw) +{ + int err; + + /* setup FQs for Rx and Tx Conf */ + err = dpaa2_switch_setup_fqs(ethsw); + if (err) + return err; + + return 0; +} + static int dpaa2_switch_init(struct fsl_mc_device *sw_dev) { struct device *dev = &sw_dev->dev; @@ -1566,6 +1603,12 @@ static int dpaa2_switch_init(struct fsl_mc_device *sw_dev) goto err_close; } + if (dpaa2_switch_has_ctrl_if(ethsw)) { + err = dpaa2_switch_ctrl_if_setup(ethsw); + if (err) + goto err_destroy_ordered_workqueue; + } + err = dpaa2_switch_register_notifier(dev); if (err) goto err_destroy_ordered_workqueue; diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h index 5f9211ccb1ef..3189dd72a51b 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h @@ -39,10 +39,19 @@ #define ETHSW_FEATURE_MAC_ADDR BIT(0) +/* Number of receive queues (one RX and one TX_CONF) */ +#define DPAA2_SWITCH_RX_NUM_FQS 2 + extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops; struct ethsw_core; +struct dpaa2_switch_fq { + struct ethsw_core *ethsw; + enum dpsw_queue_type type; + u32 fqid; +}; + /* Per port private data */ struct ethsw_port_priv { struct net_device *netdev; @@ -75,6 +84,12 @@ struct ethsw_core { struct notifier_block port_switchdev_nb; struct notifier_block port_switchdevb_nb; struct workqueue_struct *workqueue; + + struct dpaa2_switch_fq fq[DPAA2_SWITCH_RX_NUM_FQS]; }; +static inline bool dpaa2_switch_has_ctrl_if(struct ethsw_core *ethsw) +{ + return !(ethsw->sw_attr.options & DPSW_OPT_CTRL_IF_DIS); +} #endif /* __ETHSW_H */ From patchwork Wed Nov 4 16:57:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ioana Ciornei X-Patchwork-Id: 318453 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=-12.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HK_RANDOM_FROM,INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, 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 9ABEFC4741F for ; Wed, 4 Nov 2020 16:57:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2D7952071A for ; Wed, 4 Nov 2020 16:57:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="rjha0/KY" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731553AbgKDQ5e (ORCPT ); Wed, 4 Nov 2020 11:57:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41012 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731341AbgKDQ5c (ORCPT ); Wed, 4 Nov 2020 11:57:32 -0500 Received: from mail-ed1-x52c.google.com (mail-ed1-x52c.google.com [IPv6:2a00:1450:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4113CC0613D3; Wed, 4 Nov 2020 08:57:32 -0800 (PST) Received: by mail-ed1-x52c.google.com with SMTP id o18so23222678edq.4; Wed, 04 Nov 2020 08:57:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1nNBwUfUFAQ1bIBA8E/6Tf1c9Py6NpoAMvknpGcmmcQ=; b=rjha0/KYKXjUqCiWK2s85jRvS2jETsjsMCh18WdNx8MG1QTcg3s1uck2DSuRGEM/fa xc14x4HC0KjUZTPu/RLNnCuuw4B0QMuRCMC3rH7qCmY8s+palhkMLyOHUNEcgMRAPQFg 3S6SlwGIqIE5tBuBOvvpUzz5nTd6Z5Ajo4uxQ8IoM3XPd0BFG4gXD36kcG6vQWY2C/2v cSQaxbQbUAf+K8P2BsBiubIIfsXJiSGmP9sJoUIONUfmunx2w1uVeWm6xq+n6W6ugkLg LlRxkj2zGeqKt7ZGa+XaGW19fgnmC+9ZZ7UUfvmxelI6DjF8KjtgK4SvN2CcJx/6InPk BNJA== 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:mime-version:content-transfer-encoding; bh=1nNBwUfUFAQ1bIBA8E/6Tf1c9Py6NpoAMvknpGcmmcQ=; b=PF3xNtWaxMOX0dZFnr2mZc5EPNut5zQ0cowQkuZQ7Lym6QDf27tM2QSvuYjy0C/4tX gsbsSU2DwzDPuzCchD5QW2p9Jv9DL4V2DLwoGYiwTBbqa3P2S/DBqbEVzcIJt7dWYU3c TXf2Hsdstazx6RNy2A9ldcd01DhCZd0NqaFyEh6oyG6cCgPbfrGhLlLa/LNZGRpd7tcV ejZixodlZ3KZcvwn7/k4Z8fa0aOsCbIJWgUVK3L3d8waNktYvjodlEkOtj879rN1Tgga +06uu7quMzrldRrc9Cg32okan+1qsA1M4GvRjsoHa5k5Ipl1gXU4/JBynVXjBzh/R8UJ awDA== X-Gm-Message-State: AOAM5306qydthICUIyQnRusiHVqXrj+UgEMVG87D3nlpTBbgXo1rJLR9 KV5Z5xFFLZviXc5aYk86Y84= X-Google-Smtp-Source: ABdhPJzN/oEPO5lIbYCtTZb1zu00AA5hTPg3I4vraBHFAUXCxKcGWJfML0e5q478zeIIHR0TwYl0Nw== X-Received: by 2002:aa7:d783:: with SMTP id s3mr28467613edq.214.1604509050947; Wed, 04 Nov 2020 08:57:30 -0800 (PST) Received: from yoga-910.localhost ([188.25.2.177]) by smtp.gmail.com with ESMTPSA id l12sm1354748edt.46.2020.11.04.08.57.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Nov 2020 08:57:30 -0800 (PST) From: Ioana Ciornei To: Greg Kroah-Hartman , Andrew Lunn Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Ioana Ciornei Subject: [RFC 2/9] staging: dpaa2-switch: setup buffer pool for control traffic Date: Wed, 4 Nov 2020 18:57:13 +0200 Message-Id: <20201104165720.2566399-3-ciorneiioana@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201104165720.2566399-1-ciorneiioana@gmail.com> References: <20201104165720.2566399-1-ciorneiioana@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ioana Ciornei Allocate and setup a buffer pool, needed on the Rx path of the control interface. Also, define the Rx buffer size seen by the WRIOP from the PAGE_SIZE buffers seeded. Signed-off-by: Ioana Ciornei --- drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 12 +++ drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 31 ++++++++ drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 26 +++++++ drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 90 ++++++++++++++++++++++ drivers/staging/fsl-dpaa2/ethsw/ethsw.h | 10 +++ 5 files changed, 169 insertions(+) diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h index 24c902eb63e3..e27e86d5d4fb 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h @@ -8,6 +8,8 @@ #ifndef __FSL_DPSW_CMD_H #define __FSL_DPSW_CMD_H +#include "dpsw.h" + /* DPSW Version */ #define DPSW_VER_MAJOR 8 #define DPSW_VER_MINOR 1 @@ -74,6 +76,7 @@ #define DPSW_CMDID_IF_SET_PRIMARY_MAC_ADDR DPSW_CMD_ID(0x0A9) #define DPSW_CMDID_CTRL_IF_GET_ATTR DPSW_CMD_ID(0x0A0) +#define DPSW_CMDID_CTRL_IF_SET_POOLS DPSW_CMD_ID(0x0A1) /* Macros for accessing command fields smaller than 1byte */ #define DPSW_MASK(field) \ @@ -377,6 +380,15 @@ struct dpsw_rsp_ctrl_if_get_attr { __le32 tx_err_conf_fqid; }; +#define DPSW_BACKUP_POOL(val, order) (((val) & 0x1) << (order)) +struct dpsw_cmd_ctrl_if_set_pools { + u8 num_dpbp; + u8 backup_pool_mask; + __le16 pad; + __le32 dpbp_id[DPSW_MAX_DPBP]; + __le16 buffer_size[DPSW_MAX_DPBP]; +}; + struct dpsw_rsp_get_api_version { __le16 version_major; __le16 version_minor; diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c index 996f13abfb1b..01ebdb12adec 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c @@ -1213,6 +1213,37 @@ int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, return 0; } +/** + * dpsw_ctrl_if_set_pools() - Set control interface buffer pools + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @cfg: Buffer pools configuration + * + * Return: '0' on Success; Error code otherwise. + */ +int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + const struct dpsw_ctrl_if_pools_cfg *cfg) +{ + struct dpsw_cmd_ctrl_if_set_pools *cmd_params; + struct fsl_mc_command cmd = { 0 }; + int i; + + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_SET_POOLS, + cmd_flags, token); + cmd_params = (struct dpsw_cmd_ctrl_if_set_pools *)cmd.params; + cmd_params->num_dpbp = cfg->num_dpbp; + for (i = 0; i < DPSW_MAX_DPBP; i++) { + cmd_params->dpbp_id[i] = cpu_to_le32(cfg->pools[i].dpbp_id); + cmd_params->buffer_size[i] = + cpu_to_le16(cfg->pools[i].buffer_size); + cmd_params->backup_pool_mask |= + DPSW_BACKUP_POOL(cfg->pools[i].backup_pool, i); + } + + return mc_send_command(mc_io, &cmd); +} + /** * dpsw_get_api_version() - Get Data Path Switch API version * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index fcc07991119d..5ad7c0634992 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -196,6 +196,32 @@ enum dpsw_queue_type { DPSW_QUEUE_RX_ERR, }; +/** + * Maximum number of DPBP + */ +#define DPSW_MAX_DPBP 8 + +/** + * struct dpsw_ctrl_if_pools_cfg - Control interface buffer pools configuration + * @num_dpbp: Number of DPBPs + * @pools: Array of buffer pools parameters; The number of valid entries + * must match 'num_dpbp' value + * @pools.dpbp_id: DPBP object ID + * @pools.buffer_size: Buffer size + * @pools.backup_pool: Backup pool + */ +struct dpsw_ctrl_if_pools_cfg { + u8 num_dpbp; + struct { + int dpbp_id; + u16 buffer_size; + int backup_pool; + } pools[DPSW_MAX_DPBP]; +}; + +int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + const struct dpsw_ctrl_if_pools_cfg *cfg); + /** * enum dpsw_action - Action selection for special/control frames * @DPSW_ACTION_DROP: Drop frame diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index c22b9ad558c8..21d3ff6b9f55 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1503,6 +1503,83 @@ static int dpaa2_switch_setup_fqs(struct ethsw_core *ethsw) return 0; } +static int dpaa2_switch_setup_dpbp(struct ethsw_core *ethsw) +{ + struct dpsw_ctrl_if_pools_cfg dpsw_ctrl_if_pools_cfg = { 0 }; + struct device *dev = ethsw->dev; + struct fsl_mc_device *dpbp_dev; + struct dpbp_attr dpbp_attrs; + int err; + + err = fsl_mc_object_allocate(to_fsl_mc_device(dev), FSL_MC_POOL_DPBP, + &dpbp_dev); + if (err) { + if (err == -ENXIO) + err = -EPROBE_DEFER; + else + dev_err(dev, "DPBP device allocation failed\n"); + return err; + } + ethsw->dpbp_dev = dpbp_dev; + + err = dpbp_open(ethsw->mc_io, 0, dpbp_dev->obj_desc.id, + &dpbp_dev->mc_handle); + if (err) { + dev_err(dev, "dpbp_open() failed\n"); + goto err_open; + } + + err = dpbp_reset(ethsw->mc_io, 0, dpbp_dev->mc_handle); + if (err) { + dev_err(dev, "dpbp_reset() failed\n"); + goto err_reset; + } + + err = dpbp_enable(ethsw->mc_io, 0, dpbp_dev->mc_handle); + if (err) { + dev_err(dev, "dpbp_enable() failed\n"); + goto err_enable; + } + + err = dpbp_get_attributes(ethsw->mc_io, 0, dpbp_dev->mc_handle, + &dpbp_attrs); + if (err) { + dev_err(dev, "dpbp_get_attributes() failed\n"); + goto err_get_attr; + } + + dpsw_ctrl_if_pools_cfg.num_dpbp = 1; + dpsw_ctrl_if_pools_cfg.pools[0].dpbp_id = dpbp_attrs.id; + dpsw_ctrl_if_pools_cfg.pools[0].buffer_size = DPAA2_SWITCH_RX_BUF_SIZE; + dpsw_ctrl_if_pools_cfg.pools[0].backup_pool = 0; + + err = dpsw_ctrl_if_set_pools(ethsw->mc_io, 0, ethsw->dpsw_handle, + &dpsw_ctrl_if_pools_cfg); + if (err) { + dev_err(dev, "dpsw_ctrl_if_set_pools() failed\n"); + goto err_get_attr; + } + ethsw->bpid = dpbp_attrs.id; + + return 0; + +err_get_attr: + dpbp_disable(ethsw->mc_io, 0, dpbp_dev->mc_handle); +err_enable: +err_reset: + dpbp_close(ethsw->mc_io, 0, dpbp_dev->mc_handle); +err_open: + fsl_mc_object_free(dpbp_dev); + return err; +} + +static void dpaa2_switch_free_dpbp(struct ethsw_core *ethsw) +{ + dpbp_disable(ethsw->mc_io, 0, ethsw->dpbp_dev->mc_handle); + dpbp_close(ethsw->mc_io, 0, ethsw->dpbp_dev->mc_handle); + fsl_mc_object_free(ethsw->dpbp_dev); +} + static int dpaa2_switch_ctrl_if_setup(struct ethsw_core *ethsw) { int err; @@ -1512,6 +1589,11 @@ static int dpaa2_switch_ctrl_if_setup(struct ethsw_core *ethsw) if (err) return err; + /* setup the buffer poll needed on the Rx path */ + err = dpaa2_switch_setup_dpbp(ethsw); + if (err) + return err; + return 0; } @@ -1693,6 +1775,11 @@ static void dpaa2_switch_takedown(struct fsl_mc_device *sw_dev) dev_warn(dev, "dpsw_close err %d\n", err); } +static void dpaa2_switch_ctrl_if_teardown(struct ethsw_core *ethsw) +{ + dpaa2_switch_free_dpbp(ethsw); +} + static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev) { struct ethsw_port_priv *port_priv; @@ -1703,6 +1790,9 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev) dev = &sw_dev->dev; ethsw = dev_get_drvdata(dev); + if (dpaa2_switch_has_ctrl_if(ethsw)) + dpaa2_switch_ctrl_if_teardown(ethsw); + dpaa2_switch_teardown_irqs(sw_dev); dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h index 3189dd72a51b..84130134aa67 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h @@ -17,6 +17,7 @@ #include #include #include +#include #include "dpsw.h" @@ -42,6 +43,13 @@ /* Number of receive queues (one RX and one TX_CONF) */ #define DPAA2_SWITCH_RX_NUM_FQS 2 +/* Hardware requires alignment for ingress/egress buffer addresses */ +#define DPAA2_SWITCH_RX_BUF_RAW_SIZE PAGE_SIZE +#define DPAA2_SWITCH_RX_BUF_TAILROOM \ + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +#define DPAA2_SWITCH_RX_BUF_SIZE \ + (DPAA2_SWITCH_RX_BUF_RAW_SIZE - DPAA2_SWITCH_RX_BUF_TAILROOM) + extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops; struct ethsw_core; @@ -86,6 +94,8 @@ struct ethsw_core { struct workqueue_struct *workqueue; struct dpaa2_switch_fq fq[DPAA2_SWITCH_RX_NUM_FQS]; + struct fsl_mc_device *dpbp_dev; + u16 bpid; }; static inline bool dpaa2_switch_has_ctrl_if(struct ethsw_core *ethsw) From patchwork Wed Nov 4 16:57:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ioana Ciornei X-Patchwork-Id: 318452 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=-12.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HK_RANDOM_FROM,INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, 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 23C51C388F9 for ; Wed, 4 Nov 2020 16:57:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A82132072C for ; Wed, 4 Nov 2020 16:57:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GQ94Ckrf" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731729AbgKDQ5m (ORCPT ); Wed, 4 Nov 2020 11:57:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731619AbgKDQ5h (ORCPT ); Wed, 4 Nov 2020 11:57:37 -0500 Received: from mail-ed1-x532.google.com (mail-ed1-x532.google.com [IPv6:2a00:1450:4864:20::532]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 59AF3C0613D4; Wed, 4 Nov 2020 08:57:37 -0800 (PST) Received: by mail-ed1-x532.google.com with SMTP id o20so5077876eds.3; Wed, 04 Nov 2020 08:57:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=xdbs/utMxlYWSDn4luGomZ8YgspbSA2hgOF0Xj6UKtQ=; b=GQ94Ckrf6QB2xdZ3p5rsOmJvrL0Nty2yY/8q1iBgd4DVZ34bW8rXANhT8csdp7TgQM wOUIyZAkaNgRoR+34NAsppiBPz4T2guBBhErdzumm0KnCql46UvE4BS5kAebAr6HC9s6 aYpP6c6eQ3O/PxI9nr0tIAkjsH3pMcQA/+H+ALu4Kze6YMvIDi0dlqHDi6PLV6bbsWLk 1+th645ltUMZ+kXD5DJXlTkZ2uVBDlWRpjBNMzRnKh8DFsuvPMttpdkIla6F50KC7bwp xwgDm5YzNC7b9FPAiOcPI/o13rR/+OCAS46Taj0VOEbGs9oyQn5qoy3PJgUtPxt4TRPC 6U6A== 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:mime-version:content-transfer-encoding; bh=xdbs/utMxlYWSDn4luGomZ8YgspbSA2hgOF0Xj6UKtQ=; b=goa6brLuQZYx0eDt/Tm1YmlXneon6OqCsTY4L0F5JJ60mN2KytbtREycgZWRdklJZo rh61svDctnhxhzofBz/kbj941Kr+PASegLa1zQEKpxVx10Q+VhY12zwlRCFju4l5jh62 HfEG6E6B9bn7XwlnSerANq2uPmpvrolVZJSjTB17iayaRf+cYE3zLJAECLNdm2EmMjUp B7iJPLxdkeNuXXyJu9CBWuon4V8g78HuyTYCXL7Fw5NnpJdPZU4pn0oyrRZOjHTq2Nt0 LtqTCfAQZn/4HOPBViYea4lz2MWss73Mewyq06VqTelKQJJvnZrYPA236N0T1vQIkRrj F8DA== X-Gm-Message-State: AOAM532YSb7tuorfaE8z8sMexk4MKPDatgxtjCE3+YQTqLIoaSbIvS3b wxc/zmoEbDkAbY49XFhhDAI= X-Google-Smtp-Source: ABdhPJwQvsa+um/VmlvXh3Nu9Veu/vDydLxr0o5bySHveXw7e+1U8ryryBVgQ0jbreFLpIMbz9imWQ== X-Received: by 2002:a50:a683:: with SMTP id e3mr28057095edc.33.1604509055813; Wed, 04 Nov 2020 08:57:35 -0800 (PST) Received: from yoga-910.localhost ([188.25.2.177]) by smtp.gmail.com with ESMTPSA id l12sm1354748edt.46.2020.11.04.08.57.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Nov 2020 08:57:35 -0800 (PST) From: Ioana Ciornei To: Greg Kroah-Hartman , Andrew Lunn Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Ioana Ciornei Subject: [RFC 6/9] staging: dpaa2-switch: add .ndo_start_xmit() callback Date: Wed, 4 Nov 2020 18:57:17 +0200 Message-Id: <20201104165720.2566399-7-ciorneiioana@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201104165720.2566399-1-ciorneiioana@gmail.com> References: <20201104165720.2566399-1-ciorneiioana@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ioana Ciornei Implement the .ndo_start_xmit() callback for the switch port interfaces. For each of the switch ports, gather the corresponding queue destination ID (QDID) necessary for Tx enqueueing. We'll reserve 64 bytes for software annotations, where we keep a skb backpointer used on the Tx confirmation side for releasing the allocated memory. At the moment, we only support linear skbs. Signed-off-by: Ioana Ciornei --- drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 24 ++++ drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 41 ++++++ drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 28 ++++ drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 146 ++++++++++++++++++--- drivers/staging/fsl-dpaa2/ethsw/ethsw.h | 14 ++ 5 files changed, 238 insertions(+), 15 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h index 9caff864ae3e..e239747f8a54 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h @@ -45,6 +45,8 @@ #define DPSW_CMDID_IF_ENABLE DPSW_CMD_ID(0x03D) #define DPSW_CMDID_IF_DISABLE DPSW_CMD_ID(0x03E) +#define DPSW_CMDID_IF_GET_ATTR DPSW_CMD_ID(0x042) + #define DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH DPSW_CMD_ID(0x044) #define DPSW_CMDID_IF_GET_LINK_STATE DPSW_CMD_ID(0x046) @@ -258,6 +260,28 @@ struct dpsw_cmd_if { __le16 if_id; }; +#define DPSW_ADMIT_UNTAGGED_SHIFT 0 +#define DPSW_ADMIT_UNTAGGED_SIZE 4 +#define DPSW_ENABLED_SHIFT 5 +#define DPSW_ENABLED_SIZE 1 +#define DPSW_ACCEPT_ALL_VLAN_SHIFT 6 +#define DPSW_ACCEPT_ALL_VLAN_SIZE 1 + +struct dpsw_rsp_if_get_attr { + /* cmd word 0 */ + /* from LSB: admit_untagged:4 enabled:1 accept_all_vlan:1 */ + u8 conf; + u8 pad1; + u8 num_tcs; + u8 pad2; + __le16 qdid; + /* cmd word 1 */ + __le32 options; + __le32 pad3; + /* cmd word 2 */ + __le32 rate; +}; + struct dpsw_cmd_if_set_max_frame_length { __le16 if_id; __le16 frame_length; diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c index 785140d4652c..2a1967754913 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c @@ -704,6 +704,47 @@ int dpsw_if_disable(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpsw_if_get_attributes() - Function obtains attributes of interface + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @if_id: Interface Identifier + * @attr: Returned interface attributes + * + * Return: Completion status. '0' on Success; Error code otherwise. + */ +int dpsw_if_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u16 if_id, struct dpsw_if_attr *attr) +{ + struct dpsw_rsp_if_get_attr *rsp_params; + struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if *cmd_params; + int err; + + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_ATTR, cmd_flags, + token); + cmd_params = (struct dpsw_cmd_if *)cmd.params; + cmd_params->if_id = cpu_to_le16(if_id); + + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + rsp_params = (struct dpsw_rsp_if_get_attr *)cmd.params; + attr->num_tcs = rsp_params->num_tcs; + attr->rate = le32_to_cpu(rsp_params->rate); + attr->options = le32_to_cpu(rsp_params->options); + attr->qdid = le16_to_cpu(rsp_params->qdid); + attr->enabled = dpsw_get_field(rsp_params->conf, ENABLED); + attr->accept_all_vlan = dpsw_get_field(rsp_params->conf, + ACCEPT_ALL_VLAN); + attr->admit_untagged = dpsw_get_field(rsp_params->conf, + ADMIT_UNTAGGED); + + return 0; +} + /** * dpsw_if_set_max_frame_length() - Set Maximum Receive frame length. * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index 718242ea7d87..a6ed6860946c 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -440,6 +440,34 @@ int dpsw_if_disable(struct fsl_mc_io *mc_io, u16 token, u16 if_id); +/** + * struct dpsw_if_attr - Structure representing DPSW interface attributes + * @num_tcs: Number of traffic classes + * @rate: Transmit rate in bits per second + * @options: Interface configuration options (bitmap) + * @enabled: Indicates if interface is enabled + * @accept_all_vlan: The device discards/accepts incoming frames + * for VLANs that do not include this interface + * @admit_untagged: When set to 'DPSW_ADMIT_ONLY_VLAN_TAGGED', the device + * discards untagged frames or priority-tagged frames received on + * this interface; + * When set to 'DPSW_ADMIT_ALL', untagged frames or priority- + * tagged frames received on this interface are accepted + * @qdid: control frames transmit qdid + */ +struct dpsw_if_attr { + u8 num_tcs; + u32 rate; + u32 options; + int enabled; + int accept_all_vlan; + enum dpsw_accepted_frames admit_untagged; + u16 qdid; +}; + +int dpsw_if_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u16 if_id, struct dpsw_if_attr *attr); + int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index d09aa4a5126a..7805f0e58ec2 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -477,6 +477,7 @@ static int dpaa2_switch_port_change_mtu(struct net_device *netdev, int mtu) static int dpaa2_switch_port_carrier_state_sync(struct net_device *netdev) { struct ethsw_port_priv *port_priv = netdev_priv(netdev); + struct ethsw_core *ethsw = port_priv->ethsw_data; struct dpsw_link_state state; int err; @@ -497,10 +498,15 @@ static int dpaa2_switch_port_carrier_state_sync(struct net_device *netdev) WARN_ONCE(state.up > 1, "Garbage read into link_state"); if (state.up != port_priv->link_state) { - if (state.up) + if (state.up) { netif_carrier_on(netdev); - else + if (dpaa2_switch_has_ctrl_if(ethsw)) + netif_tx_start_all_queues(netdev); + } else { netif_carrier_off(netdev); + if (dpaa2_switch_has_ctrl_if(ethsw)) + netif_tx_stop_all_queues(netdev); + } port_priv->link_state = state.up; } @@ -554,8 +560,10 @@ static int dpaa2_switch_port_open(struct net_device *netdev) struct ethsw_core *ethsw = port_priv->ethsw_data; int err; - /* No need to allow Tx as control interface is disabled */ - netif_tx_stop_all_queues(netdev); + if (!dpaa2_switch_has_ctrl_if(port_priv->ethsw_data)) { + /* No need to allow Tx as control interface is disabled */ + netif_tx_stop_all_queues(netdev); + } /* Explicitly set carrier off, otherwise * netif_carrier_ok() will return true and cause 'ip link show' @@ -610,15 +618,6 @@ static int dpaa2_switch_port_stop(struct net_device *netdev) return 0; } -static netdev_tx_t dpaa2_switch_port_dropframe(struct sk_buff *skb, - struct net_device *netdev) -{ - /* we don't support I/O for now, drop the frame */ - dev_kfree_skb_any(skb); - - return NETDEV_TX_OK; -} - static int dpaa2_switch_port_parent_id(struct net_device *dev, struct netdev_phys_item_id *ppid) { @@ -835,6 +834,114 @@ static void dpaa2_switch_free_fd(const struct ethsw_core *ethsw, dev_kfree_skb(skb); } +static int dpaa2_switch_build_single_fd(struct ethsw_core *ethsw, + struct sk_buff *skb, + struct dpaa2_fd *fd) +{ + struct device *dev = ethsw->dev; + struct sk_buff **skbh; + dma_addr_t addr; + u8 *buff_start; + void *hwa; + + buff_start = PTR_ALIGN(skb->data - DPAA2_SWITCH_TX_DATA_OFFSET - + DPAA2_SWITCH_TX_BUF_ALIGN, + DPAA2_SWITCH_TX_BUF_ALIGN); + + /* Clear FAS to have consistent values for TX confirmation. It is + * located in the first 8 bytes of the buffer's hardware annotation + * area + */ + hwa = buff_start + DPAA2_SWITCH_SWA_SIZE; + memset(hwa, 0, 8); + + /* Store a backpointer to the skb at the beginning of the buffer + * (in the private data area) such that we can release it + * on Tx confirm + */ + skbh = (struct sk_buff **)buff_start; + *skbh = skb; + + addr = dma_map_single(dev, buff_start, + skb_tail_pointer(skb) - buff_start, + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev, addr))) + return -ENOMEM; + + /* Setup the FD fields */ + memset(fd, 0, sizeof(*fd)); + + dpaa2_fd_set_addr(fd, addr); + dpaa2_fd_set_offset(fd, (u16)(skb->data - buff_start)); + dpaa2_fd_set_len(fd, skb->len); + dpaa2_fd_set_format(fd, dpaa2_fd_single); + + return 0; +} + +static netdev_tx_t dpaa2_switch_port_tx(struct sk_buff *skb, + struct net_device *net_dev) +{ + struct ethsw_port_priv *port_priv = netdev_priv(net_dev); + struct ethsw_core *ethsw = port_priv->ethsw_data; + int retries = DPAA2_SWITCH_SWP_BUSY_RETRIES; + struct dpaa2_fd fd; + int err; + + if (!dpaa2_switch_has_ctrl_if(ethsw)) + goto err_free_skb; + + if (unlikely(skb_headroom(skb) < DPAA2_SWITCH_NEEDED_HEADROOM)) { + struct sk_buff *ns; + + ns = skb_realloc_headroom(skb, DPAA2_SWITCH_NEEDED_HEADROOM); + if (unlikely(!ns)) { + netdev_err(net_dev, "Error reallocating skb headroom\n"); + goto err_free_skb; + } + dev_kfree_skb(skb); + skb = ns; + } + + /* We'll be holding a back-reference to the skb until Tx confirmation */ + skb = skb_unshare(skb, GFP_ATOMIC); + if (unlikely(!skb)) { + /* skb_unshare() has already freed the skb */ + netdev_err(net_dev, "Error copying the socket buffer\n"); + goto err_exit; + } + + if (skb_is_nonlinear(skb)) { + netdev_err(net_dev, "No support for non-linear SKBs!\n"); + goto err_free_skb; + } + + err = dpaa2_switch_build_single_fd(ethsw, skb, &fd); + if (unlikely(err)) { + netdev_err(net_dev, "ethsw_build_*_fd() %d\n", err); + goto err_free_skb; + } + + do { + err = dpaa2_io_service_enqueue_qd(NULL, + port_priv->tx_qdid, + 8, 0, &fd); + retries--; + } while (err == -EBUSY && retries); + + if (unlikely(err < 0)) { + dpaa2_switch_free_fd(ethsw, &fd); + goto err_exit; + } + + return NETDEV_TX_OK; + +err_free_skb: + dev_kfree_skb(skb); +err_exit: + return NETDEV_TX_OK; +} + static const struct net_device_ops dpaa2_switch_port_ops = { .ndo_open = dpaa2_switch_port_open, .ndo_stop = dpaa2_switch_port_stop, @@ -848,7 +955,7 @@ static const struct net_device_ops dpaa2_switch_port_ops = { .ndo_fdb_del = dpaa2_switch_port_fdb_del, .ndo_fdb_dump = dpaa2_switch_port_fdb_dump, - .ndo_start_xmit = dpaa2_switch_port_dropframe, + .ndo_start_xmit = dpaa2_switch_port_tx, .ndo_get_port_parent_id = dpaa2_switch_port_parent_id, .ndo_get_phys_port_name = dpaa2_switch_port_get_phys_name, }; @@ -2237,6 +2344,7 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port) { struct net_device *netdev = port_priv->netdev; struct ethsw_core *ethsw = port_priv->ethsw_data; + struct dpsw_if_attr dpsw_if_attr; struct dpsw_vlan_if_cfg vcfg; int err; @@ -2263,7 +2371,15 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port) if (err) netdev_err(netdev, "dpsw_vlan_remove_if err %d\n", err); - return err; + err = dpsw_if_get_attributes(ethsw->mc_io, 0, ethsw->dpsw_handle, + port_priv->idx, &dpsw_if_attr); + if (err) { + netdev_err(netdev, "dpsw_if_get_attributes err %d\n", err); + return err; + } + port_priv->tx_qdid = dpsw_if_attr.qdid; + + return 0; } static void dpaa2_switch_unregister_notifier(struct device *dev) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h index bd24be2c6308..b267c04e2008 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h @@ -66,6 +66,19 @@ */ #define DPAA2_SWITCH_SWP_BUSY_RETRIES 1000 +/* Hardware annotation buffer size */ +#define DPAA2_SWITCH_HWA_SIZE 64 +/* Software annotation buffer size */ +#define DPAA2_SWITCH_SWA_SIZE 64 + +#define DPAA2_SWITCH_TX_BUF_ALIGN 64 + +#define DPAA2_SWITCH_TX_DATA_OFFSET \ + (DPAA2_SWITCH_HWA_SIZE + DPAA2_SWITCH_SWA_SIZE) + +#define DPAA2_SWITCH_NEEDED_HEADROOM \ + (DPAA2_SWITCH_TX_DATA_OFFSET + DPAA2_SWITCH_TX_BUF_ALIGN) + extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops; struct ethsw_core; @@ -92,6 +105,7 @@ struct ethsw_port_priv { u8 vlans[VLAN_VID_MASK + 1]; u16 pvid; struct net_device *bridge_dev; + u16 tx_qdid; }; /* Switch data */ From patchwork Wed Nov 4 16:57:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ioana Ciornei X-Patchwork-Id: 318450 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=-12.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HK_RANDOM_FROM,INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, 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 32B84C2D0A3 for ; Wed, 4 Nov 2020 16:58:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BB49D2071A for ; Wed, 4 Nov 2020 16:58:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FiBJYJhx" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731902AbgKDQ6O (ORCPT ); Wed, 4 Nov 2020 11:58:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41046 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731694AbgKDQ5k (ORCPT ); Wed, 4 Nov 2020 11:57:40 -0500 Received: from mail-ed1-x543.google.com (mail-ed1-x543.google.com [IPv6:2a00:1450:4864:20::543]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 15EFDC0613D4; Wed, 4 Nov 2020 08:57:40 -0800 (PST) Received: by mail-ed1-x543.google.com with SMTP id k9so23189190edo.5; Wed, 04 Nov 2020 08:57:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=n5sGF1XqNRNaQRaYaE7ck1Zj8iWI/yaXNjIgNVguXWQ=; b=FiBJYJhxaPY72lPL+XZRgnCmwsKSqP9B9ju/FpIPCGgiYl0shTuM0MA9FypcHonYSY 31ONHp6G8MZ9cKkGYisaE2hwOKQ7mDJpMVue7pw+z095Bq/h3jnQuEy8loyW6sLjqJEw LWYRF0jDt2pYP15qPGoKzDc9T7PTlXREqB4mUt2PEa9qQ5HiPxXPDsxAEqOp9hpgWgzI c37XqTE8DBeT5V6Qa5U8ua/TTdT3bpU9uegK+dP6Im1/xD22+fCD9P1oNlEN8lHzmCJH Io1csRscEv1ino4hMe6/bSMgYQ3vcxJtm1m9aF5+HG2KmE4h//uBgd1gn/DF2MMJ24bR KCuw== 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:mime-version:content-transfer-encoding; bh=n5sGF1XqNRNaQRaYaE7ck1Zj8iWI/yaXNjIgNVguXWQ=; b=hlDWKHJJp+RH3Tvlft6bH4dMqX8PoUf6Ni2d6A84L3+pXmT/88ZsXG+NH/bypMxhE1 XtN6FPdZuSbwuD9+CeEkURrAr7cT2byJtmclgVr4AWgJ+owg05Rkzy3Lyamn9fN/iS+R ytHuRJ2H1siHiNqqxA6pOFTRjMQJo1R2lUmM5dgDYdelA9YpWoULT3+QZGfzZRwC5brZ 5KZ1dBxOwua4BXfMsUJIC/yqSxq44m1zl4wAE4bq4PUJbczF+NLIw1crC8u2Wx7E7lqz +uleL4UsW/WQT9CB+zyagHMX5yipGI6ik0EaDtCvzv3y0/pZQ/VzFQjZ7FDtzML1t59z DY4g== X-Gm-Message-State: AOAM530lGcjB0smvzuu3T27InUStPSaIM4xffjVg/p/KITdt664ym9CV k/hmi55aWVtRLckgRf5cUKs= X-Google-Smtp-Source: ABdhPJwsNpEZUVNdYE3wKYvyBCeVI2Fy6rOz8VnKHpwjtGG7NNYdwsF8P3cVl30G99fXqRx5aYc+lA== X-Received: by 2002:aa7:c90d:: with SMTP id b13mr13963066edt.136.1604509058645; Wed, 04 Nov 2020 08:57:38 -0800 (PST) Received: from yoga-910.localhost ([188.25.2.177]) by smtp.gmail.com with ESMTPSA id l12sm1354748edt.46.2020.11.04.08.57.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Nov 2020 08:57:38 -0800 (PST) From: Ioana Ciornei To: Greg Kroah-Hartman , Andrew Lunn Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Ioana Ciornei Subject: [RFC 8/9] staging: dpaa2-switch: properly setup switching domains Date: Wed, 4 Nov 2020 18:57:19 +0200 Message-Id: <20201104165720.2566399-9-ciorneiioana@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201104165720.2566399-1-ciorneiioana@gmail.com> References: <20201104165720.2566399-1-ciorneiioana@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ioana Ciornei Until now, the DPAA2 switch was not capable to properly setup it's switching domains depending on the existence, or lack thereof, of a upper bridge device. This meant that all switch ports of a DPSW object were switching by default even though they were not under the same bridge device. Another issue was the inability to actually add the CPU in the flooding domains (broadcast, unknown unicast etc) of a particular switch port. This meant that a simple ping on a switch interface was not possible since no broadcast ARP frame would actually reach the CPU queues. This patch tries to fix exactly these problems by: * Creating and managing a FDB table for each flooding domain. This means that when a switch interface is not bridged it will use it's own FDB table. While in bridged mode all DPAA2 switch interfaces under the same upper will use the same FDB table, thus leverage the same FDB entries. * Adding a new MC firmware command - dpsw_set_egress_flood() - through which the driver can setup the flooding domains as needed. For example, when the switch interface is standalone, thus not in a bridge with any other DPAA2 switch port, it will setup it's broadcast and unknown unicast flooding domains to only include the control interface (the queues that reach the CPU and the driver can dequeue from). This flooding domain changes when the interface joins a bridge and is configured to include, beside the control interface, all other DPAA2 switch interfaces. Signed-off-by: Ioana Ciornei --- drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 25 ++- drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 96 +++++++++ drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 41 ++++ drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 220 +++++++++++++++++---- drivers/staging/fsl-dpaa2/ethsw/ethsw.h | 6 +- 5 files changed, 345 insertions(+), 43 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h index c6eb9bffdd3e..9b068b07bbcd 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h @@ -15,9 +15,11 @@ #define DPSW_VER_MINOR 4 #define DPSW_CMD_BASE_VERSION 1 +#define DPSW_CMD_2ND_VERSION 2 #define DPSW_CMD_ID_OFFSET 4 #define DPSW_CMD_ID(id) (((id) << DPSW_CMD_ID_OFFSET) | DPSW_CMD_BASE_VERSION) +#define DPSW_CMD_V2(id) (((id) << DPSW_CMD_ID_OFFSET) | DPSW_CMD_2ND_VERSION) /* Command IDs */ #define DPSW_CMDID_CLOSE DPSW_CMD_ID(0x800) @@ -58,7 +60,7 @@ #define DPSW_CMDID_IF_SET_LINK_CFG DPSW_CMD_ID(0x04C) #define DPSW_CMDID_VLAN_ADD DPSW_CMD_ID(0x060) -#define DPSW_CMDID_VLAN_ADD_IF DPSW_CMD_ID(0x061) +#define DPSW_CMDID_VLAN_ADD_IF DPSW_CMD_V2(0x061) #define DPSW_CMDID_VLAN_ADD_IF_UNTAGGED DPSW_CMD_ID(0x062) #define DPSW_CMDID_VLAN_REMOVE_IF DPSW_CMD_ID(0x064) @@ -66,6 +68,8 @@ #define DPSW_CMDID_VLAN_REMOVE_IF_FLOODING DPSW_CMD_ID(0x066) #define DPSW_CMDID_VLAN_REMOVE DPSW_CMD_ID(0x067) +#define DPSW_CMDID_FDB_ADD DPSW_CMD_ID(0x082) +#define DPSW_CMDID_FDB_REMOVE DPSW_CMD_ID(0x083) #define DPSW_CMDID_FDB_ADD_UNICAST DPSW_CMD_ID(0x084) #define DPSW_CMDID_FDB_REMOVE_UNICAST DPSW_CMD_ID(0x085) #define DPSW_CMDID_FDB_ADD_MULTICAST DPSW_CMD_ID(0x086) @@ -83,6 +87,8 @@ #define DPSW_CMDID_CTRL_IF_DISABLE DPSW_CMD_ID(0x0A3) #define DPSW_CMDID_CTRL_IF_SET_QUEUE DPSW_CMD_ID(0x0A6) +#define DPSW_CMDID_SET_EGRESS_FLOOD DPSW_CMD_ID(0x0AC) + /* Macros for accessing command fields smaller than 1byte */ #define DPSW_MASK(field) \ GENMASK(DPSW_##field##_SHIFT + DPSW_##field##_SIZE - 1, \ @@ -324,6 +330,16 @@ struct dpsw_vlan_add { __le16 vlan_id; }; +struct dpsw_cmd_vlan_add_if { + /* cmd word 0 */ + __le16 options; + __le16 vlan_id; + __le16 fdb_id; + __le16 pad0; + /* cmd word 1-4 */ + __le64 if_id; +}; + struct dpsw_cmd_vlan_manage_if { /* cmd word 0 */ __le16 pad0; @@ -445,4 +461,11 @@ struct dpsw_cmd_if_set_mac_addr { u8 mac_addr[6]; }; +struct dpsw_cmd_set_egress_flood { + __le16 fdb_id; + u8 flood_type; + u8 pad[5]; + __le64 if_id; +}; + #endif /* __FSL_DPSW_CMD_H */ diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c index f5cfe61498b8..936984e7af50 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c @@ -986,6 +986,76 @@ int dpsw_vlan_remove(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpsw_fdb_add() - Add FDB to switch and Returns handle to FDB table for + * the reference + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @fdb_id: Returned Forwarding Database Identifier + * @cfg: FDB Configuration + * + * Return: Completion status. '0' on Success; Error code otherwise. + */ +int dpsw_fdb_add(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 *fdb_id, + const struct dpsw_fdb_cfg *cfg) +{ + struct dpsw_cmd_fdb_add *cmd_params; + struct dpsw_rsp_fdb_add *rsp_params; + struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD, + cmd_flags, + token); + cmd_params = (struct dpsw_cmd_fdb_add *)cmd.params; + cmd_params->fdb_aging_time = cpu_to_le16(cfg->fdb_aging_time); + cmd_params->num_fdb_entries = cpu_to_le16(cfg->num_fdb_entries); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + rsp_params = (struct dpsw_rsp_fdb_add *)cmd.params; + *fdb_id = le16_to_cpu(rsp_params->fdb_id); + + return 0; +} + +/** + * dpsw_fdb_remove() - Remove FDB from switch + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @fdb_id: Forwarding Database Identifier + * + * Return: Completion status. '0' on Success; Error code otherwise. + */ +int dpsw_fdb_remove(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 fdb_id) +{ + struct dpsw_cmd_fdb_remove *cmd_params; + struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE, + cmd_flags, + token); + cmd_params = (struct dpsw_cmd_fdb_remove *)cmd.params; + cmd_params->fdb_id = cpu_to_le16(fdb_id); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + /** * dpsw_fdb_add_unicast() - Function adds an unicast entry into MAC lookup table * @mc_io: Pointer to MC portal's I/O object @@ -1493,3 +1563,29 @@ int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) return mc_send_command(mc_io, &cmd); } + +/** + * dpsw_set_egress_flood() - Set egress parameters associated with an FDB ID + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @cfg: Egress flooding configuration + * + * Return: '0' on Success; Error code otherwise. + */ +int dpsw_set_egress_flood(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + const struct dpsw_egress_flood_cfg *cfg) +{ + struct dpsw_cmd_set_egress_flood *cmd_params; + struct fsl_mc_command cmd = { 0 }; + + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_EGRESS_FLOOD, + cmd_flags, + token); + cmd_params = (struct dpsw_cmd_set_egress_flood *)cmd.params; + cmd_params->fdb_id = cpu_to_le16(cfg->fdb_id); + cmd_params->flood_type = cfg->flood_type; + build_if_id_bitmap(&cmd_params->if_id, cfg->if_id, cfg->num_ifs); + + return mc_send_command(mc_io, &cmd); +} diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index 9e30adad4ffa..8fe76c7227ea 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -493,6 +493,8 @@ int dpsw_vlan_add(struct fsl_mc_io *mc_io, u16 vlan_id, const struct dpsw_vlan_cfg *cfg); +#define DPSW_VLAN_ADD_IF_OPT_FDB_ID 0x0001 + /** * struct dpsw_vlan_if_cfg - Set of VLAN Interfaces * @num_ifs: The number of interfaces that are assigned to the egress @@ -502,7 +504,9 @@ int dpsw_vlan_add(struct fsl_mc_io *mc_io, */ struct dpsw_vlan_if_cfg { u16 num_ifs; + u16 options; u16 if_id[DPSW_MAX_IF]; + u16 fdb_id; }; int dpsw_vlan_add_if(struct fsl_mc_io *mc_io, @@ -692,4 +696,41 @@ int dpsw_if_get_primary_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, int dpsw_if_set_primary_mac_addr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u16 if_id, u8 mac_addr[6]); +/** + * struct dpsw_fdb_cfg - FDB Configuration + * @num_fdb_entries: Number of FDB entries + * @fdb_aging_time: Aging time in seconds + */ +struct dpsw_fdb_cfg { + u16 num_fdb_entries; + u16 fdb_aging_time; +}; + +int dpsw_fdb_add(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 *fdb_id, + const struct dpsw_fdb_cfg *cfg); + +int dpsw_fdb_remove(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 fdb_id); + +enum dpsw_flood_type { + DPSW_BROADCAST_FLOOD = 0, + DPSW_UNICAST_FLOOD, + DPSW_MULTICAST_FLOOD, +}; + +struct dpsw_egress_flood_cfg { + u16 fdb_id; + enum dpsw_flood_type flood_type; + u16 num_ifs; + u16 if_id[DPSW_MAX_IF]; +}; + +int dpsw_set_egress_flood(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + const struct dpsw_egress_flood_cfg *cfg); + #endif /* __FSL_DPSW_H */ diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 24bdac6d6005..7a0d9a178cdc 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -25,6 +25,36 @@ #define DEFAULT_VLAN_ID 1 +static u16 dpaa2_switch_port_get_fdb_id(struct ethsw_port_priv *port_priv) +{ + struct ethsw_port_priv *other_port_priv = NULL; + struct net_device *other_dev; + struct list_head *iter; + + /* If not part of a bridge, just use the private FDB */ + if (!port_priv->bridge_dev) + return port_priv->fdb_id; + + /* If part of a bridge, use the FDB of the first dpaa2 switch interface + * to be present in that bridge + */ + netdev_for_each_lower_dev(port_priv->bridge_dev, other_dev, iter) { + if (!dpaa2_switch_port_dev_check(other_dev, NULL)) + continue; + + other_port_priv = netdev_priv(other_dev); + break; + } + + /* We are the first dpaa2 switch interface to join the bridge, just use + * our own FDB + */ + if (!other_port_priv) + other_port_priv = port_priv; + + return other_port_priv->fdb_id; +} + static void *dpaa2_iova_to_virt(struct iommu_domain *domain, dma_addr_t iova_addr) { @@ -133,7 +163,7 @@ static int dpaa2_switch_port_add_vlan(struct ethsw_port_priv *port_priv, { struct ethsw_core *ethsw = port_priv->ethsw_data; struct net_device *netdev = port_priv->netdev; - struct dpsw_vlan_if_cfg vcfg; + struct dpsw_vlan_if_cfg vcfg = {0}; int err; if (port_priv->vlans[vid]) { @@ -141,8 +171,13 @@ static int dpaa2_switch_port_add_vlan(struct ethsw_port_priv *port_priv, return -EEXIST; } + /* If hit, this VLAN rule will lead the packet into the FDB table + * specified in the vlan configuration below + */ vcfg.num_ifs = 1; vcfg.if_id[0] = port_priv->idx; + vcfg.fdb_id = dpaa2_switch_port_get_fdb_id(port_priv); + vcfg.options |= DPSW_VLAN_ADD_IF_OPT_FDB_ID; err = dpsw_vlan_add_if(ethsw->mc_io, 0, ethsw->dpsw_handle, vid, &vcfg); if (err) { netdev_err(netdev, "dpsw_vlan_add_if err %d\n", err); @@ -172,8 +207,10 @@ static int dpaa2_switch_port_add_vlan(struct ethsw_port_priv *port_priv, return 0; } -static int dpaa2_switch_set_learning(struct ethsw_core *ethsw, bool enable) +static int dpaa2_switch_port_set_learning(struct ethsw_port_priv *port_priv, bool enable) { + u16 fdb_id = dpaa2_switch_port_get_fdb_id(port_priv); + struct ethsw_core *ethsw = port_priv->ethsw_data; enum dpsw_fdb_learning_mode learn_mode; int err; @@ -182,13 +219,12 @@ static int dpaa2_switch_set_learning(struct ethsw_core *ethsw, bool enable) else learn_mode = DPSW_FDB_LEARNING_MODE_DIS; - err = dpsw_fdb_set_learning_mode(ethsw->mc_io, 0, ethsw->dpsw_handle, 0, + err = dpsw_fdb_set_learning_mode(ethsw->mc_io, 0, ethsw->dpsw_handle, fdb_id, learn_mode); if (err) { dev_err(ethsw->dev, "dpsw_fdb_set_learning_mode err %d\n", err); return err; } - ethsw->learning = enable; return 0; } @@ -267,15 +303,17 @@ static int dpaa2_switch_port_fdb_add_uc(struct ethsw_port_priv *port_priv, const unsigned char *addr) { struct dpsw_fdb_unicast_cfg entry = {0}; + u16 fdb_id; int err; entry.if_egress = port_priv->idx; entry.type = DPSW_FDB_ENTRY_STATIC; ether_addr_copy(entry.mac_addr, addr); + fdb_id = dpaa2_switch_port_get_fdb_id(port_priv); err = dpsw_fdb_add_unicast(port_priv->ethsw_data->mc_io, 0, port_priv->ethsw_data->dpsw_handle, - 0, &entry); + fdb_id, &entry); if (err) netdev_err(port_priv->netdev, "dpsw_fdb_add_unicast err %d\n", err); @@ -306,6 +344,7 @@ static int dpaa2_switch_port_fdb_add_mc(struct ethsw_port_priv *port_priv, const unsigned char *addr) { struct dpsw_fdb_multicast_cfg entry = {0}; + u16 fdb_id; int err; ether_addr_copy(entry.mac_addr, addr); @@ -313,9 +352,10 @@ static int dpaa2_switch_port_fdb_add_mc(struct ethsw_port_priv *port_priv, entry.num_ifs = 1; entry.if_id[0] = port_priv->idx; + fdb_id = dpaa2_switch_port_get_fdb_id(port_priv); err = dpsw_fdb_add_multicast(port_priv->ethsw_data->mc_io, 0, port_priv->ethsw_data->dpsw_handle, - 0, &entry); + fdb_id, &entry); /* Silently discard error for calling multiple times the add command */ if (err && err != -ENXIO) netdev_err(port_priv->netdev, "dpsw_fdb_add_multicast err %d\n", @@ -723,6 +763,7 @@ static int dpaa2_switch_port_fdb_dump(struct sk_buff *skb, struct netlink_callba u32 fdb_dump_size; int err = 0, i; u8 *dma_mem; + u16 fdb_id; fdb_dump_size = ethsw->sw_attr.max_fdb_entries * sizeof(fdb_entry); dma_mem = kzalloc(fdb_dump_size, GFP_KERNEL); @@ -737,7 +778,8 @@ static int dpaa2_switch_port_fdb_dump(struct sk_buff *skb, struct netlink_callba goto err_map; } - err = dpsw_fdb_dump(ethsw->mc_io, 0, ethsw->dpsw_handle, 0, + fdb_id = dpaa2_switch_port_get_fdb_id(port_priv); + err = dpsw_fdb_dump(ethsw->mc_io, 0, ethsw->dpsw_handle, fdb_id, fdb_dump_iova, fdb_dump_size, &num_fdb_entries); if (err) { netdev_err(net_dev, "dpsw_fdb_dump() = %d\n", err); @@ -960,8 +1002,8 @@ static const struct net_device_ops dpaa2_switch_port_ops = { .ndo_get_phys_port_name = dpaa2_switch_port_get_phys_name, }; -static bool dpaa2_switch_port_dev_check(const struct net_device *netdev, - struct notifier_block *nb) +bool dpaa2_switch_port_dev_check(const struct net_device *netdev, + struct notifier_block *nb) { struct ethsw_port_priv *port_priv = netdev_priv(netdev); @@ -1119,9 +1161,11 @@ static int dpaa2_switch_port_attr_br_flags_set(struct net_device *netdev, if (switchdev_trans_ph_prepare(trans)) return 0; - /* Learning is enabled per switch */ - err = dpaa2_switch_set_learning(port_priv->ethsw_data, - !!(flags & BR_LEARNING)); + /* Learning is enabled per swiching domain, thus all dpaa2 switch + * interfaces under the same bridge will have their flooding state + * changed also + */ + err = dpaa2_switch_port_set_learning(port_priv, !!(flags & BR_LEARNING)); if (err) goto exit; @@ -1403,24 +1447,69 @@ static int dpaa2_switch_port_attr_set_event(struct net_device *netdev, return notifier_from_errno(err); } -/* For the moment, only flood setting needs to be updated */ -static int dpaa2_switch_port_bridge_join(struct net_device *netdev, - struct net_device *upper_dev) +static int dpaa2_switch_port_set_egress_flood(struct ethsw_port_priv *port_priv) { - struct ethsw_port_priv *port_priv = netdev_priv(netdev); struct ethsw_core *ethsw = port_priv->ethsw_data; + struct net_device *netdev = port_priv->netdev; struct ethsw_port_priv *other_port_priv; + struct dpsw_egress_flood_cfg flood_cfg; struct net_device *other_dev; struct list_head *iter; - int i, err; + int i = 0; + int err; - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) - if (ethsw->ports[i]->bridge_dev && - (ethsw->ports[i]->bridge_dev != upper_dev)) { - netdev_err(netdev, - "Only one bridge supported per DPSW object!\n"); - return -EINVAL; + if (port_priv->bridge_dev) { + /* Add all the DPAA2 switch ports found under the same bridge to the + * egress flooding domain + */ + netdev_for_each_lower_dev(port_priv->bridge_dev, other_dev, iter) { + if (!dpaa2_switch_port_dev_check(other_dev, NULL)) + continue; + + other_port_priv = netdev_priv(other_dev); + flood_cfg.if_id[i++] = other_port_priv->idx; } + } else { + flood_cfg.if_id[i++] = port_priv->idx; + } + + /* Add the CTRL interface to the egress flooding domain */ + flood_cfg.if_id[i++] = ethsw->sw_attr.num_ifs; + + /* Use the FDB of the first dpaa2 switch port added to the bridge */ + flood_cfg.fdb_id = dpaa2_switch_port_get_fdb_id(port_priv); + + /* Setup broadcast flooding domain */ + flood_cfg.flood_type = DPSW_BROADCAST_FLOOD; + flood_cfg.num_ifs = i; + err = dpsw_set_egress_flood(ethsw->mc_io, 0, ethsw->dpsw_handle, + &flood_cfg); + if (err) { + netdev_err(netdev, "dpsw_set_egress_flood() = %d\n", err); + return err; + } + + /* Setup unknown unicast flooding domain */ + flood_cfg.flood_type = DPSW_UNICAST_FLOOD; + flood_cfg.num_ifs = i; + err = dpsw_set_egress_flood(ethsw->mc_io, 0, ethsw->dpsw_handle, + &flood_cfg); + if (err) { + netdev_err(netdev, "dpsw_set_egress_flood() = %d\n", err); + return err; + } + + return 0; +} + +static int dpaa2_switch_port_bridge_join(struct net_device *netdev, + struct net_device *upper_dev) +{ + struct ethsw_port_priv *port_priv = netdev_priv(netdev); + struct ethsw_port_priv *other_port_priv; + struct net_device *other_dev; + struct list_head *iter; + int err; netdev_for_each_lower_dev(upper_dev, other_dev, iter) { if (!dpaa2_switch_port_dev_check(other_dev, NULL)) @@ -1434,11 +1523,23 @@ static int dpaa2_switch_port_bridge_join(struct net_device *netdev, } } - /* Enable flooding */ - err = dpaa2_switch_port_set_flood(port_priv, 1); - if (!err) - port_priv->bridge_dev = upper_dev; + /* Delete the previously manually installed VLAN 1 */ + err = dpaa2_switch_port_del_vlan(port_priv, 1); + if (err) + return err; + + /* Keep track of the upper bridge device */ + port_priv->bridge_dev = upper_dev; + + /* Setup the egress flood policy (broadcast, unknown unicast) */ + err = dpaa2_switch_port_set_egress_flood(port_priv); + if (err) + goto err_egress_flood; + + return 0; +err_egress_flood: + port_priv->bridge_dev = NULL; return err; } @@ -1447,10 +1548,24 @@ static int dpaa2_switch_port_bridge_leave(struct net_device *netdev) struct ethsw_port_priv *port_priv = netdev_priv(netdev); int err; - /* Disable flooding */ - err = dpaa2_switch_port_set_flood(port_priv, 0); - if (!err) - port_priv->bridge_dev = NULL; + /* Port is not part of a bridge anymore */ + port_priv->bridge_dev = NULL; + + /* Setup the egress flood policy (broadcast, unknown unicast). + * When the port is not under a bridge, only the CTRL interface is part + * of the flooding domain besides the actual port + */ + err = dpaa2_switch_port_set_egress_flood(port_priv); + if (err) + return err; + + /* Add the VLAN 1 as PVID when not under a bridge. We need this since + * the dpaa2 switch interfaces are not capable to be VLAN unaware + */ + err = dpaa2_switch_port_add_vlan(port_priv, 1, + BRIDGE_VLAN_INFO_UNTAGGED | BRIDGE_VLAN_INFO_PVID); + if (err) + return err; return err; } @@ -2291,13 +2406,6 @@ static int dpaa2_switch_init(struct fsl_mc_device *sw_dev) goto err_close; } - err = dpsw_fdb_set_learning_mode(ethsw->mc_io, 0, ethsw->dpsw_handle, 0, - DPSW_FDB_LEARNING_MODE_HW); - if (err) { - dev_err(dev, "dpsw_fdb_set_learning_mode err %d\n", err); - goto err_close; - } - stp_cfg.vlan_id = DEFAULT_VLAN_ID; stp_cfg.state = DPSW_STP_STATE_FORWARDING; @@ -2352,6 +2460,7 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port) { struct net_device *netdev = port_priv->netdev; struct ethsw_core *ethsw = port_priv->ethsw_data; + struct dpsw_fdb_cfg fdb_cfg = {0}; struct dpsw_if_attr dpsw_if_attr; struct dpsw_vlan_if_cfg vcfg; int err; @@ -2387,6 +2496,38 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port) } port_priv->tx_qdid = dpsw_if_attr.qdid; + /* Create a FDB table for this particular switch port */ + fdb_cfg.num_fdb_entries = ethsw->sw_attr.max_fdb_entries / ethsw->sw_attr.num_ifs; + err = dpsw_fdb_add(ethsw->mc_io, 0, ethsw->dpsw_handle, + &port_priv->fdb_id, &fdb_cfg); + if (err) { + netdev_err(netdev, "dpsw_fdb_add err %d\n", err); + return err; + } + + /* Setup the default learning mode to he HW learning enabled */ + err = dpsw_fdb_set_learning_mode(ethsw->mc_io, 0, ethsw->dpsw_handle, + port_priv->fdb_id, + DPSW_FDB_LEARNING_MODE_HW); + if (err) { + netdev_err(netdev, "dpsw_fdb_set_learning_mode err %d\n", err); + return err; + } + + /* We need to add VLAN 1 as the PVID on this port until it is under a + * bridge since the DPAA2 switch is not able to handle the traffic in a + * VLAN unaware fashion + */ + err = dpaa2_switch_port_add_vlan(port_priv, 1, + BRIDGE_VLAN_INFO_UNTAGGED | BRIDGE_VLAN_INFO_PVID); + if (err) + return err; + + /* Setup the egress flooding domains (broadcast, unknown unicast */ + err = dpaa2_switch_port_set_egress_flood(port_priv); + if (err) + return err; + return 0; } @@ -2562,9 +2703,6 @@ static int dpaa2_switch_probe(struct fsl_mc_device *sw_dev) /* DEFAULT_VLAN_ID is implicitly configured on the switch */ ethsw->vlans[DEFAULT_VLAN_ID] = ETHSW_VLAN_MEMBER; - /* Learning is implicitly enabled */ - ethsw->learning = true; - ethsw->ports = kcalloc(ethsw->sw_attr.num_ifs, sizeof(*ethsw->ports), GFP_KERNEL); if (!(ethsw->ports)) { diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h index b267c04e2008..f905acd18c67 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h @@ -106,6 +106,7 @@ struct ethsw_port_priv { u16 pvid; struct net_device *bridge_dev; u16 tx_qdid; + u16 fdb_id; }; /* Switch data */ @@ -121,7 +122,6 @@ struct ethsw_core { struct iommu_domain *iommu_domain; u8 vlans[VLAN_VID_MASK + 1]; - bool learning; struct notifier_block port_nb; struct notifier_block port_switchdev_nb; @@ -139,4 +139,8 @@ static inline bool dpaa2_switch_has_ctrl_if(struct ethsw_core *ethsw) { return !(ethsw->sw_attr.options & DPSW_OPT_CTRL_IF_DIS); } + +bool dpaa2_switch_port_dev_check(const struct net_device *netdev, + struct notifier_block *nb); + #endif /* __ETHSW_H */ From patchwork Wed Nov 4 16:57:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ioana Ciornei X-Patchwork-Id: 318451 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=-12.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HK_RANDOM_FROM,INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, 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 28E58C2D0A3 for ; Wed, 4 Nov 2020 16:57:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B305A2071A for ; Wed, 4 Nov 2020 16:57:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VVYHkG+R" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731860AbgKDQ54 (ORCPT ); Wed, 4 Nov 2020 11:57:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41054 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731737AbgKDQ5m (ORCPT ); Wed, 4 Nov 2020 11:57:42 -0500 Received: from mail-ed1-x532.google.com (mail-ed1-x532.google.com [IPv6:2a00:1450:4864:20::532]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 68B41C0613D3; Wed, 4 Nov 2020 08:57:41 -0800 (PST) Received: by mail-ed1-x532.google.com with SMTP id o18so23223174edq.4; Wed, 04 Nov 2020 08:57:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=o9FF9knZ/AggymzgxAUUP5RVqKNvcccbw6oC4UAV1qA=; b=VVYHkG+R6ftkEAWlKpME0l9FaKfC0FsYNBeWc5UtF+LI9Srv7fg33+osciTSkxQICP vdU4RrzMEGTTcWfWEeq2CDjj16+s0biMairmrtryva5jBFIsJuHQr9VTgUZpGC0K3Hw9 is5nzXaAIIBux8votMt4HAY7XXupFQY4jMN8DQ4YswMRjUs/QfFYcPfWj530YXmbIkQl mj5eZDGAlewGwiuXBG0TxsHj6XSBC9NJtM1S57PE0h7lc7SN5/dDCVsJKMxFlYPGX09O S/b9GI8j0TrmEuwF7jbhxNMIqn5xSfut5PwYfWAp/QHTcCWYJlZGAL9pOoynq0k2JlHa Mjsw== 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:mime-version:content-transfer-encoding; bh=o9FF9knZ/AggymzgxAUUP5RVqKNvcccbw6oC4UAV1qA=; b=jaesq2xTcnCZIh1QY5F86+AfAqjlACcQkBqC2KVprShfY7q8PUHaaOEErw46m0cKpN jGN/z4MYrUR8VQkoc302NPUKDPURL+tqRjtQP3ircqRE7qEONC27R5YULWpT1J9xeFAf v+Jv2A4UFZ5O0JDPtGUqhajN7f4ZGkpW2CnK3aVFT5JN6C9fxcDpcZ03kJM0Z5kWEnLv V+T1cRtTImcJ8peY18mbmoiX0uLJ5SjxmSMMa/arcUnMB0bbmYYz1UIV0EnYOGwEL+Dm ZmQVUsNFxoAYSWL+OV8FsR50v2HkSu8IxKyV6xbSpIxVoma8iU4OOND2kkbAJKPOmzUe namA== X-Gm-Message-State: AOAM531dEcsqoEGPhYzJbed23bWhDag9ZeNxgC2Q/avvu7TISlQ75Pvy XFkyP4OW6SB0ukgpuJVS+XpOfS7OQUvVfA== X-Google-Smtp-Source: ABdhPJy4FInzJrbBWst/EwXhpAc2yvY3C1dS/ppDLQ1IuTJE/zoAAQAPwNH9sHfr4RMuNHncCWHzxQ== X-Received: by 2002:aa7:c955:: with SMTP id h21mr28375473edt.315.1604509059994; Wed, 04 Nov 2020 08:57:39 -0800 (PST) Received: from yoga-910.localhost ([188.25.2.177]) by smtp.gmail.com with ESMTPSA id l12sm1354748edt.46.2020.11.04.08.57.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Nov 2020 08:57:39 -0800 (PST) From: Ioana Ciornei To: Greg Kroah-Hartman , Andrew Lunn Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Ioana Ciornei Subject: [RFC 9/9] staging: dpaa2-switch: accept only vlan-aware upper devices Date: Wed, 4 Nov 2020 18:57:20 +0200 Message-Id: <20201104165720.2566399-10-ciorneiioana@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201104165720.2566399-1-ciorneiioana@gmail.com> References: <20201104165720.2566399-1-ciorneiioana@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ioana Ciornei The DPAA2 Switch is not capable to handle traffic in a VLAN unaware fashion, thus the previous handling of both the accepted upper devices and the SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING flag was wrong. Fix this by checking if the bridge that we are joining is indeed VLAN aware, if not return an error. Also, the RX VLAN filtering feature is defined as 'on [fixed]' and the .ndo_vlan_rx_add_vid() and .ndo_vlan_rx_kill_vid() callbacks are implemented just by recreating a switchdev_obj_port_vlan object and then calling the same functions used on the switchdev notifier path. In addition, changing the vlan_filtering flag to 0 on a bridge under which a DPAA2 switch interface is present is not supported, thus rejected when SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING is received with such a request. Signed-off-by: Ioana Ciornei --- drivers/staging/fsl-dpaa2/Kconfig | 1 + drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 80 ++++++++++++++++++++++--- drivers/staging/fsl-dpaa2/ethsw/ethsw.h | 7 +++ 3 files changed, 79 insertions(+), 9 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/Kconfig b/drivers/staging/fsl-dpaa2/Kconfig index 244237bb068a..7cb005b6e7ab 100644 --- a/drivers/staging/fsl-dpaa2/Kconfig +++ b/drivers/staging/fsl-dpaa2/Kconfig @@ -12,6 +12,7 @@ config FSL_DPAA2 config FSL_DPAA2_ETHSW tristate "Freescale DPAA2 Ethernet Switch" + depends on BRIDGE || BRIDGE=n depends on FSL_DPAA2 depends on NET_SWITCHDEV help diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 7a0d9a178cdc..4327c432a39f 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -814,6 +814,50 @@ static int dpaa2_switch_port_fdb_dump(struct sk_buff *skb, struct netlink_callba return err; } +static int dpaa2_switch_port_vlan_add(struct net_device *netdev, __be16 proto, + u16 vid) +{ + struct switchdev_obj_port_vlan vlan = { + .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, + .vid_begin = vid, + .vid_end = vid, + /* This API only allows programming tagged, non-PVID VIDs */ + .flags = 0, + }; + struct switchdev_trans trans; + int err; + + trans.ph_prepare = true; + err = dpaa2_switch_port_vlans_add(netdev, &vlan, &trans); + if (err) + return err; + + trans.ph_prepare = false; + err = dpaa2_switch_port_vlans_add(netdev, &vlan, &trans); + if (err) + return err; + + return 0; +} + +static int dpaa2_switch_port_vlan_kill(struct net_device *netdev, __be16 proto, + u16 vid) +{ + struct switchdev_obj_port_vlan vlan = { + .vid_begin = vid, + .vid_end = vid, + /* This API only allows programming tagged, non-PVID VIDs */ + .flags = 0, + }; + int err; + + err = dpaa2_switch_port_vlans_del(netdev, &vlan); + if (err) + return err; + + return 0; +} + static int dpaa2_switch_port_set_mac_addr(struct ethsw_port_priv *port_priv) { struct ethsw_core *ethsw = port_priv->ethsw_data; @@ -996,6 +1040,8 @@ static const struct net_device_ops dpaa2_switch_port_ops = { .ndo_fdb_add = dpaa2_switch_port_fdb_add, .ndo_fdb_del = dpaa2_switch_port_fdb_del, .ndo_fdb_dump = dpaa2_switch_port_fdb_dump, + .ndo_vlan_rx_add_vid = dpaa2_switch_port_vlan_add, + .ndo_vlan_rx_kill_vid = dpaa2_switch_port_vlan_kill, .ndo_start_xmit = dpaa2_switch_port_tx, .ndo_get_port_parent_id = dpaa2_switch_port_parent_id, @@ -1195,7 +1241,8 @@ static int dpaa2_switch_port_attr_set(struct net_device *netdev, attr->u.brport_flags); break; case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: - /* VLANs are supported by default */ + if (!attr->u.vlan_filtering) + return -EOPNOTSUPP; break; default: err = -EOPNOTSUPP; @@ -1205,9 +1252,9 @@ static int dpaa2_switch_port_attr_set(struct net_device *netdev, return err; } -static int dpaa2_switch_port_vlans_add(struct net_device *netdev, - const struct switchdev_obj_port_vlan *vlan, - struct switchdev_trans *trans) +int dpaa2_switch_port_vlans_add(struct net_device *netdev, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans) { struct ethsw_port_priv *port_priv = netdev_priv(netdev); struct ethsw_core *ethsw = port_priv->ethsw_data; @@ -1375,13 +1422,13 @@ static int dpaa2_switch_port_del_vlan(struct ethsw_port_priv *port_priv, u16 vid return 0; } -static int dpaa2_switch_port_vlans_del(struct net_device *netdev, - const struct switchdev_obj_port_vlan *vlan) +int dpaa2_switch_port_vlans_del(struct net_device *netdev, + const struct switchdev_obj_port_vlan *vlan) { struct ethsw_port_priv *port_priv = netdev_priv(netdev); int vid, err = 0; - if (netif_is_bridge_master(vlan->obj.orig_dev)) + if (vlan->obj.orig_dev && netif_is_bridge_master(vlan->obj.orig_dev)) return -EOPNOTSUPP; for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { @@ -1575,14 +1622,23 @@ static int dpaa2_switch_port_netdevice_event(struct notifier_block *nb, { struct net_device *netdev = netdev_notifier_info_to_dev(ptr); struct netdev_notifier_changeupper_info *info = ptr; + struct netlink_ext_ack *extack; struct net_device *upper_dev; int err = 0; if (!dpaa2_switch_port_dev_check(netdev, nb)) return NOTIFY_DONE; - /* Handle just upper dev link/unlink for the moment */ - if (event == NETDEV_CHANGEUPPER) { + extack = netdev_notifier_info_to_extack(&info->info); + switch (event) { + case NETDEV_PRECHANGEUPPER: + upper_dev = info->upper_dev; + if (netif_is_bridge_master(upper_dev) && !br_vlan_enabled(upper_dev)) { + NL_SET_ERR_MSG_MOD(extack, "Cannot join a vlan-unaware bridge"); + err = -EOPNOTSUPP; + } + break; + case NETDEV_CHANGEUPPER: upper_dev = info->upper_dev; if (netif_is_bridge_master(upper_dev)) { if (info->linking) @@ -1590,6 +1646,7 @@ static int dpaa2_switch_port_netdevice_event(struct notifier_block *nb, else err = dpaa2_switch_port_bridge_leave(netdev); } + break; } return notifier_from_errno(err); @@ -2646,6 +2703,11 @@ static int dpaa2_switch_probe_port(struct ethsw_core *ethsw, port_netdev->min_mtu = ETH_MIN_MTU; port_netdev->max_mtu = ETHSW_MAX_FRAME_LENGTH; + /* The DPAA2 Switch's ingress path depends on the VLAN table, + * thus we are not able to disable VLAN filtering. + */ + port_netdev->features = NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER; + err = dpaa2_switch_port_init(port_priv, port_idx); if (err) goto err_port_probe; diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h index f905acd18c67..3163dd2ab2ab 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h @@ -143,4 +143,11 @@ static inline bool dpaa2_switch_has_ctrl_if(struct ethsw_core *ethsw) bool dpaa2_switch_port_dev_check(const struct net_device *netdev, struct notifier_block *nb); +int dpaa2_switch_port_vlans_add(struct net_device *netdev, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans); + +int dpaa2_switch_port_vlans_del(struct net_device *netdev, + const struct switchdev_obj_port_vlan *vlan); + #endif /* __ETHSW_H */