From patchwork Mon Jan 29 05:02:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shinas Rasheed X-Patchwork-Id: 193237 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2087:b0:106:209c:c626 with SMTP id gs7csp366698dyb; Sun, 28 Jan 2024 21:06:06 -0800 (PST) X-Google-Smtp-Source: AGHT+IGlCuDjix4Jt9O6M7n08F4DWvqlaDYcT5wxasQBH4gl0RobTCM1T5ONNlRcL0evv6ENc9h0 X-Received: by 2002:a5b:e82:0:b0:dbf:54ff:29f8 with SMTP id z2-20020a5b0e82000000b00dbf54ff29f8mr2050987ybr.107.1706504766539; Sun, 28 Jan 2024 21:06:06 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706504766; cv=pass; d=google.com; s=arc-20160816; b=wqpqsosSNuaMh7zi7HzAcdovnheBmmfwFbF2fA6nQNePWmb1EJyQV6IKF6XSCXJ5Cb ikn+H5Q4uXaCfx86Ki67SuvgvpIfnECnHGaFJzWEwKo+eOGL13fHUtEiU3gj8HLiAoTv +UqvdLt2jAacoZqj/W1YoDxsNjyHB5GoJsLMPupr5k6Q/Eap8/XYio1I6apbbVqSBH89 JXj2ekC6LeS11p/iOI2BsaiGw1IesnRj3KraIOXrlsPjQE+BxWXc/6nUJih1pp3fGtSR HsydrSh7vQYZTbe2l4aNpO0GT7lq8Lv3AEXI9qDoZ4Sqd79Urmwcu9rLpo+2h8h1cehE +W7A== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=qgQy9Ry/GjCMkuVIYkiPB4LS5/SbY2SDFUizKU12J2Q=; fh=dPIChNgAQb9/Y4RrjRb7C3oBlgWyZvIeJjyk0krVksk=; b=PFRvZJ8LxteVj43lwFmGQ6oVEiQLIrq+r4WEuJ5opGm4S7Jhj/nDnEjoODsPB4tIHA fdzDdEPesSastBwuxsjqvoesmpdxhemdudhZSB2KBnkrJbDJw3tGa3VDnSTsBkdjk+eJ nYmQF009dyS4jas7ZtH3/XK4DG/u9YnLkiFp/PHgOOMSYsM4gCvTQ9e//C7Vp8ekaD5V 7p1niNgixyWohQgsSSrguULpOQ+l4ygEXLVI3F6LJ8ptlNbyG5YRRgcakUS5PHdDEfc/ EHTpWD07WWZSfd0VmdTElnTZT+aKJIc5GE6xmwA2ta7f9dJ8WZiTtmt1Abz8bUjjBchU TBfQ== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=BkfpOTPR; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42169-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42169-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id f2-20020a656282000000b005d8b6ebfb17si3227930pgv.431.2024.01.28.21.06.06 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Jan 2024 21:06:06 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-42169-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=BkfpOTPR; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42169-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42169-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 38D6828245F for ; Mon, 29 Jan 2024 05:06:06 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5DDCA524A8; Mon, 29 Jan 2024 05:03:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="BkfpOTPR" Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 08E93433CF; Mon, 29 Jan 2024 05:03:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.148.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504619; cv=none; b=gudRj98A79zZ3q8zrfui9r6bLi7Iu7DePs5U+D09K8y/dpa1XOSFAJ6PPz1R+pMTXq+9eiRmSyT3MKXL7DRwKh714JX7JSbrRnUR6bLN2+azsWNjV1effGeMpnztKqhjWp8wCT1MoOfa/1vl8UhOzGiHGFaGAC5CpUQD6IJEcQI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504619; c=relaxed/simple; bh=6WUaNk7JhN8WiMCw/XNNerBFbXwh0YH0x2xo346ZJRA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mPyKWiSgWkdLPbtMWFfwbjNaWA5cFi7qOJ3Xg1DsKQcZx+8uhCLDSt0owyUkUUVUR9X8jm+vT9UYDUf3U2lIQCX7D9BvmRE/ZfUX1FVZmRtmgebcKlfEylM8bjQcEIN4E0dwnKF3ufwfQ33I/58dJ4uTk6zHqmJkPxNs3DJDM9Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com; spf=pass smtp.mailfrom=marvell.com; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b=BkfpOTPR; arc=none smtp.client-ip=67.231.148.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 40T4KHTG027202; Sun, 28 Jan 2024 21:03:16 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=qgQy9Ry/GjCMkuVIYkiPB4LS5/SbY2SDFUizKU12J2Q=; b=Bkf pOTPRNK5cZRRoA38YPlU03O1Pz1hDq2b3eXydRRfYXCmCx+X409MyIFG8myfGCsb JEn7eLLg+OntEdJ89Nf/acXNJGpMOETmZNWTUgvoJZBH2OZKwfePjqS5KM+RWtZX rYEzNOx4YxTuKT5+O+BeBjyl+5GPw5xcvUXPM1wh0sbfkT2Ji/LYCTjZWgrYc2gi 8qw8wT240r4aFuAyTAk5ABqUgss2ghkFLh4mx7VrRzK6M9/uihxBwNHlFGhq9Zmi QRL1NERXMVPHpmXRxFZiSPDR4EpRtZiKHnogESr1moySZKrsJ1Y8bqFu49/0DWc9 yjUHr00gOm4fBCZo6SQ== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3vx4vr82cm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 28 Jan 2024 21:03:15 -0800 (PST) Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Sun, 28 Jan 2024 21:03:13 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Sun, 28 Jan 2024 21:03:13 -0800 Received: from ubuntu-PowerEdge-T110-II.sclab.marvell.com (unknown [10.106.27.86]) by maili.marvell.com (Postfix) with ESMTP id 39BF83F7045; Sun, 28 Jan 2024 21:03:13 -0800 (PST) From: Shinas Rasheed To: , CC: , , , , , , , , , , , , "David S. Miller" , Eric Dumazet , "Jonathan Corbet" , Veerasenareddy Burru , "Satananda Burla" , Shannon Nelson , "Tony Nguyen" , Joshua Hay , Rahul Rameshbabu , Brett Creeley , Andrew Lunn , Jacob Keller Subject: [PATCH net-next v5 1/8] octeon_ep_vf: Add driver framework and device initialization Date: Sun, 28 Jan 2024 21:02:47 -0800 Message-ID: <20240129050254.3047778-2-srasheed@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240129050254.3047778-1-srasheed@marvell.com> References: <20240129050254.3047778-1-srasheed@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: jGrPnsz9r3QmmIRV632wf9Ev0H4CPah2 X-Proofpoint-GUID: jGrPnsz9r3QmmIRV632wf9Ev0H4CPah2 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-01-29_02,2024-01-25_01,2023-05-22_02 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789399942167823217 X-GMAIL-MSGID: 1789399942167823217 Add driver framework and device setup and initialization for Octeon PCI Endpoint NIC VF. Add implementation to load module, initialize, register network device, cleanup and unload module. Signed-off-by: Shinas Rasheed --- V5: - No changes V4: https://lore.kernel.org/all/20240108124213.2966536-2-srasheed@marvell.com/ - No changes V3: https://lore.kernel.org/all/20240105203823.2953604-2-srasheed@marvell.com/ - Removed UINT64_MAX, which is unused V2: https://lore.kernel.org/all/20231223134000.2906144-2-srasheed@marvell.com/ - Removed linux/version.h header file from inclusion in octep_vf_main.c V1: https://lore.kernel.org/all/20231221092844.2885872-2-srasheed@marvell.com/ .../device_drivers/ethernet/index.rst | 1 + .../ethernet/marvell/octeon_ep_vf.rst | 24 + drivers/net/ethernet/marvell/Kconfig | 1 + drivers/net/ethernet/marvell/Makefile | 1 + .../net/ethernet/marvell/octeon_ep_vf/Kconfig | 19 + .../ethernet/marvell/octeon_ep_vf/Makefile | 9 + .../marvell/octeon_ep_vf/octep_vf_cn9k.c | 157 ++++++ .../marvell/octeon_ep_vf/octep_vf_cnxk.c | 158 ++++++ .../marvell/octeon_ep_vf/octep_vf_config.h | 160 ++++++ .../marvell/octeon_ep_vf/octep_vf_main.c | 528 ++++++++++++++++++ .../marvell/octeon_ep_vf/octep_vf_main.h | 332 +++++++++++ .../marvell/octeon_ep_vf/octep_vf_mbox.c | 96 ++++ .../marvell/octeon_ep_vf/octep_vf_mbox.h | 25 + .../marvell/octeon_ep_vf/octep_vf_regs_cn9k.h | 154 +++++ .../marvell/octeon_ep_vf/octep_vf_regs_cnxk.h | 162 ++++++ .../marvell/octeon_ep_vf/octep_vf_rx.c | 42 ++ .../marvell/octeon_ep_vf/octep_vf_rx.h | 224 ++++++++ .../marvell/octeon_ep_vf/octep_vf_tx.c | 43 ++ .../marvell/octeon_ep_vf/octep_vf_tx.h | 276 +++++++++ 19 files changed, 2412 insertions(+) create mode 100644 Documentation/networking/device_drivers/ethernet/marvell/octeon_ep_vf.rst create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/Kconfig create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/Makefile create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cnxk.c create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_config.h create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_regs_cn9k.h create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_regs_cnxk.h create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.h create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.h diff --git a/Documentation/networking/device_drivers/ethernet/index.rst b/Documentation/networking/device_drivers/ethernet/index.rst index 43de285b8a92..6932d8c043c2 100644 --- a/Documentation/networking/device_drivers/ethernet/index.rst +++ b/Documentation/networking/device_drivers/ethernet/index.rst @@ -42,6 +42,7 @@ Contents: intel/ice marvell/octeontx2 marvell/octeon_ep + marvell/octeon_ep_vf mellanox/mlx5/index microsoft/netvsc neterion/s2io diff --git a/Documentation/networking/device_drivers/ethernet/marvell/octeon_ep_vf.rst b/Documentation/networking/device_drivers/ethernet/marvell/octeon_ep_vf.rst new file mode 100644 index 000000000000..603133d0b92f --- /dev/null +++ b/Documentation/networking/device_drivers/ethernet/marvell/octeon_ep_vf.rst @@ -0,0 +1,24 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +======================================================================= +Linux kernel networking driver for Marvell's Octeon PCI Endpoint NIC VF +======================================================================= + +Network driver for Marvell's Octeon PCI EndPoint NIC VF. +Copyright (c) 2020 Marvell International Ltd. + +Overview +======== +This driver implements networking functionality of Marvell's Octeon PCI +EndPoint NIC VF. + +Supported Devices +================= +Currently, this driver support following devices: + * Network controller: Cavium, Inc. Device b203 + * Network controller: Cavium, Inc. Device b403 + * Network controller: Cavium, Inc. Device b103 + * Network controller: Cavium, Inc. Device b903 + * Network controller: Cavium, Inc. Device ba03 + * Network controller: Cavium, Inc. Device bc03 + * Network controller: Cavium, Inc. Device bd03 diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig index 884d64114bff..837295fecd17 100644 --- a/drivers/net/ethernet/marvell/Kconfig +++ b/drivers/net/ethernet/marvell/Kconfig @@ -180,6 +180,7 @@ config SKY2_DEBUG source "drivers/net/ethernet/marvell/octeontx2/Kconfig" source "drivers/net/ethernet/marvell/octeon_ep/Kconfig" +source "drivers/net/ethernet/marvell/octeon_ep_vf/Kconfig" source "drivers/net/ethernet/marvell/prestera/Kconfig" endif # NET_VENDOR_MARVELL diff --git a/drivers/net/ethernet/marvell/Makefile b/drivers/net/ethernet/marvell/Makefile index ceba4aa4f026..a399defe25fd 100644 --- a/drivers/net/ethernet/marvell/Makefile +++ b/drivers/net/ethernet/marvell/Makefile @@ -12,5 +12,6 @@ obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SKY2) += sky2.o obj-y += octeon_ep/ +obj-y += octeon_ep_vf/ obj-y += octeontx2/ obj-y += prestera/ diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/Kconfig b/drivers/net/ethernet/marvell/octeon_ep_vf/Kconfig new file mode 100644 index 000000000000..dbd1267bda0c --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Marvell's Octeon PCI Endpoint NIC VF Driver Configuration +# + +config OCTEON_EP_VF + tristate "Marvell Octeon PCI Endpoint NIC VF Driver" + depends on 64BIT + depends on PCI + help + This driver supports networking functionality of Marvell's + Octeon PCI Endpoint NIC VF. + + To know the list of devices supported by this driver, refer + documentation in + . + + To compile this drivers as a module, choose M here. Name of the + module is octeon_ep_vf. diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/Makefile b/drivers/net/ethernet/marvell/octeon_ep_vf/Makefile new file mode 100644 index 000000000000..694eb9b46e99 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Network driver for Marvell's Octeon PCI Endpoint NIC VF +# + +obj-$(CONFIG_OCTEON_EP_VF) += octeon_ep_vf.o + +octeon_ep_vf-y := octep_vf_main.o octep_vf_cn9k.o octep_vf_cnxk.o \ + octep_vf_tx.o octep_vf_rx.o octep_vf_mbox.o diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c new file mode 100644 index 000000000000..c24ef2265205 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#include +#include +#include + +#include "octep_vf_config.h" +#include "octep_vf_main.h" +#include "octep_vf_regs_cn9k.h" + +/* Reset all hardware Tx/Rx queues */ +static void octep_vf_reset_io_queues_cn93(struct octep_vf_device *oct) +{ +} + +/* Initialize configuration limits and initial active config */ +static void octep_vf_init_config_cn93_vf(struct octep_vf_device *oct) +{ + struct octep_vf_config *conf = oct->conf; + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_CONTROL(0)); + conf->ring_cfg.max_io_rings = (reg_val >> CN93_VF_R_IN_CTL_RPVF_POS) & + CN93_VF_R_IN_CTL_RPVF_MASK; + conf->ring_cfg.active_io_rings = conf->ring_cfg.max_io_rings; + + conf->iq.num_descs = OCTEP_VF_IQ_MAX_DESCRIPTORS; + conf->iq.instr_type = OCTEP_VF_64BYTE_INSTR; + conf->iq.db_min = OCTEP_VF_DB_MIN; + conf->iq.intr_threshold = OCTEP_VF_IQ_INTR_THRESHOLD; + + conf->oq.num_descs = OCTEP_VF_OQ_MAX_DESCRIPTORS; + conf->oq.buf_size = OCTEP_VF_OQ_BUF_SIZE; + conf->oq.refill_threshold = OCTEP_VF_OQ_REFILL_THRESHOLD; + conf->oq.oq_intr_pkt = OCTEP_VF_OQ_INTR_PKT_THRESHOLD; + conf->oq.oq_intr_time = OCTEP_VF_OQ_INTR_TIME_THRESHOLD; + + conf->msix_cfg.ioq_msix = conf->ring_cfg.active_io_rings; +} + +/* Setup registers for a hardware Tx Queue */ +static void octep_vf_setup_iq_regs_cn93(struct octep_vf_device *oct, int iq_no) +{ +} + +/* Setup registers for a hardware Rx Queue */ +static void octep_vf_setup_oq_regs_cn93(struct octep_vf_device *oct, int oq_no) +{ +} + +/* Setup registers for a VF mailbox */ +static void octep_vf_setup_mbox_regs_cn93(struct octep_vf_device *oct, int q_no) +{ +} + +/* Tx/Rx queue interrupt handler */ +static irqreturn_t octep_vf_ioq_intr_handler_cn93(void *data) +{ + return IRQ_HANDLED; +} + +/* Re-initialize Octeon hardware registers */ +static void octep_vf_reinit_regs_cn93(struct octep_vf_device *oct) +{ +} + +/* Enable all interrupts */ +static void octep_vf_enable_interrupts_cn93(struct octep_vf_device *oct) +{ +} + +/* Disable all interrupts */ +static void octep_vf_disable_interrupts_cn93(struct octep_vf_device *oct) +{ +} + +/* Get new Octeon Read Index: index of descriptor that Octeon reads next. */ +static u32 octep_vf_update_iq_read_index_cn93(struct octep_vf_iq *iq) +{ + return 0; +} + +/* Enable a hardware Tx Queue */ +static void octep_vf_enable_iq_cn93(struct octep_vf_device *oct, int iq_no) +{ +} + +/* Enable a hardware Rx Queue */ +static void octep_vf_enable_oq_cn93(struct octep_vf_device *oct, int oq_no) +{ +} + +/* Enable all hardware Tx/Rx Queues assigned to VF */ +static void octep_vf_enable_io_queues_cn93(struct octep_vf_device *oct) +{ +} + +/* Disable a hardware Tx Queue assigned to VF */ +static void octep_vf_disable_iq_cn93(struct octep_vf_device *oct, int iq_no) +{ +} + +/* Disable a hardware Rx Queue assigned to VF */ +static void octep_vf_disable_oq_cn93(struct octep_vf_device *oct, int oq_no) +{ +} + +/* Disable all hardware Tx/Rx Queues assigned to VF */ +static void octep_vf_disable_io_queues_cn93(struct octep_vf_device *oct) +{ +} + +/* Dump hardware registers (including Tx/Rx queues) for debugging. */ +static void octep_vf_dump_registers_cn93(struct octep_vf_device *oct) +{ +} + +/** + * octep_vf_device_setup_cn93() - Setup Octeon device. + * + * @oct: Octeon device private data structure. + * + * - initialize hardware operations. + * - get target side pcie port number for the device. + * - set initial configuration and max limits. + */ +void octep_vf_device_setup_cn93(struct octep_vf_device *oct) +{ + oct->hw_ops.setup_iq_regs = octep_vf_setup_iq_regs_cn93; + oct->hw_ops.setup_oq_regs = octep_vf_setup_oq_regs_cn93; + oct->hw_ops.setup_mbox_regs = octep_vf_setup_mbox_regs_cn93; + + oct->hw_ops.ioq_intr_handler = octep_vf_ioq_intr_handler_cn93; + oct->hw_ops.reinit_regs = octep_vf_reinit_regs_cn93; + + oct->hw_ops.enable_interrupts = octep_vf_enable_interrupts_cn93; + oct->hw_ops.disable_interrupts = octep_vf_disable_interrupts_cn93; + + oct->hw_ops.update_iq_read_idx = octep_vf_update_iq_read_index_cn93; + + oct->hw_ops.enable_iq = octep_vf_enable_iq_cn93; + oct->hw_ops.enable_oq = octep_vf_enable_oq_cn93; + oct->hw_ops.enable_io_queues = octep_vf_enable_io_queues_cn93; + + oct->hw_ops.disable_iq = octep_vf_disable_iq_cn93; + oct->hw_ops.disable_oq = octep_vf_disable_oq_cn93; + oct->hw_ops.disable_io_queues = octep_vf_disable_io_queues_cn93; + oct->hw_ops.reset_io_queues = octep_vf_reset_io_queues_cn93; + + oct->hw_ops.dump_registers = octep_vf_dump_registers_cn93; + octep_vf_init_config_cn93_vf(oct); +} diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cnxk.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cnxk.c new file mode 100644 index 000000000000..af07a4a6edc5 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cnxk.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#include +#include +#include + +#include "octep_vf_config.h" +#include "octep_vf_main.h" +#include "octep_vf_regs_cnxk.h" + +/* Reset all hardware Tx/Rx queues */ +static void octep_vf_reset_io_queues_cnxk(struct octep_vf_device *oct) +{ +} + +/* Initialize configuration limits and initial active config */ +static void octep_vf_init_config_cnxk_vf(struct octep_vf_device *oct) +{ + struct octep_vf_config *conf = oct->conf; + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_CONTROL(0)); + conf->ring_cfg.max_io_rings = (reg_val >> CNXK_VF_R_IN_CTL_RPVF_POS) & + CNXK_VF_R_IN_CTL_RPVF_MASK; + conf->ring_cfg.active_io_rings = conf->ring_cfg.max_io_rings; + + conf->iq.num_descs = OCTEP_VF_IQ_MAX_DESCRIPTORS; + conf->iq.instr_type = OCTEP_VF_64BYTE_INSTR; + conf->iq.db_min = OCTEP_VF_DB_MIN; + conf->iq.intr_threshold = OCTEP_VF_IQ_INTR_THRESHOLD; + + conf->oq.num_descs = OCTEP_VF_OQ_MAX_DESCRIPTORS; + conf->oq.buf_size = OCTEP_VF_OQ_BUF_SIZE; + conf->oq.refill_threshold = OCTEP_VF_OQ_REFILL_THRESHOLD; + conf->oq.oq_intr_pkt = OCTEP_VF_OQ_INTR_PKT_THRESHOLD; + conf->oq.oq_intr_time = OCTEP_VF_OQ_INTR_TIME_THRESHOLD; + conf->oq.wmark = OCTEP_VF_OQ_WMARK_MIN; + + conf->msix_cfg.ioq_msix = conf->ring_cfg.active_io_rings; +} + +/* Setup registers for a hardware Tx Queue */ +static void octep_vf_setup_iq_regs_cnxk(struct octep_vf_device *oct, int iq_no) +{ +} + +/* Setup registers for a hardware Rx Queue */ +static void octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no) +{ +} + +/* Setup registers for a VF mailbox */ +static void octep_vf_setup_mbox_regs_cnxk(struct octep_vf_device *oct, int q_no) +{ +} + +/* Tx/Rx queue interrupt handler */ +static irqreturn_t octep_vf_ioq_intr_handler_cnxk(void *data) +{ + return IRQ_HANDLED; +} + +/* Re-initialize Octeon hardware registers */ +static void octep_vf_reinit_regs_cnxk(struct octep_vf_device *oct) +{ +} + +/* Enable all interrupts */ +static void octep_vf_enable_interrupts_cnxk(struct octep_vf_device *oct) +{ +} + +/* Disable all interrupts */ +static void octep_vf_disable_interrupts_cnxk(struct octep_vf_device *oct) +{ +} + +/* Get new Octeon Read Index: index of descriptor that Octeon reads next. */ +static u32 octep_vf_update_iq_read_index_cnxk(struct octep_vf_iq *iq) +{ + return 0; +} + +/* Enable a hardware Tx Queue */ +static void octep_vf_enable_iq_cnxk(struct octep_vf_device *oct, int iq_no) +{ +} + +/* Enable a hardware Rx Queue */ +static void octep_vf_enable_oq_cnxk(struct octep_vf_device *oct, int oq_no) +{ +} + +/* Enable all hardware Tx/Rx Queues assigned to VF */ +static void octep_vf_enable_io_queues_cnxk(struct octep_vf_device *oct) +{ +} + +/* Disable a hardware Tx Queue assigned to VF */ +static void octep_vf_disable_iq_cnxk(struct octep_vf_device *oct, int iq_no) +{ +} + +/* Disable a hardware Rx Queue assigned to VF */ +static void octep_vf_disable_oq_cnxk(struct octep_vf_device *oct, int oq_no) +{ +} + +/* Disable all hardware Tx/Rx Queues assigned to VF */ +static void octep_vf_disable_io_queues_cnxk(struct octep_vf_device *oct) +{ +} + +/* Dump hardware registers (including Tx/Rx queues) for debugging. */ +static void octep_vf_dump_registers_cnxk(struct octep_vf_device *oct) +{ +} + +/** + * octep_vf_device_setup_cnxk() - Setup Octeon device. + * + * @oct: Octeon device private data structure. + * + * - initialize hardware operations. + * - get target side pcie port number for the device. + * - set initial configuration and max limits. + */ +void octep_vf_device_setup_cnxk(struct octep_vf_device *oct) +{ + oct->hw_ops.setup_iq_regs = octep_vf_setup_iq_regs_cnxk; + oct->hw_ops.setup_oq_regs = octep_vf_setup_oq_regs_cnxk; + oct->hw_ops.setup_mbox_regs = octep_vf_setup_mbox_regs_cnxk; + + oct->hw_ops.ioq_intr_handler = octep_vf_ioq_intr_handler_cnxk; + oct->hw_ops.reinit_regs = octep_vf_reinit_regs_cnxk; + + oct->hw_ops.enable_interrupts = octep_vf_enable_interrupts_cnxk; + oct->hw_ops.disable_interrupts = octep_vf_disable_interrupts_cnxk; + + oct->hw_ops.update_iq_read_idx = octep_vf_update_iq_read_index_cnxk; + + oct->hw_ops.enable_iq = octep_vf_enable_iq_cnxk; + oct->hw_ops.enable_oq = octep_vf_enable_oq_cnxk; + oct->hw_ops.enable_io_queues = octep_vf_enable_io_queues_cnxk; + + oct->hw_ops.disable_iq = octep_vf_disable_iq_cnxk; + oct->hw_ops.disable_oq = octep_vf_disable_oq_cnxk; + oct->hw_ops.disable_io_queues = octep_vf_disable_io_queues_cnxk; + oct->hw_ops.reset_io_queues = octep_vf_reset_io_queues_cnxk; + + oct->hw_ops.dump_registers = octep_vf_dump_registers_cnxk; + octep_vf_init_config_cnxk_vf(oct); +} diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_config.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_config.h new file mode 100644 index 000000000000..e03a647b0110 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_config.h @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#ifndef _OCTEP_VF_CONFIG_H_ +#define _OCTEP_VF_CONFIG_H_ + +/* Tx instruction types by length */ +#define OCTEP_VF_32BYTE_INSTR 32 +#define OCTEP_VF_64BYTE_INSTR 64 + +/* Tx Queue: maximum descriptors per ring */ +#define OCTEP_VF_IQ_MAX_DESCRIPTORS 1024 +/* Minimum input (Tx) requests to be enqueued to ring doorbell */ +#define OCTEP_VF_DB_MIN 8 +/* Packet threshold for Tx queue interrupt */ +#define OCTEP_VF_IQ_INTR_THRESHOLD 0x0 + +/* Minimum watermark for backpressure */ +#define OCTEP_VF_OQ_WMARK_MIN 256 + +/* Rx Queue: maximum descriptors per ring */ +#define OCTEP_VF_OQ_MAX_DESCRIPTORS 1024 + +/* Rx buffer size: Use page size buffers. + * Build skb from allocated page buffer once the packet is received. + * When a gathered packet is received, make head page as skb head and + * page buffers in consecutive Rx descriptors as fragments. + */ +#define OCTEP_VF_OQ_BUF_SIZE (SKB_WITH_OVERHEAD(PAGE_SIZE)) +#define OCTEP_VF_OQ_PKTS_PER_INTR 128 +#define OCTEP_VF_OQ_REFILL_THRESHOLD (OCTEP_VF_OQ_MAX_DESCRIPTORS / 4) + +#define OCTEP_VF_OQ_INTR_PKT_THRESHOLD 1 +#define OCTEP_VF_OQ_INTR_TIME_THRESHOLD 10 + +#define OCTEP_VF_MSIX_NAME_SIZE (IFNAMSIZ + 32) + +/* Tx Queue wake threshold + * wakeup a stopped Tx queue if minimum 2 descriptors are available. + * Even a skb with fragments consume only one Tx queue descriptor entry. + */ +#define OCTEP_VF_WAKE_QUEUE_THRESHOLD 2 + +/* Minimum MTU supported by Octeon network interface */ +#define OCTEP_VF_MIN_MTU ETH_MIN_MTU +/* Maximum MTU supported by Octeon interface*/ +#define OCTEP_VF_MAX_MTU (10000 - (ETH_HLEN + ETH_FCS_LEN)) +/* Default MTU */ +#define OCTEP_VF_DEFAULT_MTU 1500 + +/* Macros to get octeon config params */ +#define CFG_GET_IQ_CFG(cfg) ((cfg)->iq) +#define CFG_GET_IQ_NUM_DESC(cfg) ((cfg)->iq.num_descs) +#define CFG_GET_IQ_INSTR_TYPE(cfg) ((cfg)->iq.instr_type) +#define CFG_GET_IQ_INSTR_SIZE(cfg) (64) +#define CFG_GET_IQ_DB_MIN(cfg) ((cfg)->iq.db_min) +#define CFG_GET_IQ_INTR_THRESHOLD(cfg) ((cfg)->iq.intr_threshold) + +#define CFG_GET_OQ_NUM_DESC(cfg) ((cfg)->oq.num_descs) +#define CFG_GET_OQ_BUF_SIZE(cfg) ((cfg)->oq.buf_size) +#define CFG_GET_OQ_REFILL_THRESHOLD(cfg) ((cfg)->oq.refill_threshold) +#define CFG_GET_OQ_INTR_PKT(cfg) ((cfg)->oq.oq_intr_pkt) +#define CFG_GET_OQ_INTR_TIME(cfg) ((cfg)->oq.oq_intr_time) +#define CFG_GET_OQ_WMARK(cfg) ((cfg)->oq.wmark) + +#define CFG_GET_PORTS_ACTIVE_IO_RINGS(cfg) ((cfg)->ring_cfg.active_io_rings) +#define CFG_GET_PORTS_MAX_IO_RINGS(cfg) ((cfg)->ring_cfg.max_io_rings) + +#define CFG_GET_CORE_TICS_PER_US(cfg) ((cfg)->core_cfg.core_tics_per_us) +#define CFG_GET_COPROC_TICS_PER_US(cfg) ((cfg)->core_cfg.coproc_tics_per_us) + +#define CFG_GET_IOQ_MSIX(cfg) ((cfg)->msix_cfg.ioq_msix) + +/* Hardware Tx Queue configuration. */ +struct octep_vf_iq_config { + /* Size of the Input queue (number of commands) */ + u16 num_descs; + + /* Command size - 32 or 64 bytes */ + u16 instr_type; + + /* Minimum number of commands pending to be posted to Octeon before driver + * hits the Input queue doorbell. + */ + u16 db_min; + + /* Trigger the IQ interrupt when processed cmd count reaches + * this level. + */ + u32 intr_threshold; +}; + +/* Hardware Rx Queue configuration. */ +struct octep_vf_oq_config { + /* Size of Output queue (number of descriptors) */ + u16 num_descs; + + /* Size of buffer in this Output queue. */ + u16 buf_size; + + /* The number of buffers that were consumed during packet processing + * by the driver on this Output queue before the driver attempts to + * replenish the descriptor ring with new buffers. + */ + u16 refill_threshold; + + /* Interrupt Coalescing (Packet Count). Octeon will interrupt the host + * only if it sent as many packets as specified by this field. + * The driver usually does not use packet count interrupt coalescing. + */ + u32 oq_intr_pkt; + + /* Interrupt Coalescing (Time Interval). Octeon will interrupt the host + * if at least one packet was sent in the time interval specified by + * this field. The driver uses time interval interrupt coalescing by + * default. The time is specified in microseconds. + */ + u32 oq_intr_time; + + /* Water mark for backpressure. + * Output queue sends backpressure signal to source when + * free buffer count falls below wmark. + */ + u32 wmark; +}; + +/* Tx/Rx configuration */ +struct octep_vf_ring_config { + /* Max number of IOQs */ + u16 max_io_rings; + + /* Number of active IOQs */ + u16 active_io_rings; +}; + +/* Octeon MSI-x config. */ +struct octep_vf_msix_config { + /* Number of IOQ interrupts */ + u16 ioq_msix; +}; + +/* Data Structure to hold configuration limits and active config */ +struct octep_vf_config { + /* Input Queue attributes. */ + struct octep_vf_iq_config iq; + + /* Output Queue attributes. */ + struct octep_vf_oq_config oq; + + /* MSI-X interrupt config */ + struct octep_vf_msix_config msix_cfg; + + /* NIC VF ring Configuration */ + struct octep_vf_ring_config ring_cfg; +}; +#endif /* _OCTEP_VF_CONFIG_H_ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c new file mode 100644 index 000000000000..50a2a13c5f2e --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c @@ -0,0 +1,528 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "octep_vf_config.h" +#include "octep_vf_main.h" + +struct workqueue_struct *octep_vf_wq; + +/* Supported Devices */ +static const struct pci_device_id octep_vf_pci_id_tbl[] = { + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CN93_VF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CNF95N_VF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CN98_VF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CN10KA_VF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CNF10KA_VF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CNF10KB_VF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CN10KB_VF)}, + {0, }, +}; +MODULE_DEVICE_TABLE(pci, octep_vf_pci_id_tbl); + +MODULE_AUTHOR("Veerasenareddy Burru "); +MODULE_DESCRIPTION(OCTEP_VF_DRV_STRING); +MODULE_LICENSE("GPL"); + +static void octep_vf_link_up(struct net_device *netdev) +{ + netif_carrier_on(netdev); + netif_tx_start_all_queues(netdev); +} + +static void octep_vf_set_rx_state(struct octep_vf_device *oct, bool up) +{ + int err; + + err = octep_vf_mbox_set_rx_state(oct, up); + if (err) + netdev_err(oct->netdev, "Set Rx state to %d failed with err:%d\n", up, err); +} + +static int octep_vf_get_link_status(struct octep_vf_device *oct) +{ + int err; + + err = octep_vf_mbox_get_link_status(oct, &oct->link_info.oper_up); + if (err) + netdev_err(oct->netdev, "Get link status failed with err:%d\n", err); + return oct->link_info.oper_up; +} + +static void octep_vf_set_link_status(struct octep_vf_device *oct, bool up) +{ + int err; + + err = octep_vf_mbox_set_link_status(oct, up); + if (err) { + netdev_err(oct->netdev, "Set link status to %d failed with err:%d\n", up, err); + return; + } + oct->link_info.oper_up = up; +} + +/** + * octep_vf_open() - start the octeon network device. + * + * @netdev: pointer to kernel network device. + * + * setup Tx/Rx queues, interrupts and enable hardware operation of Tx/Rx queues + * and interrupts.. + * + * Return: 0, on successfully setting up device and bring it up. + * -1, on any error. + */ +static int octep_vf_open(struct net_device *netdev) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + int err, ret; + + netdev_info(netdev, "Starting netdev ...\n"); + netif_carrier_off(netdev); + + oct->hw_ops.reset_io_queues(oct); + + if (octep_vf_setup_iqs(oct)) + goto setup_iq_err; + if (octep_vf_setup_oqs(oct)) + goto setup_oq_err; + + err = netif_set_real_num_tx_queues(netdev, oct->num_oqs); + if (err) + goto set_queues_err; + err = netif_set_real_num_rx_queues(netdev, oct->num_iqs); + if (err) + goto set_queues_err; + + oct->link_info.admin_up = 1; + octep_vf_set_rx_state(oct, true); + + ret = octep_vf_get_link_status(oct); + if (!ret) + octep_vf_set_link_status(oct, true); + + /* Enable the input and output queues for this Octeon device */ + oct->hw_ops.enable_io_queues(oct); + + /* Enable Octeon device interrupts */ + oct->hw_ops.enable_interrupts(oct); + + octep_vf_oq_dbell_init(oct); + + ret = octep_vf_get_link_status(oct); + if (ret) + octep_vf_link_up(netdev); + + return 0; + +set_queues_err: + octep_vf_free_oqs(oct); +setup_oq_err: + octep_vf_free_iqs(oct); +setup_iq_err: + return -1; +} + +/** + * octep_vf_stop() - stop the octeon network device. + * + * @netdev: pointer to kernel network device. + * + * stop the device Tx/Rx operations, bring down the link and + * free up all resources allocated for Tx/Rx queues and interrupts. + */ +static int octep_vf_stop(struct net_device *netdev) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + + netdev_info(netdev, "Stopping the device ...\n"); + + /* Stop Tx from stack */ + netif_tx_stop_all_queues(netdev); + netif_carrier_off(netdev); + netif_tx_disable(netdev); + + octep_vf_set_link_status(oct, false); + octep_vf_set_rx_state(oct, false); + + oct->link_info.admin_up = 0; + oct->link_info.oper_up = 0; + + oct->hw_ops.disable_interrupts(oct); + + octep_vf_clean_iqs(oct); + + oct->hw_ops.disable_io_queues(oct); + oct->hw_ops.reset_io_queues(oct); + octep_vf_free_oqs(oct); + octep_vf_free_iqs(oct); + netdev_info(netdev, "Device stopped !!\n"); + return 0; +} + +/** + * octep_vf_start_xmit() - Enqueue packet to Octoen hardware Tx Queue. + * + * @skb: packet skbuff pointer. + * @netdev: kernel network device. + * + * Return: NETDEV_TX_BUSY, if Tx Queue is full. + * NETDEV_TX_OK, if successfully enqueued to hardware Tx queue. + */ +static netdev_tx_t octep_vf_start_xmit(struct sk_buff *skb, + struct net_device *netdev) +{ + return NETDEV_TX_OK; +} + +/** + * octep_vf_tx_timeout_task - work queue task to Handle Tx queue timeout. + * + * @work: pointer to Tx queue timeout work_struct + * + * Stop and start the device so that it frees up all queue resources + * and restarts the queues, that potentially clears a Tx queue timeout + * condition. + **/ +static void octep_vf_tx_timeout_task(struct work_struct *work) +{ + struct octep_vf_device *oct = container_of(work, struct octep_vf_device, + tx_timeout_task); + struct net_device *netdev = oct->netdev; + + rtnl_lock(); + if (netif_running(netdev)) { + octep_vf_stop(netdev); + octep_vf_open(netdev); + } + rtnl_unlock(); +} + +/** + * octep_vf_tx_timeout() - Handle Tx Queue timeout. + * + * @netdev: pointer to kernel network device. + * @txqueue: Timed out Tx queue number. + * + * Schedule a work to handle Tx queue timeout. + */ +static void octep_vf_tx_timeout(struct net_device *netdev, unsigned int txqueue) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + + queue_work(octep_vf_wq, &oct->tx_timeout_task); +} + +static const struct net_device_ops octep_vf_netdev_ops = { + .ndo_open = octep_vf_open, + .ndo_stop = octep_vf_stop, + .ndo_start_xmit = octep_vf_start_xmit, + .ndo_tx_timeout = octep_vf_tx_timeout, +}; + +static const char *octep_vf_devid_to_str(struct octep_vf_device *oct) +{ + switch (oct->chip_id) { + case OCTEP_PCI_DEVICE_ID_CN93_VF: + return "CN93XX"; + case OCTEP_PCI_DEVICE_ID_CNF95N_VF: + return "CNF95N"; + case OCTEP_PCI_DEVICE_ID_CN10KA_VF: + return "CN10KA"; + case OCTEP_PCI_DEVICE_ID_CNF10KA_VF: + return "CNF10KA"; + case OCTEP_PCI_DEVICE_ID_CNF10KB_VF: + return "CNF10KB"; + case OCTEP_PCI_DEVICE_ID_CN10KB_VF: + return "CN10KB"; + default: + return "Unsupported"; + } +} + +/** + * octep_vf_device_setup() - Setup Octeon Device. + * + * @oct: Octeon device private data structure. + * + * Setup Octeon device hardware operations, configuration, etc ... + */ +int octep_vf_device_setup(struct octep_vf_device *oct) +{ + struct pci_dev *pdev = oct->pdev; + + /* allocate memory for oct->conf */ + oct->conf = kzalloc(sizeof(*oct->conf), GFP_KERNEL); + if (!oct->conf) + return -ENOMEM; + + /* Map BAR region 0 */ + oct->mmio.hw_addr = ioremap(pci_resource_start(oct->pdev, 0), + pci_resource_len(oct->pdev, 0)); + if (!oct->mmio.hw_addr) { + dev_err(&pdev->dev, + "Failed to remap BAR0; start=0x%llx len=0x%llx\n", + pci_resource_start(oct->pdev, 0), + pci_resource_len(oct->pdev, 0)); + goto ioremap_err; + } + oct->mmio.mapped = 1; + + oct->chip_id = pdev->device; + oct->rev_id = pdev->revision; + dev_info(&pdev->dev, "chip_id = 0x%x\n", pdev->device); + + switch (oct->chip_id) { + case OCTEP_PCI_DEVICE_ID_CN93_VF: + case OCTEP_PCI_DEVICE_ID_CNF95N_VF: + case OCTEP_PCI_DEVICE_ID_CN98_VF: + dev_info(&pdev->dev, "Setting up OCTEON %s VF PASS%d.%d\n", + octep_vf_devid_to_str(oct), OCTEP_VF_MAJOR_REV(oct), + OCTEP_VF_MINOR_REV(oct)); + octep_vf_device_setup_cn93(oct); + break; + case OCTEP_PCI_DEVICE_ID_CNF10KA_VF: + case OCTEP_PCI_DEVICE_ID_CN10KA_VF: + case OCTEP_PCI_DEVICE_ID_CNF10KB_VF: + case OCTEP_PCI_DEVICE_ID_CN10KB_VF: + dev_info(&pdev->dev, "Setting up OCTEON %s VF PASS%d.%d\n", + octep_vf_devid_to_str(oct), OCTEP_VF_MAJOR_REV(oct), + OCTEP_VF_MINOR_REV(oct)); + octep_vf_device_setup_cnxk(oct); + break; + default: + dev_err(&pdev->dev, "Unsupported device\n"); + goto unsupported_dev; + } + + return 0; + +unsupported_dev: + iounmap(oct->mmio.hw_addr); +ioremap_err: + kfree(oct->conf); + return -EOPNOTSUPP; +} + +/** + * octep_vf_device_cleanup() - Cleanup Octeon Device. + * + * @oct: Octeon device private data structure. + * + * Cleanup Octeon device allocated resources. + */ +static void octep_vf_device_cleanup(struct octep_vf_device *oct) +{ + dev_info(&oct->pdev->dev, "Cleaning up Octeon Device ...\n"); + + if (oct->mmio.mapped) + iounmap(oct->mmio.hw_addr); + + kfree(oct->conf); + oct->conf = NULL; +} + +static int octep_vf_get_mac_addr(struct octep_vf_device *oct, u8 *addr) +{ + return octep_vf_mbox_get_mac_addr(oct, addr); +} + +/** + * octep_vf_probe() - Octeon PCI device probe handler. + * + * @pdev: PCI device structure. + * @ent: entry in Octeon PCI device ID table. + * + * Initializes and enables the Octeon PCI device for network operations. + * Initializes Octeon private data structure and registers a network device. + */ +static int octep_vf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct octep_vf_device *octep_vf_dev; + struct net_device *netdev; + int err; + + err = pci_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, "Failed to enable PCI device\n"); + return err; + } + + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (err) { + dev_err(&pdev->dev, "Failed to set DMA mask !!\n"); + goto err_dma_mask; + } + + err = pci_request_mem_regions(pdev, OCTEP_VF_DRV_NAME); + if (err) { + dev_err(&pdev->dev, "Failed to map PCI memory regions\n"); + goto err_pci_regions; + } + + pci_set_master(pdev); + + netdev = alloc_etherdev_mq(sizeof(struct octep_vf_device), + OCTEP_VF_MAX_QUEUES); + if (!netdev) { + dev_err(&pdev->dev, "Failed to allocate netdev\n"); + err = -ENOMEM; + goto err_alloc_netdev; + } + SET_NETDEV_DEV(netdev, &pdev->dev); + + octep_vf_dev = netdev_priv(netdev); + octep_vf_dev->netdev = netdev; + octep_vf_dev->pdev = pdev; + octep_vf_dev->dev = &pdev->dev; + pci_set_drvdata(pdev, octep_vf_dev); + + err = octep_vf_device_setup(octep_vf_dev); + if (err) { + dev_err(&pdev->dev, "Device setup failed\n"); + goto err_octep_vf_config; + } + INIT_WORK(&octep_vf_dev->tx_timeout_task, octep_vf_tx_timeout_task); + + netdev->netdev_ops = &octep_vf_netdev_ops; + netif_carrier_off(netdev); + + if (octep_vf_setup_mbox(octep_vf_dev)) { + dev_err(&pdev->dev, "VF Mailbox setup failed\n"); + err = -ENOMEM; + goto err_setup_mbox; + } + + if (octep_vf_mbox_version_check(octep_vf_dev)) { + dev_err(&pdev->dev, "PF VF Mailbox version mismatch\n"); + err = -EINVAL; + goto err_mbox_version; + } + + netdev->hw_features = NETIF_F_SG; + netdev->min_mtu = OCTEP_VF_MIN_MTU; + netdev->max_mtu = OCTEP_VF_MAX_MTU; + netdev->mtu = OCTEP_VF_DEFAULT_MTU; + + netdev->features |= netdev->hw_features; + octep_vf_get_mac_addr(octep_vf_dev, octep_vf_dev->mac_addr); + eth_hw_addr_set(netdev, octep_vf_dev->mac_addr); + err = register_netdev(netdev); + if (err) { + dev_err(&pdev->dev, "Failed to register netdev\n"); + goto err_register_dev; + } + dev_info(&pdev->dev, "Device probe successful\n"); + return 0; + +err_register_dev: +err_mbox_version: + octep_vf_delete_mbox(octep_vf_dev); +err_setup_mbox: + octep_vf_device_cleanup(octep_vf_dev); +err_octep_vf_config: + free_netdev(netdev); +err_alloc_netdev: + pci_release_mem_regions(pdev); +err_pci_regions: +err_dma_mask: + pci_disable_device(pdev); + dev_err(&pdev->dev, "Device probe failed\n"); + return err; +} + +/** + * octep_vf_remove() - Remove Octeon PCI device from driver control. + * + * @pdev: PCI device structure of the Octeon device. + * + * Cleanup all resources allocated for the Octeon device. + * Unregister from network device and disable the PCI device. + */ +static void octep_vf_remove(struct pci_dev *pdev) +{ + struct octep_vf_device *oct = pci_get_drvdata(pdev); + struct net_device *netdev; + + if (!oct) + return; + + octep_vf_mbox_dev_remove(oct); + cancel_work_sync(&oct->tx_timeout_task); + netdev = oct->netdev; + if (netdev->reg_state == NETREG_REGISTERED) + unregister_netdev(netdev); + octep_vf_delete_mbox(oct); + octep_vf_device_cleanup(oct); + pci_release_mem_regions(pdev); + free_netdev(netdev); + pci_disable_device(pdev); +} + +static struct pci_driver octep_vf_driver = { + .name = OCTEP_VF_DRV_NAME, + .id_table = octep_vf_pci_id_tbl, + .probe = octep_vf_probe, + .remove = octep_vf_remove, +}; + +/** + * octep_vf_init_module() - Module initialization. + * + * create common resource for the driver and register PCI driver. + */ +static int __init octep_vf_init_module(void) +{ + int ret; + + pr_info("%s: Loading %s ...\n", OCTEP_VF_DRV_NAME, OCTEP_VF_DRV_STRING); + + /* work queue for all deferred tasks */ + octep_vf_wq = create_singlethread_workqueue(OCTEP_VF_DRV_NAME); + if (!octep_vf_wq) { + pr_err("%s: Failed to create common workqueue\n", + OCTEP_VF_DRV_NAME); + return -ENOMEM; + } + + ret = pci_register_driver(&octep_vf_driver); + if (ret < 0) { + pr_err("%s: Failed to register PCI driver; err=%d\n", + OCTEP_VF_DRV_NAME, ret); + return ret; + } + + pr_info("%s: Loaded successfully !\n", OCTEP_VF_DRV_NAME); + + return ret; +} + +/** + * octep_vf_exit_module() - Module exit routine. + * + * unregister the driver with PCI subsystem and cleanup common resources. + */ +static void __exit octep_vf_exit_module(void) +{ + pr_info("%s: Unloading ...\n", OCTEP_VF_DRV_NAME); + + pci_unregister_driver(&octep_vf_driver); + destroy_workqueue(octep_vf_wq); + + pr_info("%s: Unloading complete\n", OCTEP_VF_DRV_NAME); +} + +module_init(octep_vf_init_module); +module_exit(octep_vf_exit_module); diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h new file mode 100644 index 000000000000..e22e393c6ee2 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h @@ -0,0 +1,332 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#ifndef _OCTEP_VF_MAIN_H_ +#define _OCTEP_VF_MAIN_H_ + +#include "octep_vf_tx.h" +#include "octep_vf_rx.h" +#include "octep_vf_mbox.h" + +#define OCTEP_VF_DRV_NAME "octeon_ep_vf" +#define OCTEP_VF_DRV_STRING "Marvell Octeon EndPoint NIC VF Driver" + +#define OCTEP_PCI_DEVICE_ID_CN93_VF 0xB203 //93xx VF +#define OCTEP_PCI_DEVICE_ID_CNF95N_VF 0xB403 //95N VF +#define OCTEP_PCI_DEVICE_ID_CN98_VF 0xB103 +#define OCTEP_PCI_DEVICE_ID_CN10KA_VF 0xB903 +#define OCTEP_PCI_DEVICE_ID_CNF10KA_VF 0xBA03 +#define OCTEP_PCI_DEVICE_ID_CNF10KB_VF 0xBC03 +#define OCTEP_PCI_DEVICE_ID_CN10KB_VF 0xBD03 + +#define OCTEP_VF_MAX_QUEUES 63 +#define OCTEP_VF_MAX_IQ OCTEP_VF_MAX_QUEUES +#define OCTEP_VF_MAX_OQ OCTEP_VF_MAX_QUEUES + +#define OCTEP_VF_MAX_MSIX_VECTORS OCTEP_VF_MAX_OQ + +#define OCTEP_VF_IQ_INTR_RESEND_BIT 59 +#define OCTEP_VF_OQ_INTR_RESEND_BIT 59 + +#define IQ_INSTR_PENDING(iq) ({ typeof(iq) iq__ = (iq); \ + ((iq__)->host_write_index - (iq__)->flush_index) & \ + (iq__)->ring_size_mask; \ + }) +#define IQ_INSTR_SPACE(iq) ({ typeof(iq) iq_ = (iq); \ + (iq_)->max_count - IQ_INSTR_PENDING(iq_); \ + }) + +/* PCI address space mapping information. + * Each of the 3 address spaces given by BAR0, BAR2 and BAR4 of + * Octeon gets mapped to different physical address spaces in + * the kernel. + */ +struct octep_vf_mmio { + /* The physical address to which the PCI address space is mapped. */ + u8 __iomem *hw_addr; + + /* Flag indicating the mapping was successful. */ + int mapped; +}; + +struct octep_vf_hw_ops { + void (*setup_iq_regs)(struct octep_vf_device *oct, int q); + void (*setup_oq_regs)(struct octep_vf_device *oct, int q); + void (*setup_mbox_regs)(struct octep_vf_device *oct, int mbox); + + irqreturn_t (*non_ioq_intr_handler)(void *ioq_vector); + irqreturn_t (*ioq_intr_handler)(void *ioq_vector); + void (*reinit_regs)(struct octep_vf_device *oct); + u32 (*update_iq_read_idx)(struct octep_vf_iq *iq); + + void (*enable_interrupts)(struct octep_vf_device *oct); + void (*disable_interrupts)(struct octep_vf_device *oct); + + void (*enable_io_queues)(struct octep_vf_device *oct); + void (*disable_io_queues)(struct octep_vf_device *oct); + void (*enable_iq)(struct octep_vf_device *oct, int q); + void (*disable_iq)(struct octep_vf_device *oct, int q); + void (*enable_oq)(struct octep_vf_device *oct, int q); + void (*disable_oq)(struct octep_vf_device *oct, int q); + void (*reset_io_queues)(struct octep_vf_device *oct); + void (*dump_registers)(struct octep_vf_device *oct); +}; + +/* Octeon mailbox data */ +struct octep_vf_mbox_data { + /* Holds the offset of received data via mailbox. */ + u32 data_index; + + /* Holds the received data via mailbox. */ + u8 recv_data[OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE]; +}; + +/* wrappers around work structs */ +struct octep_vf_mbox_wk { + struct work_struct work; + void *ctxptr; +}; + +/* Octeon device mailbox */ +struct octep_vf_mbox { + /* A mutex to protect access to this q_mbox. */ + struct mutex lock; + + u32 state; + + /* SLI_MAC_PF_MBOX_INT for PF, SLI_PKT_MBOX_INT for VF. */ + u8 __iomem *mbox_int_reg; + + /* SLI_PKT_PF_VF_MBOX_SIG(0) for PF, + * SLI_PKT_PF_VF_MBOX_SIG(1) for VF. + */ + u8 __iomem *mbox_write_reg; + + /* SLI_PKT_PF_VF_MBOX_SIG(1) for PF, + * SLI_PKT_PF_VF_MBOX_SIG(0) for VF. + */ + u8 __iomem *mbox_read_reg; + + /* Octeon mailbox data */ + struct octep_vf_mbox_data mbox_data; + + /* Octeon mailbox work handler to process Mbox messages */ + struct octep_vf_mbox_wk wk; +}; + +/* Tx/Rx queue vector per interrupt. */ +struct octep_vf_ioq_vector { + char name[OCTEP_VF_MSIX_NAME_SIZE]; + struct napi_struct napi; + struct octep_vf_device *octep_vf_dev; + struct octep_vf_iq *iq; + struct octep_vf_oq *oq; + cpumask_t affinity_mask; +}; + +/* Octeon hardware/firmware offload capability flags. */ +#define OCTEP_VF_CAP_TX_CHECKSUM BIT(0) +#define OCTEP_VF_CAP_RX_CHECKSUM BIT(1) +#define OCTEP_VF_CAP_TSO BIT(2) + +/* Link modes */ +enum octep_vf_link_mode_bit_indices { + OCTEP_VF_LINK_MODE_10GBASE_T = 0, + OCTEP_VF_LINK_MODE_10GBASE_R, + OCTEP_VF_LINK_MODE_10GBASE_CR, + OCTEP_VF_LINK_MODE_10GBASE_KR, + OCTEP_VF_LINK_MODE_10GBASE_LR, + OCTEP_VF_LINK_MODE_10GBASE_SR, + OCTEP_VF_LINK_MODE_25GBASE_CR, + OCTEP_VF_LINK_MODE_25GBASE_KR, + OCTEP_VF_LINK_MODE_25GBASE_SR, + OCTEP_VF_LINK_MODE_40GBASE_CR4, + OCTEP_VF_LINK_MODE_40GBASE_KR4, + OCTEP_VF_LINK_MODE_40GBASE_LR4, + OCTEP_VF_LINK_MODE_40GBASE_SR4, + OCTEP_VF_LINK_MODE_50GBASE_CR2, + OCTEP_VF_LINK_MODE_50GBASE_KR2, + OCTEP_VF_LINK_MODE_50GBASE_SR2, + OCTEP_VF_LINK_MODE_50GBASE_CR, + OCTEP_VF_LINK_MODE_50GBASE_KR, + OCTEP_VF_LINK_MODE_50GBASE_LR, + OCTEP_VF_LINK_MODE_50GBASE_SR, + OCTEP_VF_LINK_MODE_100GBASE_CR4, + OCTEP_VF_LINK_MODE_100GBASE_KR4, + OCTEP_VF_LINK_MODE_100GBASE_LR4, + OCTEP_VF_LINK_MODE_100GBASE_SR4, + OCTEP_VF_LINK_MODE_NBITS +}; + +/* Hardware interface link state information. */ +struct octep_vf_iface_link_info { + /* Bitmap of Supported link speeds/modes. */ + u64 supported_modes; + + /* Bitmap of Advertised link speeds/modes. */ + u64 advertised_modes; + + /* Negotiated link speed in Mbps. */ + u32 speed; + + /* MTU */ + u16 mtu; + + /* Autonegotiation state. */ +#define OCTEP_VF_LINK_MODE_AUTONEG_SUPPORTED BIT(0) +#define OCTEP_VF_LINK_MODE_AUTONEG_ADVERTISED BIT(1) + u8 autoneg; + + /* Pause frames setting. */ +#define OCTEP_VF_LINK_MODE_PAUSE_SUPPORTED BIT(0) +#define OCTEP_VF_LINK_MODE_PAUSE_ADVERTISED BIT(1) + u8 pause; + + /* Admin state of the link (ifconfig up/down */ + u8 admin_up; + + /* Operational state of the link: physical link is up down */ + u8 oper_up; +}; + +/* Hardware interface stats information. */ +struct octep_vf_iface_rxtx_stats { + /* Hardware Interface Rx statistics */ + struct octep_vf_iface_rx_stats iface_rx_stats; + + /* Hardware Interface Tx statistics */ + struct octep_vf_iface_tx_stats iface_tx_stats; +}; + +struct octep_vf_fw_info { + /* pkind value to be used in every Tx hardware descriptor */ + u8 pkind; + /* front size data */ + u8 fsz; + /* supported rx offloads OCTEP_VF_RX_OFFLOAD_* */ + u16 rx_ol_flags; + /* supported tx offloads OCTEP_VF_TX_OFFLOAD_* */ + u16 tx_ol_flags; +}; + +/* The Octeon device specific private data structure. + * Each Octeon device has this structure to represent all its components. + */ +struct octep_vf_device { + struct octep_vf_config *conf; + + /* Octeon Chip type. */ + u16 chip_id; + u16 rev_id; + + /* Device capabilities enabled */ + u64 caps_enabled; + /* Device capabilities supported */ + u64 caps_supported; + + /* Pointer to basic Linux device */ + struct device *dev; + /* Linux PCI device pointer */ + struct pci_dev *pdev; + /* Netdev corresponding to the Octeon device */ + struct net_device *netdev; + + /* memory mapped io range */ + struct octep_vf_mmio mmio; + + /* MAC address */ + u8 mac_addr[ETH_ALEN]; + + /* Tx queues (IQ: Instruction Queue) */ + u16 num_iqs; + /* Pointers to Octeon Tx queues */ + struct octep_vf_iq *iq[OCTEP_VF_MAX_IQ]; + + /* Rx queues (OQ: Output Queue) */ + u16 num_oqs; + /* Pointers to Octeon Rx queues */ + struct octep_vf_oq *oq[OCTEP_VF_MAX_OQ]; + + /* Hardware port number of the PCIe interface */ + u16 pcie_port; + + /* Hardware operations */ + struct octep_vf_hw_ops hw_ops; + + /* IRQ info */ + u16 num_irqs; + u16 num_non_ioq_irqs; + char *non_ioq_irq_names; + struct msix_entry *msix_entries; + /* IOq information of it's corresponding MSI-X interrupt. */ + struct octep_vf_ioq_vector *ioq_vector[OCTEP_VF_MAX_QUEUES]; + + /* Hardware Interface Tx statistics */ + struct octep_vf_iface_tx_stats iface_tx_stats; + /* Hardware Interface Rx statistics */ + struct octep_vf_iface_rx_stats iface_rx_stats; + + /* Hardware Interface Link info like supported modes, aneg support */ + struct octep_vf_iface_link_info link_info; + + /* Mailbox to talk to VFs */ + struct octep_vf_mbox *mbox; + + /* Work entry to handle Tx timeout */ + struct work_struct tx_timeout_task; + + /* offset for iface stats */ + u32 ctrl_mbox_ifstats_offset; + + /* Negotiated Mbox version */ + u32 mbox_neg_ver; + + /* firmware info */ + struct octep_vf_fw_info fw_info; +}; + +static inline u16 OCTEP_VF_MAJOR_REV(struct octep_vf_device *oct) +{ + u16 rev = (oct->rev_id & 0xC) >> 2; + + return (rev == 0) ? 1 : rev; +} + +static inline u16 OCTEP_VF_MINOR_REV(struct octep_vf_device *oct) +{ + return (oct->rev_id & 0x3); +} + +/* Octeon CSR read/write access APIs */ +#define octep_vf_write_csr(octep_vf_dev, reg_off, value) \ + writel(value, (octep_vf_dev)->mmio.hw_addr + (reg_off)) + +#define octep_vf_write_csr64(octep_vf_dev, reg_off, val64) \ + writeq(val64, (octep_vf_dev)->mmio.hw_addr + (reg_off)) + +#define octep_vf_read_csr(octep_vf_dev, reg_off) \ + readl((octep_vf_dev)->mmio.hw_addr + (reg_off)) + +#define octep_vf_read_csr64(octep_vf_dev, reg_off) \ + readq((octep_vf_dev)->mmio.hw_addr + (reg_off)) + +extern struct workqueue_struct *octep_vf_wq; + +int octep_vf_device_setup(struct octep_vf_device *oct); +int octep_vf_setup_iqs(struct octep_vf_device *oct); +void octep_vf_free_iqs(struct octep_vf_device *oct); +void octep_vf_clean_iqs(struct octep_vf_device *oct); +int octep_vf_setup_oqs(struct octep_vf_device *oct); +void octep_vf_free_oqs(struct octep_vf_device *oct); +void octep_vf_oq_dbell_init(struct octep_vf_device *oct); +void octep_vf_device_setup_cn93(struct octep_vf_device *oct); +void octep_vf_device_setup_cnxk(struct octep_vf_device *oct); +int octep_vf_iq_process_completions(struct octep_vf_iq *iq, u16 budget); +int octep_vf_oq_process_rx(struct octep_vf_oq *oq, int budget); +int octep_vf_get_if_stats(struct octep_vf_device *oct); +void octep_vf_mbox_work(struct work_struct *work); +#endif /* _OCTEP_VF_MAIN_H_ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c new file mode 100644 index 000000000000..1c1fe293fc50 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ +#include +#include +#include +#include "octep_vf_config.h" +#include "octep_vf_main.h" + +int octep_vf_setup_mbox(struct octep_vf_device *oct) +{ + int ring = 0; + + oct->mbox = vzalloc(sizeof(*oct->mbox)); + if (!oct->mbox) + return -1; + + mutex_init(&oct->mbox->lock); + + oct->hw_ops.setup_mbox_regs(oct, ring); + INIT_WORK(&oct->mbox->wk.work, octep_vf_mbox_work); + oct->mbox->wk.ctxptr = oct; + dev_info(&oct->pdev->dev, "setup vf mbox successfully\n"); + return 0; +} + +void octep_vf_delete_mbox(struct octep_vf_device *oct) +{ + if (oct->mbox) { + if (work_pending(&oct->mbox->wk.work)) + cancel_work_sync(&oct->mbox->wk.work); + + mutex_destroy(&oct->mbox->lock); + vfree(oct->mbox); + oct->mbox = NULL; + dev_info(&oct->pdev->dev, "Deleted vf mbox successfully\n"); + } +} + +int octep_vf_mbox_version_check(struct octep_vf_device *oct) +{ + return 0; +} + +void octep_vf_mbox_work(struct work_struct *work) +{ +} + +int octep_vf_mbox_set_mtu(struct octep_vf_device *oct, int mtu) +{ + return 0; +} + +int octep_vf_mbox_set_mac_addr(struct octep_vf_device *oct, char *mac_addr) +{ + return 0; +} + +int octep_vf_mbox_get_mac_addr(struct octep_vf_device *oct, char *mac_addr) +{ + return 0; +} + +int octep_vf_mbox_set_rx_state(struct octep_vf_device *oct, bool state) +{ + return 0; +} + +int octep_vf_mbox_set_link_status(struct octep_vf_device *oct, bool status) +{ + return 0; +} + +int octep_vf_mbox_get_link_status(struct octep_vf_device *oct, u8 *oper_up) +{ + return 0; +} + +int octep_vf_mbox_dev_remove(struct octep_vf_device *oct) +{ + return 0; +} + +int octep_vf_mbox_get_fw_info(struct octep_vf_device *oct) +{ + return 0; +} + +int octep_vf_mbox_set_offloads(struct octep_vf_device *oct, u16 tx_offloads, + u16 rx_offloads) +{ + return 0; +} diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h new file mode 100644 index 000000000000..14f4fb19445b --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell Octeon EP (EndPoint) Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ +#ifndef _OCTEP_VF_MBOX_H_ +#define _OCTEP_VF_MBOX_H_ + +#define OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE 256 + +int octep_vf_setup_mbox(struct octep_vf_device *oct); +void octep_vf_delete_mbox(struct octep_vf_device *oct); +int octep_vf_mbox_set_mtu(struct octep_vf_device *oct, int mtu); +int octep_vf_mbox_set_mac_addr(struct octep_vf_device *oct, char *mac_addr); +int octep_vf_mbox_get_mac_addr(struct octep_vf_device *oct, char *mac_addr); +int octep_vf_mbox_version_check(struct octep_vf_device *oct); +int octep_vf_mbox_set_rx_state(struct octep_vf_device *oct, bool state); +int octep_vf_mbox_set_link_status(struct octep_vf_device *oct, bool status); +int octep_vf_mbox_get_link_status(struct octep_vf_device *oct, u8 *oper_up); +int octep_vf_mbox_dev_remove(struct octep_vf_device *oct); +int octep_vf_mbox_get_fw_info(struct octep_vf_device *oct); +int octep_vf_mbox_set_offloads(struct octep_vf_device *oct, u16 tx_offloads, u16 rx_offloads); + +#endif diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_regs_cn9k.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_regs_cn9k.h new file mode 100644 index 000000000000..25e2a876ebba --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_regs_cn9k.h @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ +#ifndef _OCTEP_VF_REGS_CN9K_H_ +#define _OCTEP_VF_REGS_CN9K_H_ + +/*############################ RST #########################*/ +#define CN93_VF_CONFIG_XPANSION_BAR 0x38 +#define CN93_VF_CONFIG_PCIE_CAP 0x70 +#define CN93_VF_CONFIG_PCIE_DEVCAP 0x74 +#define CN93_VF_CONFIG_PCIE_DEVCTL 0x78 +#define CN93_VF_CONFIG_PCIE_LINKCAP 0x7C +#define CN93_VF_CONFIG_PCIE_LINKCTL 0x80 +#define CN93_VF_CONFIG_PCIE_SLOTCAP 0x84 +#define CN93_VF_CONFIG_PCIE_SLOTCTL 0x88 + +#define CN93_VF_RING_OFFSET BIT_ULL(17) + +/*###################### RING IN REGISTERS #########################*/ +#define CN93_VF_SDP_R_IN_CONTROL_START 0x10000 +#define CN93_VF_SDP_R_IN_ENABLE_START 0x10010 +#define CN93_VF_SDP_R_IN_INSTR_BADDR_START 0x10020 +#define CN93_VF_SDP_R_IN_INSTR_RSIZE_START 0x10030 +#define CN93_VF_SDP_R_IN_INSTR_DBELL_START 0x10040 +#define CN93_VF_SDP_R_IN_CNTS_START 0x10050 +#define CN93_VF_SDP_R_IN_INT_LEVELS_START 0x10060 +#define CN93_VF_SDP_R_IN_PKT_CNT_START 0x10080 +#define CN93_VF_SDP_R_IN_BYTE_CNT_START 0x10090 + +#define CN93_VF_SDP_R_IN_CONTROL(ring) \ + (CN93_VF_SDP_R_IN_CONTROL_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_IN_ENABLE(ring) \ + (CN93_VF_SDP_R_IN_ENABLE_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_IN_INSTR_BADDR(ring) \ + (CN93_VF_SDP_R_IN_INSTR_BADDR_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_IN_INSTR_RSIZE(ring) \ + (CN93_VF_SDP_R_IN_INSTR_RSIZE_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_IN_INSTR_DBELL(ring) \ + (CN93_VF_SDP_R_IN_INSTR_DBELL_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_IN_CNTS(ring) \ + (CN93_VF_SDP_R_IN_CNTS_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_IN_INT_LEVELS(ring) \ + (CN93_VF_SDP_R_IN_INT_LEVELS_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_IN_PKT_CNT(ring) \ + (CN93_VF_SDP_R_IN_PKT_CNT_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_IN_BYTE_CNT(ring) \ + (CN93_VF_SDP_R_IN_BYTE_CNT_START + ((ring) * CN93_VF_RING_OFFSET)) + +/*------------------ R_IN Masks ----------------*/ + +/** Rings per Virtual Function **/ +#define CN93_VF_R_IN_CTL_RPVF_MASK (0xF) +#define CN93_VF_R_IN_CTL_RPVF_POS (48) + +/* Number of instructions to be read in one MAC read request. + * setting to Max value(4) + **/ +#define CN93_VF_R_IN_CTL_IDLE BIT_ULL(28) +#define CN93_VF_R_IN_CTL_RDSIZE (0x3ULL << 25) +#define CN93_VF_R_IN_CTL_IS_64B BIT_ULL(24) +#define CN93_VF_R_IN_CTL_D_NSR BIT_ULL(8) +#define CN93_VF_R_IN_CTL_D_ESR BIT_ULL(6) +#define CN93_VF_R_IN_CTL_D_ROR BIT_ULL(5) +#define CN93_VF_R_IN_CTL_NSR BIT_ULL(3) +#define CN93_VF_R_IN_CTL_ESR BIT_ULL(1) +#define CN93_VF_R_IN_CTL_ROR BIT_ULL(0) + +#define CN93_VF_R_IN_CTL_MASK (CN93_VF_R_IN_CTL_RDSIZE | CN93_VF_R_IN_CTL_IS_64B) + +/*###################### RING OUT REGISTERS #########################*/ +#define CN93_VF_SDP_R_OUT_CNTS_START 0x10100 +#define CN93_VF_SDP_R_OUT_INT_LEVELS_START 0x10110 +#define CN93_VF_SDP_R_OUT_SLIST_BADDR_START 0x10120 +#define CN93_VF_SDP_R_OUT_SLIST_RSIZE_START 0x10130 +#define CN93_VF_SDP_R_OUT_SLIST_DBELL_START 0x10140 +#define CN93_VF_SDP_R_OUT_CONTROL_START 0x10150 +#define CN93_VF_SDP_R_OUT_ENABLE_START 0x10160 +#define CN93_VF_SDP_R_OUT_PKT_CNT_START 0x10180 +#define CN93_VF_SDP_R_OUT_BYTE_CNT_START 0x10190 + +#define CN93_VF_SDP_R_OUT_CONTROL(ring) \ + (CN93_VF_SDP_R_OUT_CONTROL_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_OUT_ENABLE(ring) \ + (CN93_VF_SDP_R_OUT_ENABLE_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_OUT_SLIST_BADDR(ring) \ + (CN93_VF_SDP_R_OUT_SLIST_BADDR_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_OUT_SLIST_RSIZE(ring) \ + (CN93_VF_SDP_R_OUT_SLIST_RSIZE_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_OUT_SLIST_DBELL(ring) \ + (CN93_VF_SDP_R_OUT_SLIST_DBELL_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_OUT_CNTS(ring) \ + (CN93_VF_SDP_R_OUT_CNTS_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_OUT_INT_LEVELS(ring) \ + (CN93_VF_SDP_R_OUT_INT_LEVELS_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_OUT_PKT_CNT(ring) \ + (CN93_VF_SDP_R_OUT_PKT_CNT_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_OUT_BYTE_CNT(ring) \ + (CN93_VF_SDP_R_OUT_BYTE_CNT_START + ((ring) * CN93_VF_RING_OFFSET)) + +/*------------------ R_OUT Masks ----------------*/ +#define CN93_VF_R_OUT_INT_LEVELS_BMODE BIT_ULL(63) +#define CN93_VF_R_OUT_INT_LEVELS_TIMET (32) + +#define CN93_VF_R_OUT_CTL_IDLE BIT_ULL(40) +#define CN93_VF_R_OUT_CTL_ES_I BIT_ULL(34) +#define CN93_VF_R_OUT_CTL_NSR_I BIT_ULL(33) +#define CN93_VF_R_OUT_CTL_ROR_I BIT_ULL(32) +#define CN93_VF_R_OUT_CTL_ES_D BIT_ULL(30) +#define CN93_VF_R_OUT_CTL_NSR_D BIT_ULL(29) +#define CN93_VF_R_OUT_CTL_ROR_D BIT_ULL(28) +#define CN93_VF_R_OUT_CTL_ES_P BIT_ULL(26) +#define CN93_VF_R_OUT_CTL_NSR_P BIT_ULL(25) +#define CN93_VF_R_OUT_CTL_ROR_P BIT_ULL(24) +#define CN93_VF_R_OUT_CTL_IMODE BIT_ULL(23) + +/* ##################### Mail Box Registers ########################## */ +/* SDP PF to VF Mailbox Data Register */ +#define CN93_VF_SDP_R_MBOX_PF_VF_DATA_START 0x10210 +/* SDP Packet PF to VF Mailbox Interrupt Register */ +#define CN93_VF_SDP_R_MBOX_PF_VF_INT_START 0x10220 +/* SDP VF to PF Mailbox Data Register */ +#define CN93_VF_SDP_R_MBOX_VF_PF_DATA_START 0x10230 + +#define CN93_VF_SDP_R_MBOX_PF_VF_INT_ENAB BIT_ULL(1) +#define CN93_VF_SDP_R_MBOX_PF_VF_INT_STATUS BIT_ULL(0) + +#define CN93_VF_SDP_R_MBOX_PF_VF_DATA(ring) \ + (CN93_VF_SDP_R_MBOX_PF_VF_DATA_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_MBOX_PF_VF_INT(ring) \ + (CN93_VF_SDP_R_MBOX_PF_VF_INT_START + ((ring) * CN93_VF_RING_OFFSET)) + +#define CN93_VF_SDP_R_MBOX_VF_PF_DATA(ring) \ + (CN93_VF_SDP_R_MBOX_VF_PF_DATA_START + ((ring) * CN93_VF_RING_OFFSET)) +#endif /* _OCTEP_VF_REGS_CN9K_H_ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_regs_cnxk.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_regs_cnxk.h new file mode 100644 index 000000000000..2e156745ef64 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_regs_cnxk.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ +#ifndef _OCTEP_VF_REGS_CNXK_H_ +#define _OCTEP_VF_REGS_CNXK_H_ + +/*############################ RST #########################*/ +#define CNXK_VF_CONFIG_XPANSION_BAR 0x38 +#define CNXK_VF_CONFIG_PCIE_CAP 0x70 +#define CNXK_VF_CONFIG_PCIE_DEVCAP 0x74 +#define CNXK_VF_CONFIG_PCIE_DEVCTL 0x78 +#define CNXK_VF_CONFIG_PCIE_LINKCAP 0x7C +#define CNXK_VF_CONFIG_PCIE_LINKCTL 0x80 +#define CNXK_VF_CONFIG_PCIE_SLOTCAP 0x84 +#define CNXK_VF_CONFIG_PCIE_SLOTCTL 0x88 + +#define CNXK_VF_RING_OFFSET (0x1ULL << 17) + +/*###################### RING IN REGISTERS #########################*/ +#define CNXK_VF_SDP_R_IN_CONTROL_START 0x10000 +#define CNXK_VF_SDP_R_IN_ENABLE_START 0x10010 +#define CNXK_VF_SDP_R_IN_INSTR_BADDR_START 0x10020 +#define CNXK_VF_SDP_R_IN_INSTR_RSIZE_START 0x10030 +#define CNXK_VF_SDP_R_IN_INSTR_DBELL_START 0x10040 +#define CNXK_VF_SDP_R_IN_CNTS_START 0x10050 +#define CNXK_VF_SDP_R_IN_INT_LEVELS_START 0x10060 +#define CNXK_VF_SDP_R_IN_PKT_CNT_START 0x10080 +#define CNXK_VF_SDP_R_IN_BYTE_CNT_START 0x10090 +#define CNXK_VF_SDP_R_ERR_TYPE_START 0x10400 + +#define CNXK_VF_SDP_R_ERR_TYPE(ring) \ + (CNXK_VF_SDP_R_ERR_TYPE_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_IN_CONTROL(ring) \ + (CNXK_VF_SDP_R_IN_CONTROL_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_IN_ENABLE(ring) \ + (CNXK_VF_SDP_R_IN_ENABLE_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_IN_INSTR_BADDR(ring) \ + (CNXK_VF_SDP_R_IN_INSTR_BADDR_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_IN_INSTR_RSIZE(ring) \ + (CNXK_VF_SDP_R_IN_INSTR_RSIZE_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_IN_INSTR_DBELL(ring) \ + (CNXK_VF_SDP_R_IN_INSTR_DBELL_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_IN_CNTS(ring) \ + (CNXK_VF_SDP_R_IN_CNTS_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_IN_INT_LEVELS(ring) \ + (CNXK_VF_SDP_R_IN_INT_LEVELS_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_IN_PKT_CNT(ring) \ + (CNXK_VF_SDP_R_IN_PKT_CNT_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_IN_BYTE_CNT(ring) \ + (CNXK_VF_SDP_R_IN_BYTE_CNT_START + ((ring) * CNXK_VF_RING_OFFSET)) + +/*------------------ R_IN Masks ----------------*/ + +/** Rings per Virtual Function **/ +#define CNXK_VF_R_IN_CTL_RPVF_MASK (0xF) +#define CNXK_VF_R_IN_CTL_RPVF_POS (48) + +/* Number of instructions to be read in one MAC read request. + * setting to Max value(4) + **/ +#define CNXK_VF_R_IN_CTL_IDLE (0x1ULL << 28) +#define CNXK_VF_R_IN_CTL_RDSIZE (0x3ULL << 25) +#define CNXK_VF_R_IN_CTL_IS_64B (0x1ULL << 24) +#define CNXK_VF_R_IN_CTL_D_NSR (0x1ULL << 8) +#define CNXK_VF_R_IN_CTL_D_ESR (0x1ULL << 6) +#define CNXK_VF_R_IN_CTL_D_ROR (0x1ULL << 5) +#define CNXK_VF_R_IN_CTL_NSR (0x1ULL << 3) +#define CNXK_VF_R_IN_CTL_ESR (0x1ULL << 1) +#define CNXK_VF_R_IN_CTL_ROR (0x1ULL << 0) + +#define CNXK_VF_R_IN_CTL_MASK (CNXK_VF_R_IN_CTL_RDSIZE | CNXK_VF_R_IN_CTL_IS_64B) + +/*###################### RING OUT REGISTERS #########################*/ +#define CNXK_VF_SDP_R_OUT_CNTS_START 0x10100 +#define CNXK_VF_SDP_R_OUT_INT_LEVELS_START 0x10110 +#define CNXK_VF_SDP_R_OUT_SLIST_BADDR_START 0x10120 +#define CNXK_VF_SDP_R_OUT_SLIST_RSIZE_START 0x10130 +#define CNXK_VF_SDP_R_OUT_SLIST_DBELL_START 0x10140 +#define CNXK_VF_SDP_R_OUT_CONTROL_START 0x10150 +#define CNXK_VF_SDP_R_OUT_WMARK_START 0x10160 +#define CNXK_VF_SDP_R_OUT_ENABLE_START 0x10170 +#define CNXK_VF_SDP_R_OUT_PKT_CNT_START 0x10180 +#define CNXK_VF_SDP_R_OUT_BYTE_CNT_START 0x10190 + +#define CNXK_VF_SDP_R_OUT_CONTROL(ring) \ + (CNXK_VF_SDP_R_OUT_CONTROL_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_OUT_ENABLE(ring) \ + (CNXK_VF_SDP_R_OUT_ENABLE_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_OUT_SLIST_BADDR(ring) \ + (CNXK_VF_SDP_R_OUT_SLIST_BADDR_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_OUT_SLIST_RSIZE(ring) \ + (CNXK_VF_SDP_R_OUT_SLIST_RSIZE_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_OUT_SLIST_DBELL(ring) \ + (CNXK_VF_SDP_R_OUT_SLIST_DBELL_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_OUT_WMARK(ring) \ + (CNXK_VF_SDP_R_OUT_WMARK_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_OUT_CNTS(ring) \ + (CNXK_VF_SDP_R_OUT_CNTS_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_OUT_INT_LEVELS(ring) \ + (CNXK_VF_SDP_R_OUT_INT_LEVELS_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_OUT_PKT_CNT(ring) \ + (CNXK_VF_SDP_R_OUT_PKT_CNT_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_OUT_BYTE_CNT(ring) \ + (CNXK_VF_SDP_R_OUT_BYTE_CNT_START + ((ring) * CNXK_VF_RING_OFFSET)) + +/*------------------ R_OUT Masks ----------------*/ +#define CNXK_VF_R_OUT_INT_LEVELS_BMODE BIT_ULL(63) +#define CNXK_VF_R_OUT_INT_LEVELS_TIMET (32) + +#define CNXK_VF_R_OUT_CTL_IDLE BIT_ULL(40) +#define CNXK_VF_R_OUT_CTL_ES_I BIT_ULL(34) +#define CNXK_VF_R_OUT_CTL_NSR_I BIT_ULL(33) +#define CNXK_VF_R_OUT_CTL_ROR_I BIT_ULL(32) +#define CNXK_VF_R_OUT_CTL_ES_D BIT_ULL(30) +#define CNXK_VF_R_OUT_CTL_NSR_D BIT_ULL(29) +#define CNXK_VF_R_OUT_CTL_ROR_D BIT_ULL(28) +#define CNXK_VF_R_OUT_CTL_ES_P BIT_ULL(26) +#define CNXK_VF_R_OUT_CTL_NSR_P BIT_ULL(25) +#define CNXK_VF_R_OUT_CTL_ROR_P BIT_ULL(24) +#define CNXK_VF_R_OUT_CTL_IMODE BIT_ULL(23) + +/* ##################### Mail Box Registers ########################## */ +/* SDP PF to VF Mailbox Data Register */ +#define CNXK_VF_SDP_R_MBOX_PF_VF_DATA_START 0x10210 +/* SDP Packet PF to VF Mailbox Interrupt Register */ +#define CNXK_VF_SDP_R_MBOX_PF_VF_INT_START 0x10220 +/* SDP VF to PF Mailbox Data Register */ +#define CNXK_VF_SDP_R_MBOX_VF_PF_DATA_START 0x10230 + +#define CNXK_VF_SDP_R_MBOX_PF_VF_INT_ENAB BIT_ULL(1) +#define CNXK_VF_SDP_R_MBOX_PF_VF_INT_STATUS BIT_ULL(0) + +#define CNXK_VF_SDP_R_MBOX_PF_VF_DATA(ring) \ + (CNXK_VF_SDP_R_MBOX_PF_VF_DATA_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_MBOX_PF_VF_INT(ring) \ + (CNXK_VF_SDP_R_MBOX_PF_VF_INT_START + ((ring) * CNXK_VF_RING_OFFSET)) + +#define CNXK_VF_SDP_R_MBOX_VF_PF_DATA(ring) \ + (CNXK_VF_SDP_R_MBOX_VF_PF_DATA_START + ((ring) * CNXK_VF_RING_OFFSET)) +#endif /* _OCTEP_VF_REGS_CNXK_H_ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c new file mode 100644 index 000000000000..4f1a8157ce39 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#include +#include + +#include "octep_vf_config.h" +#include "octep_vf_main.h" + +/** + * octep_vf_setup_oqs() - setup resources for all Rx queues. + * + * @oct: Octeon device private data structure. + */ +int octep_vf_setup_oqs(struct octep_vf_device *oct) +{ + return -1; +} + +/** + * octep_vf_oq_dbell_init() - Initialize Rx queue doorbell. + * + * @oct: Octeon device private data structure. + * + * Write number of descriptors to Rx queue doorbell register. + */ +void octep_vf_oq_dbell_init(struct octep_vf_device *oct) +{ +} + +/** + * octep_vf_free_oqs() - Free resources of all Rx queues. + * + * @oct: Octeon device private data structure. + */ +void octep_vf_free_oqs(struct octep_vf_device *oct) +{ +} diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.h new file mode 100644 index 000000000000..fe46838b5200 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.h @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#ifndef _OCTEP_VF_RX_H_ +#define _OCTEP_VF_RX_H_ + +/* struct octep_vf_oq_desc_hw - Octeon Hardware OQ descriptor format. + * + * The descriptor ring is made of descriptors which have 2 64-bit values: + * + * @buffer_ptr: DMA address of the skb->data + * @info_ptr: DMA address of host memory, used to update pkt count by hw. + * This is currently unused to save pci writes. + */ +struct octep_vf_oq_desc_hw { + dma_addr_t buffer_ptr; + u64 info_ptr; +}; + +static_assert(sizeof(struct octep_vf_oq_desc_hw) == 16); + +#define OCTEP_VF_OQ_DESC_SIZE (sizeof(struct octep_vf_oq_desc_hw)) + +/* Rx offload flags */ +#define OCTEP_VF_RX_OFFLOAD_VLAN_STRIP BIT(0) +#define OCTEP_VF_RX_OFFLOAD_IPV4_CKSUM BIT(1) +#define OCTEP_VF_RX_OFFLOAD_UDP_CKSUM BIT(2) +#define OCTEP_VF_RX_OFFLOAD_TCP_CKSUM BIT(3) + +#define OCTEP_VF_RX_OFFLOAD_CKSUM (OCTEP_VF_RX_OFFLOAD_IPV4_CKSUM | \ + OCTEP_VF_RX_OFFLOAD_UDP_CKSUM | \ + OCTEP_VF_RX_OFFLOAD_TCP_CKSUM) + +#define OCTEP_VF_RX_IP_CSUM(flags) ((flags) & \ + (OCTEP_VF_RX_OFFLOAD_IPV4_CKSUM | \ + OCTEP_VF_RX_OFFLOAD_TCP_CKSUM | \ + OCTEP_VF_RX_OFFLOAD_UDP_CKSUM)) + +/* bit 0 is vlan strip */ +#define OCTEP_VF_RX_CSUM_IP_VERIFIED BIT(1) +#define OCTEP_VF_RX_CSUM_L4_VERIFIED BIT(2) + +#define OCTEP_VF_RX_CSUM_VERIFIED(flags) ((flags) & \ + (OCTEP_VF_RX_CSUM_L4_VERIFIED | \ + OCTEP_VF_RX_CSUM_IP_VERIFIED)) + +/* Extended Response Header in packet data received from Hardware. + * Includes metadata like checksum status. + * this is valid only if hardware/firmware published support for this. + * This is at offset 0 of packet data (skb->data). + */ +struct octep_vf_oq_resp_hw_ext { + /* Reserved. */ + u64 rsvd:48; + + /* rx offload flags */ + u16 rx_ol_flags; +}; + +static_assert(sizeof(struct octep_vf_oq_resp_hw_ext) == 8); + +#define OCTEP_VF_OQ_RESP_HW_EXT_SIZE (sizeof(struct octep_vf_oq_resp_hw_ext)) + +/* Length of Rx packet DMA'ed by Octeon to Host. + * this is in bigendian; so need to be converted to cpu endian. + * Octeon writes this at the beginning of Rx buffer (skb->data). + */ +struct octep_vf_oq_resp_hw { + /* The Length of the packet. */ + __be64 length; +}; + +static_assert(sizeof(struct octep_vf_oq_resp_hw) == 8); + +#define OCTEP_VF_OQ_RESP_HW_SIZE (sizeof(struct octep_vf_oq_resp_hw)) + +/* Pointer to data buffer. + * Driver keeps a pointer to the data buffer that it made available to + * the Octeon device. Since the descriptor ring keeps physical (bus) + * addresses, this field is required for the driver to keep track of + * the virtual address pointers. The fields are operated by + * OS-dependent routines. + */ +struct octep_vf_rx_buffer { + struct page *page; + + /* length from rx hardware descriptor after converting to cpu endian */ + u64 len; +}; + +#define OCTEP_VF_OQ_RECVBUF_SIZE (sizeof(struct octep_vf_rx_buffer)) + +/* Output Queue statistics. Each output queue has four stats fields. */ +struct octep_vf_oq_stats { + /* Number of packets received from the Device. */ + u64 packets; + + /* Number of bytes received from the Device. */ + u64 bytes; + + /* Number of times failed to allocate buffers. */ + u64 alloc_failures; +}; + +#define OCTEP_VF_OQ_STATS_SIZE (sizeof(struct octep_vf_oq_stats)) + +/* Hardware interface Rx statistics */ +struct octep_vf_iface_rx_stats { + /* Received packets */ + u64 pkts; + + /* Octets of received packets */ + u64 octets; + + /* Received PAUSE and Control packets */ + u64 pause_pkts; + + /* Received PAUSE and Control octets */ + u64 pause_octets; + + /* Filtered DMAC0 packets */ + u64 dmac0_pkts; + + /* Filtered DMAC0 octets */ + u64 dmac0_octets; + + /* Packets dropped due to RX FIFO full */ + u64 dropped_pkts_fifo_full; + + /* Octets dropped due to RX FIFO full */ + u64 dropped_octets_fifo_full; + + /* Error packets */ + u64 err_pkts; + + /* Filtered DMAC1 packets */ + u64 dmac1_pkts; + + /* Filtered DMAC1 octets */ + u64 dmac1_octets; + + /* NCSI-bound packets dropped */ + u64 ncsi_dropped_pkts; + + /* NCSI-bound octets dropped */ + u64 ncsi_dropped_octets; + + /* Multicast packets received. */ + u64 mcast_pkts; + + /* Broadcast packets received. */ + u64 bcast_pkts; + +}; + +/* The Descriptor Ring Output Queue structure. + * This structure has all the information required to implement a + * Octeon OQ. + */ +struct octep_vf_oq { + u32 q_no; + + struct octep_vf_device *octep_vf_dev; + struct net_device *netdev; + struct device *dev; + + struct napi_struct *napi; + + /* The receive buffer list. This list has the virtual addresses + * of the buffers. + */ + struct octep_vf_rx_buffer *buff_info; + + /* Pointer to the mapped packet credit register. + * Host writes number of info/buffer ptrs available to this register + */ + u8 __iomem *pkts_credit_reg; + + /* Pointer to the mapped packet sent register. + * Octeon writes the number of packets DMA'ed to host memory + * in this register. + */ + u8 __iomem *pkts_sent_reg; + + /* Statistics for this OQ. */ + struct octep_vf_oq_stats stats; + + /* Packets pending to be processed */ + u32 pkts_pending; + u32 last_pkt_count; + + /* Index in the ring where the driver should read the next packet */ + u32 host_read_idx; + + /* Number of descriptors in this ring. */ + u32 max_count; + u32 ring_size_mask; + + /* The number of descriptors pending refill. */ + u32 refill_count; + + /* Index in the ring where the driver will refill the + * descriptor's buffer + */ + u32 host_refill_idx; + u32 refill_threshold; + + /* The size of each buffer pointed by the buffer pointer. */ + u32 buffer_size; + u32 max_single_buffer_size; + + /* The 8B aligned descriptor ring starts at this address. */ + struct octep_vf_oq_desc_hw *desc_ring; + + /* DMA mapped address of the OQ descriptor ring. */ + dma_addr_t desc_ring_dma; +}; + +#define OCTEP_VF_OQ_SIZE (sizeof(struct octep_vf_oq)) +#endif /* _OCTEP_VF_RX_H_ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c new file mode 100644 index 000000000000..232ba479ecf6 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#include +#include + +#include "octep_vf_config.h" +#include "octep_vf_main.h" + +/** + * octep_vf_clean_iqs() - Clean Tx queues to shutdown the device. + * + * @oct: Octeon device private data structure. + * + * Free the buffers in Tx queue descriptors pending completion and + * reset queue indices + */ +void octep_vf_clean_iqs(struct octep_vf_device *oct) +{ +} + +/** + * octep_vf_setup_iqs() - setup resources for all Tx queues. + * + * @oct: Octeon device private data structure. + */ +int octep_vf_setup_iqs(struct octep_vf_device *oct) +{ + return -1; +} + +/** + * octep_vf_free_iqs() - Free resources of all Tx queues. + * + * @oct: Octeon device private data structure. + */ +void octep_vf_free_iqs(struct octep_vf_device *oct) +{ +} diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.h new file mode 100644 index 000000000000..f338b975103c --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.h @@ -0,0 +1,276 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#ifndef _OCTEP_VF_TX_H_ +#define _OCTEP_VF_TX_H_ + +#define IQ_SEND_OK 0 +#define IQ_SEND_STOP 1 +#define IQ_SEND_FAILED -1 + +#define TX_BUFTYPE_NONE 0 +#define TX_BUFTYPE_NET 1 +#define TX_BUFTYPE_NET_SG 2 +#define NUM_TX_BUFTYPES 3 + +/* Hardware format for Scatter/Gather list + * + * 63 48|47 32|31 16|15 0 + * ----------------------------------------- + * | Len 0 | Len 1 | Len 2 | Len 3 | + * ----------------------------------------- + * | Ptr 0 | + * ----------------------------------------- + * | Ptr 1 | + * ----------------------------------------- + * | Ptr 2 | + * ----------------------------------------- + * | Ptr 3 | + * ----------------------------------------- + */ +struct octep_vf_tx_sglist_desc { + u16 len[4]; + dma_addr_t dma_ptr[4]; +}; + +static_assert(sizeof(struct octep_vf_tx_sglist_desc) == 40); + +/* Each Scatter/Gather entry sent to hardwar hold four pointers. + * So, number of entries required is (MAX_SKB_FRAGS + 1)/4, where '+1' + * is for main skb which also goes as a gather buffer to Octeon hardware. + * To allocate sufficient SGLIST entries for a packet with max fragments, + * align by adding 3 before calcuating max SGLIST entries per packet. + */ +#define OCTEP_VF_SGLIST_ENTRIES_PER_PKT ((MAX_SKB_FRAGS + 1 + 3) / 4) +#define OCTEP_VF_SGLIST_SIZE_PER_PKT \ + (OCTEP_VF_SGLIST_ENTRIES_PER_PKT * sizeof(struct octep_vf_tx_sglist_desc)) + +struct octep_vf_tx_buffer { + struct sk_buff *skb; + dma_addr_t dma; + struct octep_vf_tx_sglist_desc *sglist; + dma_addr_t sglist_dma; + u8 gather; +}; + +#define OCTEP_VF_IQ_TXBUFF_INFO_SIZE (sizeof(struct octep_vf_tx_buffer)) + +/* VF Hardware interface Tx statistics */ +struct octep_vf_iface_tx_stats { + /* Total frames sent on the interface */ + u64 pkts; + + /* Total octets sent on the interface */ + u64 octs; + + /* Packets sent to a broadcast DMAC */ + u64 bcst; + + /* Packets sent to the multicast DMAC */ + u64 mcst; + + /* Packets dropped */ + u64 dropped; + + /* Reserved */ + u64 reserved[13]; +}; + +/* VF Input Queue statistics */ +struct octep_vf_iq_stats { + /* Instructions posted to this queue. */ + u64 instr_posted; + + /* Instructions copied by hardware for processing. */ + u64 instr_completed; + + /* Instructions that could not be processed. */ + u64 instr_dropped; + + /* Bytes sent through this queue. */ + u64 bytes_sent; + + /* Gather entries sent through this queue. */ + u64 sgentry_sent; + + /* Number of transmit failures due to TX_BUSY */ + u64 tx_busy; + + /* Number of times the queue is restarted */ + u64 restart_cnt; +}; + +/* The instruction (input) queue. + * The input queue is used to post raw (instruction) mode data or packet + * data to Octeon device from the host. Each input queue (up to 4) for + * a Octeon device has one such structure to represent it. + */ +struct octep_vf_iq { + u32 q_no; + + struct octep_vf_device *octep_vf_dev; + struct net_device *netdev; + struct device *dev; + struct netdev_queue *netdev_q; + + /* Index in input ring where driver should write the next packet */ + u16 host_write_index; + + /* Index in input ring where Octeon is expected to read next packet */ + u16 octep_vf_read_index; + + /* This index aids in finding the window in the queue where Octeon + * has read the commands. + */ + u16 flush_index; + + /* Statistics for this input queue. */ + struct octep_vf_iq_stats stats; + + /* Pointer to the Virtual Base addr of the input ring. */ + struct octep_vf_tx_desc_hw *desc_ring; + + /* DMA mapped base address of the input descriptor ring. */ + dma_addr_t desc_ring_dma; + + /* Info of Tx buffers pending completion. */ + struct octep_vf_tx_buffer *buff_info; + + /* Base pointer to Scatter/Gather lists for all ring descriptors. */ + struct octep_vf_tx_sglist_desc *sglist; + + /* DMA mapped addr of Scatter Gather Lists */ + dma_addr_t sglist_dma; + + /* Octeon doorbell register for the ring. */ + u8 __iomem *doorbell_reg; + + /* Octeon instruction count register for this ring. */ + u8 __iomem *inst_cnt_reg; + + /* interrupt level register for this ring */ + u8 __iomem *intr_lvl_reg; + + /* Maximum no. of instructions in this queue. */ + u32 max_count; + u32 ring_size_mask; + + u32 pkt_in_done; + u32 pkts_processed; + + u32 status; + + /* Number of instructions pending to be posted to Octeon. */ + u32 fill_cnt; + + /* The max. number of instructions that can be held pending by the + * driver before ringing doorbell. + */ + u32 fill_threshold; +}; + +/* Hardware Tx Instruction Header */ +struct octep_vf_instr_hdr { + /* Data Len */ + u64 tlen:16; + + /* Reserved */ + u64 rsvd:20; + + /* PKIND for SDP */ + u64 pkind:6; + + /* Front Data size */ + u64 fsz:6; + + /* No. of entries in gather list */ + u64 gsz:14; + + /* Gather indicator 1=gather*/ + u64 gather:1; + + /* Reserved3 */ + u64 reserved3:1; +}; + +static_assert(sizeof(struct octep_vf_instr_hdr) == 8); + +/* Tx offload flags */ +#define OCTEP_VF_TX_OFFLOAD_VLAN_INSERT BIT(0) +#define OCTEP_VF_TX_OFFLOAD_IPV4_CKSUM BIT(1) +#define OCTEP_VF_TX_OFFLOAD_UDP_CKSUM BIT(2) +#define OCTEP_VF_TX_OFFLOAD_TCP_CKSUM BIT(3) +#define OCTEP_VF_TX_OFFLOAD_SCTP_CKSUM BIT(4) +#define OCTEP_VF_TX_OFFLOAD_TCP_TSO BIT(5) +#define OCTEP_VF_TX_OFFLOAD_UDP_TSO BIT(6) + +#define OCTEP_VF_TX_OFFLOAD_CKSUM (OCTEP_VF_TX_OFFLOAD_IPV4_CKSUM | \ + OCTEP_VF_TX_OFFLOAD_UDP_CKSUM | \ + OCTEP_VF_TX_OFFLOAD_TCP_CKSUM) + +#define OCTEP_VF_TX_OFFLOAD_TSO (OCTEP_VF_TX_OFFLOAD_TCP_TSO | \ + OCTEP_VF_TX_OFFLOAD_UDP_TSO) + +#define OCTEP_VF_TX_IP_CSUM(flags) ((flags) & \ + (OCTEP_VF_TX_OFFLOAD_IPV4_CKSUM | \ + OCTEP_VF_TX_OFFLOAD_TCP_CKSUM | \ + OCTEP_VF_TX_OFFLOAD_UDP_CKSUM)) + +#define OCTEP_VF_TX_TSO(flags) ((flags) & \ + (OCTEP_VF_TX_OFFLOAD_TCP_TSO | \ + OCTEP_VF_TX_OFFLOAD_UDP_TSO)) + +struct tx_mdata { + /* offload flags */ + u16 ol_flags; + + /* gso size */ + u16 gso_size; + + /* gso flags */ + u16 gso_segs; + + /* reserved */ + u16 rsvd1; + + /* reserved */ + u64 rsvd2; +}; + +static_assert(sizeof(struct tx_mdata) == 16); + +/* 64-byte Tx instruction format. + * Format of instruction for a 64-byte mode input queue. + * + * only first 16-bytes (dptr and ih) are mandatory; rest are optional + * and filled by the driver based on firmware/hardware capabilities. + * These optional headers together called Front Data and its size is + * described by ih->fsz. + */ +struct octep_vf_tx_desc_hw { + /* Pointer where the input data is available. */ + u64 dptr; + + /* Instruction Header. */ + union { + struct octep_vf_instr_hdr ih; + u64 ih64; + }; + + union { + u64 txm64[2]; + struct tx_mdata txm; + }; + + /* Additional headers available in a 64-byte instruction. */ + u64 exhdr[4]; +}; + +static_assert(sizeof(struct octep_vf_tx_desc_hw) == 64); + +#define OCTEP_VF_IQ_DESC_SIZE (sizeof(struct octep_vf_tx_desc_hw)) +#endif /* _OCTEP_VF_TX_H_ */ From patchwork Mon Jan 29 05:02:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shinas Rasheed X-Patchwork-Id: 193239 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2087:b0:106:209c:c626 with SMTP id gs7csp367576dyb; Sun, 28 Jan 2024 21:08:43 -0800 (PST) X-Google-Smtp-Source: AGHT+IEPACEKuHbFt4ps9BYoD/0f/gjoE/qPzs5WMIZtlUP5PTq7N3m3iA/AaHLhFlPw0vOYs4sT X-Received: by 2002:a05:6122:58f:b0:4b7:8d7c:346c with SMTP id i15-20020a056122058f00b004b78d7c346cmr1133668vko.3.1706504923430; Sun, 28 Jan 2024 21:08:43 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706504923; cv=pass; d=google.com; s=arc-20160816; b=Aom3jEfLZ12ymcWtDSyUcE8cTBkIumIUAibwOXXFbu5dTbZ+rt9J02EAfqMx1IlZwV 7UU9S/a+cWxcnmWeVZlqx4sltXg1tkYyQSyL+mW2yvVxYTRe9ZYuIuF2PK0Q2tSkX+Ax KgZqmo1bM3s6V0+sCEuwh+MprHhcDP0X9eUkkx9KPpNRIZPGeY9c+iIQ7h423zSzrdin GfNgkBZltZqWV5fV8vrv5fPLblhLLoC9JbNLBW4K/63B9Oe39PpTjzX56L8fyrCZPekR FWE4WHvqKJ54P2JKizTIHfkNQ5OgVjADcluAi8Prx19Ay3K25ne9Umrdqe6UpG4NN/hY gYoQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=/6vhrXptiz3YqJDXvGOHWmLnXYBKA1H82QKOpimOmkQ=; fh=Y/Zcr0YXYeEsWchgSSogMl8sJJcf/EqHGWMcPJ+i19E=; b=FjdRzXFFgU8yMUEi3SASRPtHTLImtHNV97ksTZe+LLShmz2OUTaqbgnnEbj2O7Qjuu wY3lZPysfp21/mURLhHTPF2BbGYP7Wt+9y8N1y1s3g+wg0QvxWQWKDAIEv8Ei29a29iX UdV0hAgIT46p2jwHKZL/o0rOjaw9C1tdKoDKKyttkWSGX4GOROraTDJR8pZIsoCTcR30 x6zI/JZvVYEZfERvB9i3NV1KRIqdBG7sTkzG1PkWJSD68a+Uv6LgM/Uvr/Us0PnSE44e 4TxzrmxO+KnyI3/sAr1bEh8ogHVOELjYAHWt3PKHmknnOfgGURTXjuxaLqFC741GY1Db Gzbw== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=k7pao5lA; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42171-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42171-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id k68-20020a633d47000000b005ce01026222si5073060pga.49.2024.01.28.21.08.42 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Jan 2024 21:08:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-42171-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=k7pao5lA; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42171-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42171-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 7AF91B23E4D for ; Mon, 29 Jan 2024 05:05:56 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5C5FA51C40; Mon, 29 Jan 2024 05:03:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="k7pao5lA" Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D81E64CDE1; Mon, 29 Jan 2024 05:03:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.156.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504624; cv=none; b=RXSOpPsecHb68mqXdaXyWXh4fAfeS5UWfty6Q3QQWwmFuHBjjG1Rj8rJICg6Bv6ryzxnKQ1stCu1kQ0cF7GN+IggEiMY+y0P/2aybTPKZtyxfmhPreW6YSyfK4eCKLHoPL8HwyZZrdG7kczklGfpxK8Fo500N5C0a2Hmyg4HX6Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504624; c=relaxed/simple; bh=HdaMLL9rW0QVZDM+Hi0DvXYGiGUOJKuyginQJJwFUOQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nNfG9WWpU+0Uwyk6P55WiHAU8HrDaOJ0Lam/8bPXDipjleLNhBPvv6iJR8FtBcRNn7z+3dKjTR78G3vJPEMKvRi+tdnKpHeAOJ9bNBmdoTyFVTQ9WSiJ/m5LprCg5X9WQu8laiKZhXF5yAc6Zd8ixb/dccC3jlO212gShMKfG9g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com; spf=pass smtp.mailfrom=marvell.com; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b=k7pao5lA; arc=none smtp.client-ip=67.231.156.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 40SMhIvR008259; Sun, 28 Jan 2024 21:03:19 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=/6vhrXptiz3YqJDXvGOHWmLnXYBKA1H82QKOpimOmkQ=; b=k7p ao5lA41JrgrgB6cKiiPdNVMKtQ2QhwxHYs7WMP5MBhkjQn5G3vd+i9aCemnIhnp7 pBx7zc8lMtWwbkWiKEOdhjdi7u8UOICdAdw7w20Mipg2gUzaJtS1lzo+8hxKCkuW DQU9DmWyvfd7qWZYNFJpSjwj3kmV+KGJeB4ZpxAVRRhkg9EZ2LpNAJfKUBCkYbHp FNSgIfGBJ1pmCUxekoWO4gi+DtGtgCvOU8XSN3l2ywSjnfSee+i2ln/gpWJeLZl6 OUPhbXmQtEikJkeLWMjmZWXMDZCIlVEtRQ+keJWJZI05cyFBYNVCfRno0DDhgZaJ veZEjXCyyXcCLzWuBcQ== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3vw27nbj7e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 28 Jan 2024 21:03:19 -0800 (PST) Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Sun, 28 Jan 2024 21:03:16 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Sun, 28 Jan 2024 21:03:16 -0800 Received: from ubuntu-PowerEdge-T110-II.sclab.marvell.com (unknown [10.106.27.86]) by maili.marvell.com (Postfix) with ESMTP id 224775B6941; Sun, 28 Jan 2024 21:03:16 -0800 (PST) From: Shinas Rasheed To: , CC: , , , , , , , , , , , , Veerasenareddy Burru , Satananda Burla , "David S. Miller" , Eric Dumazet Subject: [PATCH net-next v5 2/8] octeon_ep_vf: add hardware configuration APIs Date: Sun, 28 Jan 2024 21:02:48 -0800 Message-ID: <20240129050254.3047778-3-srasheed@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240129050254.3047778-1-srasheed@marvell.com> References: <20240129050254.3047778-1-srasheed@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: fmrM3TUBbFiZ_12dObKPIfBtUYrltkNc X-Proofpoint-GUID: fmrM3TUBbFiZ_12dObKPIfBtUYrltkNc X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-01-29_02,2024-01-25_01,2023-05-22_02 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789400106551664511 X-GMAIL-MSGID: 1789400106551664511 Implement hardware resource init and shutdown helper APIs, like hardware Tx/Rx queue init/enable/disable/reset. Signed-off-by: Shinas Rasheed --- V5: - Changed unchecked int return type of functions to void and removed unnecessary initializations. V4: https://lore.kernel.org/all/20240108124213.2966536-3-srasheed@marvell.com/ - No changes V3: https://lore.kernel.org/all/20240105203823.2953604-3-srasheed@marvell.com/ - Replaced masks and ULL declarations with GENMASK_ULL(), ULL() and other linux/bits.h macros - Corrected declarations to conform to xmas tree format V2: https://lore.kernel.org/all/20231223134000.2906144-3-srasheed@marvell.com/ - No changes V1: https://lore.kernel.org/all/20231221092844.2885872-3-srasheed@marvell.com/ .../marvell/octeon_ep_vf/octep_vf_cn9k.c | 336 ++++++++++++++++- .../marvell/octeon_ep_vf/octep_vf_cnxk.c | 346 +++++++++++++++++- 2 files changed, 680 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c index c24ef2265205..91fed3390bab 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c @@ -13,9 +13,125 @@ #include "octep_vf_main.h" #include "octep_vf_regs_cn9k.h" +/* Dump useful hardware IQ/OQ CSRs for debug purpose */ +static void cn93_vf_dump_q_regs(struct octep_vf_device *oct, int qno) +{ + struct device *dev = &oct->pdev->dev; + + dev_info(dev, "IQ-%d register dump\n", qno); + dev_info(dev, "R[%d]_IN_INSTR_DBELL[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_IN_INSTR_DBELL(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_INSTR_DBELL(qno))); + dev_info(dev, "R[%d]_IN_CONTROL[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_IN_CONTROL(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_CONTROL(qno))); + dev_info(dev, "R[%d]_IN_ENABLE[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_IN_ENABLE(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_ENABLE(qno))); + dev_info(dev, "R[%d]_IN_INSTR_BADDR[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_IN_INSTR_BADDR(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_INSTR_BADDR(qno))); + dev_info(dev, "R[%d]_IN_INSTR_RSIZE[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_IN_INSTR_RSIZE(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_INSTR_RSIZE(qno))); + dev_info(dev, "R[%d]_IN_CNTS[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_IN_CNTS(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_CNTS(qno))); + dev_info(dev, "R[%d]_IN_INT_LEVELS[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_IN_INT_LEVELS(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(qno))); + dev_info(dev, "R[%d]_IN_PKT_CNT[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_IN_PKT_CNT(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_PKT_CNT(qno))); + dev_info(dev, "R[%d]_IN_BYTE_CNT[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_IN_BYTE_CNT(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_BYTE_CNT(qno))); + + dev_info(dev, "OQ-%d register dump\n", qno); + dev_info(dev, "R[%d]_OUT_SLIST_DBELL[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_OUT_SLIST_DBELL(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_SLIST_DBELL(qno))); + dev_info(dev, "R[%d]_OUT_CONTROL[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_OUT_CONTROL(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_CONTROL(qno))); + dev_info(dev, "R[%d]_OUT_ENABLE[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_OUT_ENABLE(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_ENABLE(qno))); + dev_info(dev, "R[%d]_OUT_SLIST_BADDR[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_OUT_SLIST_BADDR(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_SLIST_BADDR(qno))); + dev_info(dev, "R[%d]_OUT_SLIST_RSIZE[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_OUT_SLIST_RSIZE(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_SLIST_RSIZE(qno))); + dev_info(dev, "R[%d]_OUT_CNTS[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_OUT_CNTS(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_CNTS(qno))); + dev_info(dev, "R[%d]_OUT_INT_LEVELS[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_OUT_INT_LEVELS(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(qno))); + dev_info(dev, "R[%d]_OUT_PKT_CNT[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_OUT_PKT_CNT(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_PKT_CNT(qno))); + dev_info(dev, "R[%d]_OUT_BYTE_CNT[0x%llx]: 0x%016llx\n", + qno, CN93_VF_SDP_R_OUT_BYTE_CNT(qno), + octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_BYTE_CNT(qno))); +} + +/* Reset Hardware Tx queue */ +static void cn93_vf_reset_iq(struct octep_vf_device *oct, int q_no) +{ + u64 val = ULL(0); + + dev_dbg(&oct->pdev->dev, "Reset VF IQ-%d\n", q_no); + + /* Disable the Tx/Instruction Ring */ + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_ENABLE(q_no), val); + + /* clear the Instruction Ring packet/byte counts and doorbell CSRs */ + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(q_no), val); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_PKT_CNT(q_no), val); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_BYTE_CNT(q_no), val); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INSTR_BADDR(q_no), val); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INSTR_RSIZE(q_no), val); + + val = GENMASK_ULL(31, 0); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INSTR_DBELL(q_no), val); + + val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_CNTS(q_no)); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_CNTS(q_no), + val & GENMASK_ULL(31, 0)); + + return; +} + +/* Reset Hardware Rx queue */ +static void cn93_vf_reset_oq(struct octep_vf_device *oct, int q_no) +{ + u64 val = ULL(0); + + /* Disable Output (Rx) Ring */ + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_ENABLE(q_no), val); + + /* Clear count CSRs */ + val = octep_vf_read_csr(oct, CN93_VF_SDP_R_OUT_CNTS(q_no)); + octep_vf_write_csr(oct, CN93_VF_SDP_R_OUT_CNTS(q_no), val); + + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_PKT_CNT(q_no), GENMASK_ULL(35, 0)); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_SLIST_DBELL(q_no), GENMASK_ULL(31, 0)); +} + /* Reset all hardware Tx/Rx queues */ static void octep_vf_reset_io_queues_cn93(struct octep_vf_device *oct) { + struct pci_dev *pdev = oct->pdev; + int q; + + dev_dbg(&pdev->dev, "Reset OCTEP_CN93 VF IO Queues\n"); + + for (q = 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { + cn93_vf_reset_iq(oct, q); + cn93_vf_reset_oq(oct, q); + } } /* Initialize configuration limits and initial active config */ @@ -46,78 +162,296 @@ static void octep_vf_init_config_cn93_vf(struct octep_vf_device *oct) /* Setup registers for a hardware Tx Queue */ static void octep_vf_setup_iq_regs_cn93(struct octep_vf_device *oct, int iq_no) { + struct octep_vf_iq *iq = oct->iq[iq_no]; + u32 reset_instr_cnt; + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_CONTROL(iq_no)); + + /* wait for IDLE to set to 1 */ + if (!(reg_val & CN93_VF_R_IN_CTL_IDLE)) { + do { + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_CONTROL(iq_no)); + } while (!(reg_val & CN93_VF_R_IN_CTL_IDLE)); + } + reg_val |= CN93_VF_R_IN_CTL_RDSIZE; + reg_val |= CN93_VF_R_IN_CTL_IS_64B; + reg_val |= CN93_VF_R_IN_CTL_ESR; + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_CONTROL(iq_no), reg_val); + + /* Write the start of the input queue's ring and its size */ + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INSTR_BADDR(iq_no), iq->desc_ring_dma); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INSTR_RSIZE(iq_no), iq->max_count); + + /* Remember the doorbell & instruction count register addr for this queue */ + iq->doorbell_reg = oct->mmio.hw_addr + CN93_VF_SDP_R_IN_INSTR_DBELL(iq_no); + iq->inst_cnt_reg = oct->mmio.hw_addr + CN93_VF_SDP_R_IN_CNTS(iq_no); + iq->intr_lvl_reg = oct->mmio.hw_addr + CN93_VF_SDP_R_IN_INT_LEVELS(iq_no); + + /* Store the current instruction counter (used in flush_iq calculation) */ + reset_instr_cnt = readl(iq->inst_cnt_reg); + writel(reset_instr_cnt, iq->inst_cnt_reg); + + /* INTR_THRESHOLD is set to max(FFFFFFFF) to disable the INTR */ + reg_val = CFG_GET_IQ_INTR_THRESHOLD(oct->conf) & GENMASK_ULL(31, 0); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(iq_no), reg_val); } /* Setup registers for a hardware Rx Queue */ static void octep_vf_setup_oq_regs_cn93(struct octep_vf_device *oct, int oq_no) { + struct octep_vf_oq *oq = oct->oq[oq_no]; + u32 time_threshold = 0; + u64 oq_ctl = ULL(0); + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_CONTROL(oq_no)); + + /* wait for IDLE to set to 1 */ + if (!(reg_val & CN93_VF_R_OUT_CTL_IDLE)) { + do { + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_CONTROL(oq_no)); + } while (!(reg_val & CN93_VF_R_OUT_CTL_IDLE)); + } + + reg_val &= ~(CN93_VF_R_OUT_CTL_IMODE); + reg_val &= ~(CN93_VF_R_OUT_CTL_ROR_P); + reg_val &= ~(CN93_VF_R_OUT_CTL_NSR_P); + reg_val &= ~(CN93_VF_R_OUT_CTL_ROR_I); + reg_val &= ~(CN93_VF_R_OUT_CTL_NSR_I); + reg_val &= ~(CN93_VF_R_OUT_CTL_ES_I); + reg_val &= ~(CN93_VF_R_OUT_CTL_ROR_D); + reg_val &= ~(CN93_VF_R_OUT_CTL_NSR_D); + reg_val &= ~(CN93_VF_R_OUT_CTL_ES_D); + reg_val |= (CN93_VF_R_OUT_CTL_ES_P); + + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_CONTROL(oq_no), reg_val); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_SLIST_BADDR(oq_no), oq->desc_ring_dma); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_SLIST_RSIZE(oq_no), oq->max_count); + + oq_ctl = octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_CONTROL(oq_no)); + oq_ctl &= ~GENMASK_ULL(22, 0); //clear the ISIZE and BSIZE (22-0) + oq_ctl |= (oq->buffer_size & GENMASK_ULL(15, 0)); //populate the BSIZE (15-0) + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_CONTROL(oq_no), oq_ctl); + + /* Get the mapped address of the pkt_sent and pkts_credit regs */ + oq->pkts_sent_reg = oct->mmio.hw_addr + CN93_VF_SDP_R_OUT_CNTS(oq_no); + oq->pkts_credit_reg = oct->mmio.hw_addr + CN93_VF_SDP_R_OUT_SLIST_DBELL(oq_no); + + time_threshold = CFG_GET_OQ_INTR_TIME(oct->conf); + reg_val = ((u64)time_threshold << 32) | CFG_GET_OQ_INTR_PKT(oct->conf); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(oq_no), reg_val); } /* Setup registers for a VF mailbox */ static void octep_vf_setup_mbox_regs_cn93(struct octep_vf_device *oct, int q_no) { + struct octep_vf_mbox *mbox = oct->mbox; + + /* PF to VF DATA reg. VF reads from this reg */ + mbox->mbox_read_reg = oct->mmio.hw_addr + CN93_VF_SDP_R_MBOX_PF_VF_DATA(q_no); + + /* VF mbox interrupt reg */ + mbox->mbox_int_reg = oct->mmio.hw_addr + CN93_VF_SDP_R_MBOX_PF_VF_INT(q_no); + + /* VF to PF DATA reg. VF writes into this reg */ + mbox->mbox_write_reg = oct->mmio.hw_addr + CN93_VF_SDP_R_MBOX_VF_PF_DATA(q_no); +} + +/* Mailbox Interrupt handler */ +static void cn93_handle_vf_mbox_intr(struct octep_vf_device *oct) +{ + if (oct->mbox) + schedule_work(&oct->mbox->wk.work); + else + dev_err(&oct->pdev->dev, "cannot schedule work on invalid mbox\n"); } /* Tx/Rx queue interrupt handler */ static irqreturn_t octep_vf_ioq_intr_handler_cn93(void *data) { + struct octep_vf_ioq_vector *vector = data; + struct octep_vf_device *oct; + struct octep_vf_oq *oq; + u64 reg_val; + + oct = vector->octep_vf_dev; + oq = vector->oq; + /* Mailbox interrupt arrives along with interrupt of tx/rx ring pair 0 */ + if (oq->q_no == 0) { + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_MBOX_PF_VF_INT(0)); + if (reg_val & CN93_VF_SDP_R_MBOX_PF_VF_INT_STATUS) { + cn93_handle_vf_mbox_intr(oct); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_MBOX_PF_VF_INT(0), reg_val); + } + } + napi_schedule_irqoff(oq->napi); return IRQ_HANDLED; } /* Re-initialize Octeon hardware registers */ static void octep_vf_reinit_regs_cn93(struct octep_vf_device *oct) { + u32 i; + + for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) + oct->hw_ops.setup_iq_regs(oct, i); + + for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) + oct->hw_ops.setup_oq_regs(oct, i); + + oct->hw_ops.enable_interrupts(oct); + oct->hw_ops.enable_io_queues(oct); + + for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) + writel(oct->oq[i]->max_count, oct->oq[i]->pkts_credit_reg); } /* Enable all interrupts */ static void octep_vf_enable_interrupts_cn93(struct octep_vf_device *oct) { + int num_rings, q; + u64 reg_val; + + num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + for (q = 0; q < num_rings; q++) { + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(q)); + reg_val |= BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(q), reg_val); + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(q)); + reg_val |= BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(q), reg_val); + } + /* Enable PF to VF mbox interrupt by setting 2nd bit*/ + octep_vf_write_csr64(oct, CN93_VF_SDP_R_MBOX_PF_VF_INT(0), + CN93_VF_SDP_R_MBOX_PF_VF_INT_ENAB); } /* Disable all interrupts */ static void octep_vf_disable_interrupts_cn93(struct octep_vf_device *oct) { + int num_rings, q; + u64 reg_val; + + /* Disable PF to VF mbox interrupt by setting 2nd bit*/ + if (oct->mbox) + octep_vf_write_csr64(oct, CN93_VF_SDP_R_MBOX_PF_VF_INT(0), 0x0); + + num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + for (q = 0; q < num_rings; q++) { + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(q)); + reg_val &= ~BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(q), reg_val); + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(q)); + reg_val &= ~BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(q), reg_val); + } } /* Get new Octeon Read Index: index of descriptor that Octeon reads next. */ static u32 octep_vf_update_iq_read_index_cn93(struct octep_vf_iq *iq) { - return 0; + u32 pkt_in_done = readl(iq->inst_cnt_reg); + u32 last_done, new_idx; + + last_done = pkt_in_done - iq->pkt_in_done; + iq->pkt_in_done = pkt_in_done; + + new_idx = (iq->octep_vf_read_index + last_done) % iq->max_count; + + return new_idx; } /* Enable a hardware Tx Queue */ static void octep_vf_enable_iq_cn93(struct octep_vf_device *oct, int iq_no) { + u64 loop = HZ; + u64 reg_val; + + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INSTR_DBELL(iq_no), GENMASK_ULL(31, 0)); + + while (octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_INSTR_DBELL(iq_no)) && + loop--) { + schedule_timeout_interruptible(1); + } + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(iq_no)); + reg_val |= BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(iq_no), reg_val); + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_ENABLE(iq_no)); + reg_val |= ULL(1); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_ENABLE(iq_no), reg_val); } /* Enable a hardware Rx Queue */ static void octep_vf_enable_oq_cn93(struct octep_vf_device *oct, int oq_no) { + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(oq_no)); + reg_val |= BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(oq_no), reg_val); + + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_SLIST_DBELL(oq_no), GENMASK_ULL(31, 0)); + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_ENABLE(oq_no)); + reg_val |= ULL(1); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_ENABLE(oq_no), reg_val); } /* Enable all hardware Tx/Rx Queues assigned to VF */ static void octep_vf_enable_io_queues_cn93(struct octep_vf_device *oct) { + u8 q; + + for (q = 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { + octep_vf_enable_iq_cn93(oct, q); + octep_vf_enable_oq_cn93(oct, q); + } } /* Disable a hardware Tx Queue assigned to VF */ static void octep_vf_disable_iq_cn93(struct octep_vf_device *oct, int iq_no) { + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_ENABLE(iq_no)); + reg_val &= ~ULL(1); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_ENABLE(iq_no), reg_val); } /* Disable a hardware Rx Queue assigned to VF */ static void octep_vf_disable_oq_cn93(struct octep_vf_device *oct, int oq_no) { + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_ENABLE(oq_no)); + reg_val &= ~ULL(1); + octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_ENABLE(oq_no), reg_val); } /* Disable all hardware Tx/Rx Queues assigned to VF */ static void octep_vf_disable_io_queues_cn93(struct octep_vf_device *oct) { + int q; + + for (q = 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { + octep_vf_disable_iq_cn93(oct, q); + octep_vf_disable_oq_cn93(oct, q); + } } /* Dump hardware registers (including Tx/Rx queues) for debugging. */ static void octep_vf_dump_registers_cn93(struct octep_vf_device *oct) { + u8 num_rings, q; + + num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + for (q = 0; q < num_rings; q++) + cn93_vf_dump_q_regs(oct, q); } /** diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cnxk.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cnxk.c index af07a4a6edc5..4c7da12ba43b 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cnxk.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cnxk.c @@ -13,9 +13,127 @@ #include "octep_vf_main.h" #include "octep_vf_regs_cnxk.h" +/* Dump useful hardware IQ/OQ CSRs for debug purpose */ +static void cnxk_vf_dump_q_regs(struct octep_vf_device *oct, int qno) +{ + struct device *dev = &oct->pdev->dev; + + dev_info(dev, "IQ-%d register dump\n", qno); + dev_info(dev, "R[%d]_IN_INSTR_DBELL[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_IN_INSTR_DBELL(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_INSTR_DBELL(qno))); + dev_info(dev, "R[%d]_IN_CONTROL[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_IN_CONTROL(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_CONTROL(qno))); + dev_info(dev, "R[%d]_IN_ENABLE[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_IN_ENABLE(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_ENABLE(qno))); + dev_info(dev, "R[%d]_IN_INSTR_BADDR[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_IN_INSTR_BADDR(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_INSTR_BADDR(qno))); + dev_info(dev, "R[%d]_IN_INSTR_RSIZE[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_IN_INSTR_RSIZE(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_INSTR_RSIZE(qno))); + dev_info(dev, "R[%d]_IN_CNTS[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_IN_CNTS(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_CNTS(qno))); + dev_info(dev, "R[%d]_IN_INT_LEVELS[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_IN_INT_LEVELS(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_INT_LEVELS(qno))); + dev_info(dev, "R[%d]_IN_PKT_CNT[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_IN_PKT_CNT(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_PKT_CNT(qno))); + dev_info(dev, "R[%d]_IN_BYTE_CNT[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_IN_BYTE_CNT(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_BYTE_CNT(qno))); + + dev_info(dev, "OQ-%d register dump\n", qno); + dev_info(dev, "R[%d]_OUT_SLIST_DBELL[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_OUT_SLIST_DBELL(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_DBELL(qno))); + dev_info(dev, "R[%d]_OUT_CONTROL[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_OUT_CONTROL(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(qno))); + dev_info(dev, "R[%d]_OUT_ENABLE[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_OUT_ENABLE(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_ENABLE(qno))); + dev_info(dev, "R[%d]_OUT_SLIST_BADDR[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_OUT_SLIST_BADDR(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_BADDR(qno))); + dev_info(dev, "R[%d]_OUT_SLIST_RSIZE[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_OUT_SLIST_RSIZE(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_RSIZE(qno))); + dev_info(dev, "R[%d]_OUT_CNTS[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_OUT_CNTS(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CNTS(qno))); + dev_info(dev, "R[%d]_OUT_INT_LEVELS[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_OUT_INT_LEVELS(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_INT_LEVELS(qno))); + dev_info(dev, "R[%d]_OUT_PKT_CNT[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_OUT_PKT_CNT(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_PKT_CNT(qno))); + dev_info(dev, "R[%d]_OUT_BYTE_CNT[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_OUT_BYTE_CNT(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_BYTE_CNT(qno))); + dev_info(dev, "R[%d]_ERR_TYPE[0x%llx]: 0x%016llx\n", + qno, CNXK_VF_SDP_R_ERR_TYPE(qno), + octep_vf_read_csr64(oct, CNXK_VF_SDP_R_ERR_TYPE(qno))); +} + +/* Reset Hardware Tx queue */ +static void cnxk_vf_reset_iq(struct octep_vf_device *oct, int q_no) +{ + u64 val = ULL(0); + + dev_dbg(&oct->pdev->dev, "Reset VF IQ-%d\n", q_no); + + /* Disable the Tx/Instruction Ring */ + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_ENABLE(q_no), val); + + /* clear the Instruction Ring packet/byte counts and doorbell CSRs */ + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INT_LEVELS(q_no), val); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_PKT_CNT(q_no), val); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_BYTE_CNT(q_no), val); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INSTR_BADDR(q_no), val); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INSTR_RSIZE(q_no), val); + + val = GENMASK_ULL(31, 0); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INSTR_DBELL(q_no), val); + + val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_CNTS(q_no)); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_CNTS(q_no), val & GENMASK_ULL(31, 0)); + + return; +} + +/* Reset Hardware Rx queue */ +static void cnxk_vf_reset_oq(struct octep_vf_device *oct, int q_no) +{ + u64 val = ULL(0); + + /* Disable Output (Rx) Ring */ + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_ENABLE(q_no), val); + + /* Clear count CSRs */ + val = octep_vf_read_csr(oct, CNXK_VF_SDP_R_OUT_CNTS(q_no)); + octep_vf_write_csr(oct, CNXK_VF_SDP_R_OUT_CNTS(q_no), val); + + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_PKT_CNT(q_no), GENMASK_ULL(35, 0)); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_DBELL(q_no), GENMASK_ULL(31, 0)); +} + /* Reset all hardware Tx/Rx queues */ static void octep_vf_reset_io_queues_cnxk(struct octep_vf_device *oct) { + struct pci_dev *pdev = oct->pdev; + int q; + + dev_dbg(&pdev->dev, "Reset OCTEP_CNXK VF IO Queues\n"); + + for (q = 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { + cnxk_vf_reset_iq(oct, q); + cnxk_vf_reset_oq(oct, q); + } } /* Initialize configuration limits and initial active config */ @@ -47,78 +165,304 @@ static void octep_vf_init_config_cnxk_vf(struct octep_vf_device *oct) /* Setup registers for a hardware Tx Queue */ static void octep_vf_setup_iq_regs_cnxk(struct octep_vf_device *oct, int iq_no) { + struct octep_vf_iq *iq = oct->iq[iq_no]; + u32 reset_instr_cnt; + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_CONTROL(iq_no)); + + /* wait for IDLE to set to 1 */ + if (!(reg_val & CNXK_VF_R_IN_CTL_IDLE)) { + do { + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_CONTROL(iq_no)); + } while (!(reg_val & CNXK_VF_R_IN_CTL_IDLE)); + } + reg_val |= CNXK_VF_R_IN_CTL_RDSIZE; + reg_val |= CNXK_VF_R_IN_CTL_IS_64B; + reg_val |= CNXK_VF_R_IN_CTL_ESR; + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_CONTROL(iq_no), reg_val); + + /* Write the start of the input queue's ring and its size */ + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INSTR_BADDR(iq_no), iq->desc_ring_dma); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INSTR_RSIZE(iq_no), iq->max_count); + + /* Remember the doorbell & instruction count register addr for this queue */ + iq->doorbell_reg = oct->mmio.hw_addr + CNXK_VF_SDP_R_IN_INSTR_DBELL(iq_no); + iq->inst_cnt_reg = oct->mmio.hw_addr + CNXK_VF_SDP_R_IN_CNTS(iq_no); + iq->intr_lvl_reg = oct->mmio.hw_addr + CNXK_VF_SDP_R_IN_INT_LEVELS(iq_no); + + /* Store the current instruction counter (used in flush_iq calculation) */ + reset_instr_cnt = readl(iq->inst_cnt_reg); + writel(reset_instr_cnt, iq->inst_cnt_reg); + + /* INTR_THRESHOLD is set to max(FFFFFFFF) to disable the INTR */ + reg_val = CFG_GET_IQ_INTR_THRESHOLD(oct->conf) & GENMASK_ULL(31, 0); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INT_LEVELS(iq_no), reg_val); } /* Setup registers for a hardware Rx Queue */ static void octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no) { + struct octep_vf_oq *oq = oct->oq[oq_no]; + u32 time_threshold = 0; + u64 oq_ctl = ULL(0); + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no)); + + /* wait for IDLE to set to 1 */ + if (!(reg_val & CNXK_VF_R_OUT_CTL_IDLE)) { + do { + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no)); + } while (!(reg_val & CNXK_VF_R_OUT_CTL_IDLE)); + } + + reg_val &= ~(CNXK_VF_R_OUT_CTL_IMODE); + reg_val &= ~(CNXK_VF_R_OUT_CTL_ROR_P); + reg_val &= ~(CNXK_VF_R_OUT_CTL_NSR_P); + reg_val &= ~(CNXK_VF_R_OUT_CTL_ROR_I); + reg_val &= ~(CNXK_VF_R_OUT_CTL_NSR_I); + reg_val &= ~(CNXK_VF_R_OUT_CTL_ES_I); + reg_val &= ~(CNXK_VF_R_OUT_CTL_ROR_D); + reg_val &= ~(CNXK_VF_R_OUT_CTL_NSR_D); + reg_val &= ~(CNXK_VF_R_OUT_CTL_ES_D); + reg_val |= (CNXK_VF_R_OUT_CTL_ES_P); + + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no), reg_val); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_BADDR(oq_no), oq->desc_ring_dma); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_RSIZE(oq_no), oq->max_count); + + oq_ctl = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no)); + /* Clear the ISIZE and BSIZE (22-0) */ + oq_ctl &= ~GENMASK_ULL(22, 0); + /* Populate the BSIZE (15-0) */ + oq_ctl |= (oq->buffer_size & GENMASK_ULL(15, 0)); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no), oq_ctl); + + /* Get the mapped address of the pkt_sent and pkts_credit regs */ + oq->pkts_sent_reg = oct->mmio.hw_addr + CNXK_VF_SDP_R_OUT_CNTS(oq_no); + oq->pkts_credit_reg = oct->mmio.hw_addr + CNXK_VF_SDP_R_OUT_SLIST_DBELL(oq_no); + + time_threshold = CFG_GET_OQ_INTR_TIME(oct->conf); + reg_val = ((u64)time_threshold << 32) | CFG_GET_OQ_INTR_PKT(oct->conf); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_INT_LEVELS(oq_no), reg_val); + + /* set watermark for backpressure */ + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_WMARK(oq_no)); + reg_val &= ~GENMASK_ULL(31, 0); + reg_val |= CFG_GET_OQ_WMARK(oct->conf); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_WMARK(oq_no), reg_val); } /* Setup registers for a VF mailbox */ static void octep_vf_setup_mbox_regs_cnxk(struct octep_vf_device *oct, int q_no) { + struct octep_vf_mbox *mbox = oct->mbox; + + /* PF to VF DATA reg. VF reads from this reg */ + mbox->mbox_read_reg = oct->mmio.hw_addr + CNXK_VF_SDP_R_MBOX_PF_VF_DATA(q_no); + + /* VF mbox interrupt reg */ + mbox->mbox_int_reg = oct->mmio.hw_addr + CNXK_VF_SDP_R_MBOX_PF_VF_INT(q_no); + + /* VF to PF DATA reg. VF writes into this reg */ + mbox->mbox_write_reg = oct->mmio.hw_addr + CNXK_VF_SDP_R_MBOX_VF_PF_DATA(q_no); +} + +/* Mailbox Interrupt handler */ +static void cnxk_handle_vf_mbox_intr(struct octep_vf_device *oct) +{ + if (oct->mbox) + schedule_work(&oct->mbox->wk.work); + else + dev_err(&oct->pdev->dev, "cannot schedule work on invalid mbox\n"); } /* Tx/Rx queue interrupt handler */ static irqreturn_t octep_vf_ioq_intr_handler_cnxk(void *data) { + struct octep_vf_ioq_vector *vector = data; + struct octep_vf_device *oct; + struct octep_vf_oq *oq; + u64 reg_val; + + oct = vector->octep_vf_dev; + oq = vector->oq; + /* Mailbox interrupt arrives along with interrupt of tx/rx ring pair 0 */ + if (oq->q_no == 0) { + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_MBOX_PF_VF_INT(0)); + if (reg_val & CNXK_VF_SDP_R_MBOX_PF_VF_INT_STATUS) { + cnxk_handle_vf_mbox_intr(oct); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_MBOX_PF_VF_INT(0), reg_val); + } + } + napi_schedule_irqoff(oq->napi); return IRQ_HANDLED; } /* Re-initialize Octeon hardware registers */ static void octep_vf_reinit_regs_cnxk(struct octep_vf_device *oct) { + u32 i; + + for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) + oct->hw_ops.setup_iq_regs(oct, i); + + for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) + oct->hw_ops.setup_oq_regs(oct, i); + + oct->hw_ops.enable_interrupts(oct); + oct->hw_ops.enable_io_queues(oct); + + for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) + writel(oct->oq[i]->max_count, oct->oq[i]->pkts_credit_reg); } /* Enable all interrupts */ static void octep_vf_enable_interrupts_cnxk(struct octep_vf_device *oct) { + int num_rings, q; + u64 reg_val; + + num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + for (q = 0; q < num_rings; q++) { + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_INT_LEVELS(q)); + reg_val |= BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INT_LEVELS(q), reg_val); + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_INT_LEVELS(q)); + reg_val |= BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_INT_LEVELS(q), reg_val); + } + /* Enable PF to VF mbox interrupt by setting 2nd bit*/ + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_MBOX_PF_VF_INT(0), + CNXK_VF_SDP_R_MBOX_PF_VF_INT_ENAB); } /* Disable all interrupts */ static void octep_vf_disable_interrupts_cnxk(struct octep_vf_device *oct) { + int num_rings, q; + u64 reg_val; + + /* Disable PF to VF mbox interrupt by setting 2nd bit*/ + if (oct->mbox) + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_MBOX_PF_VF_INT(0), 0x0); + + num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + for (q = 0; q < num_rings; q++) { + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_INT_LEVELS(q)); + reg_val &= ~BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INT_LEVELS(q), reg_val); + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_INT_LEVELS(q)); + reg_val &= ~BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_INT_LEVELS(q), reg_val); + } } /* Get new Octeon Read Index: index of descriptor that Octeon reads next. */ static u32 octep_vf_update_iq_read_index_cnxk(struct octep_vf_iq *iq) { - return 0; + u32 pkt_in_done = readl(iq->inst_cnt_reg); + u32 last_done, new_idx; + + last_done = pkt_in_done - iq->pkt_in_done; + iq->pkt_in_done = pkt_in_done; + + new_idx = (iq->octep_vf_read_index + last_done) % iq->max_count; + + return new_idx; } /* Enable a hardware Tx Queue */ static void octep_vf_enable_iq_cnxk(struct octep_vf_device *oct, int iq_no) { + u64 loop = HZ; + u64 reg_val; + + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INSTR_DBELL(iq_no), GENMASK_ULL(31, 0)); + + while (octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_INSTR_DBELL(iq_no)) && + loop--) { + schedule_timeout_interruptible(1); + } + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_INT_LEVELS(iq_no)); + reg_val |= BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_INT_LEVELS(iq_no), reg_val); + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_ENABLE(iq_no)); + reg_val |= ULL(1); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_ENABLE(iq_no), reg_val); } /* Enable a hardware Rx Queue */ static void octep_vf_enable_oq_cnxk(struct octep_vf_device *oct, int oq_no) { + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_INT_LEVELS(oq_no)); + reg_val |= BIT_ULL_MASK(62); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_INT_LEVELS(oq_no), reg_val); + + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_DBELL(oq_no), GENMASK_ULL(31, 0)); + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_ENABLE(oq_no)); + reg_val |= ULL(1); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_ENABLE(oq_no), reg_val); } /* Enable all hardware Tx/Rx Queues assigned to VF */ static void octep_vf_enable_io_queues_cnxk(struct octep_vf_device *oct) { + u8 q; + + for (q = 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { + octep_vf_enable_iq_cnxk(oct, q); + octep_vf_enable_oq_cnxk(oct, q); + } } /* Disable a hardware Tx Queue assigned to VF */ static void octep_vf_disable_iq_cnxk(struct octep_vf_device *oct, int iq_no) { + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_IN_ENABLE(iq_no)); + reg_val &= ~ULL(1); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_IN_ENABLE(iq_no), reg_val); } /* Disable a hardware Rx Queue assigned to VF */ static void octep_vf_disable_oq_cnxk(struct octep_vf_device *oct, int oq_no) { + u64 reg_val; + + reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_ENABLE(oq_no)); + reg_val &= ~ULL(1); + octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_ENABLE(oq_no), reg_val); } /* Disable all hardware Tx/Rx Queues assigned to VF */ static void octep_vf_disable_io_queues_cnxk(struct octep_vf_device *oct) { + int q; + + for (q = 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { + octep_vf_disable_iq_cnxk(oct, q); + octep_vf_disable_oq_cnxk(oct, q); + } } /* Dump hardware registers (including Tx/Rx queues) for debugging. */ static void octep_vf_dump_registers_cnxk(struct octep_vf_device *oct) { + u8 num_rings, q; + + num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + for (q = 0; q < num_rings; q++) + cnxk_vf_dump_q_regs(oct, q); } /** From patchwork Mon Jan 29 05:02:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shinas Rasheed X-Patchwork-Id: 193234 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2087:b0:106:209c:c626 with SMTP id gs7csp366168dyb; Sun, 28 Jan 2024 21:04:39 -0800 (PST) X-Google-Smtp-Source: AGHT+IGjUtClRPxHaIlxrpOf9mlJy9RAdT2fZD7TKObrcauaaDw+C2EHiYNDNclrOvc3ieYW+/lG X-Received: by 2002:a17:906:b741:b0:a30:3863:333d with SMTP id fx1-20020a170906b74100b00a303863333dmr3229422ejb.75.1706504679238; Sun, 28 Jan 2024 21:04:39 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706504679; cv=pass; d=google.com; s=arc-20160816; b=0kiZs3pT7ZwhcvbHjrS4tHaJX2k6qe9SYhS/pHDu4Et7i0D8J6AZkz35xjM2PBDIA4 ubvmp35UPX8h7RLpjJlP+q6Sf5lW1j9JvF/repm7rd1lL0gHSt6AmRzU3kUPRMW2HinC sGIQj7b7ZXgGrbP4qBvXWmID4oFlRu4UPu2Kw+yvtRmNIByr8EH79M/jWEvC1J2umqon 5v1dSGoy38bgdB1fYkWGd9Woj5CeUwbMDrxkyIx57xpFwdtz/7dDTF2RvVm5NQp/xadE osAOJ/j0rUyGRmsB+hNAa4BM3meHmrkJ2C1BWOnqmAOC5VjQ5T7ocRL9fvcVc57m1eul oBqQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=iTO/bu6e0y1QCBXzgrY5JDdTtrHRcWbJU9mlyM03dXw=; fh=Y/Zcr0YXYeEsWchgSSogMl8sJJcf/EqHGWMcPJ+i19E=; b=NYnAmOxBlWZYjf6vSeJSkyhtOv2dSbIeYXihUYnUxPbtOD4YpFYmt39D3FWwE5sRNL G+QxA+EN/qsdbQtyUePZnGrWuC7jlAbYdSDT4QtO9ND7y1nZxAn9o2uGofBVZZEdHjp3 gMFzoESi2iPNKU/AVurMLUaSW/MdhvzwTpiPw9LqWAuMPcBIXeu0oRfJV4SUUQinnZzq cCWTfPVNdCiLReGbYdocs1pTTB2i0fKSgter/knEQCG0UjSROKF3j1qhfEsfz+yjry0H DUDfzQ++a+Wu83+iBTg8nHEsBmDmNBSH/KPMIAyiIimksIYlZS0bHDLo+h18yjXBjtAQ sd6g== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=GRPbhCzx; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42166-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42166-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id w24-20020a1709067c9800b00a349fd53d0bsi3043642ejo.66.2024.01.28.21.04.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Jan 2024 21:04:39 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-42166-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) client-ip=2604:1380:4601:e00::3; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=GRPbhCzx; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42166-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42166-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id A3A2E1F237ED for ; Mon, 29 Jan 2024 05:04:38 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4A74F4CB58; Mon, 29 Jan 2024 05:03:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="GRPbhCzx" Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 367013C68E; Mon, 29 Jan 2024 05:03:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.148.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504614; cv=none; b=nl2SVwV2RNOtxYcjcfljaycQWhD8BCY2ozwNnmTQDaeJr+/tE2PfcYahOgZnMADzSjprAvsSZDktTuAEdvdWc/lAfprp73oHmv8Z6g1WvaAJeTFJD2U3AsAgyix4hY+GsFW7C2tBddE2g5jhtiG6oqIroRFGvmdl2E6njXbKZho= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504614; c=relaxed/simple; bh=P2vY3RR76uxU+rypc2+2JdC1WU0b6PubWScp4Xo9h9M=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KlVmjphF8AvKbZyg8eRf2203E9211vQMtpFLbYy5LqGbaPBgubZdWgEBUVrP0Jr1jUaHwdxxFk1A4fG/ihgyb3dJlv0vkNaomHVMPs1kH9YIo+PW33QBPsbIwueGtdaHYSI0KFabgJlAxeaJ8/c0+LrF8zy+FAgl79KClNlGWco= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com; spf=pass smtp.mailfrom=marvell.com; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b=GRPbhCzx; arc=none smtp.client-ip=67.231.148.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 40T4KEj7027114; Sun, 28 Jan 2024 21:03:21 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=iTO/bu6e0y1QCBXzgrY5JDdTtrHRcWbJU9mlyM03dXw=; b=GRP bhCzxeg85BDimdXZdirOltErAYqE2PdhyRAfSvd8Ad0sTIIkq1rqXSQZS+0jwHoZ /BFCHVvokqrhB25qQKpzI5z39YoCGPXV3X8V+FAr6N1FPOYWt1ejo9x1ps6/gG1/ 4U9oR/1uco9wrFnSh032el+hcrXWQPLJOo1LtwTCyTLCNhlZDYtZ7DQZMnzMEIu5 wQohrWZRFsXBJgftTUFdYg8Zdj+59FIpt/eTiAG+ngXYnQLiqjNwiaQuX4QY8v12 RppgfqFA39aLj6Y+ORvWoLAbx98IkRsf0nOiVXAHMBUorV/qUZs2GJW3Us0viER1 5y+XZJgizHAMt190iIg== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3vx4vr82ct-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 28 Jan 2024 21:03:20 -0800 (PST) Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Sun, 28 Jan 2024 21:03:19 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Sun, 28 Jan 2024 21:03:19 -0800 Received: from ubuntu-PowerEdge-T110-II.sclab.marvell.com (unknown [10.106.27.86]) by maili.marvell.com (Postfix) with ESMTP id B31E93F7045; Sun, 28 Jan 2024 21:03:18 -0800 (PST) From: Shinas Rasheed To: , CC: , , , , , , , , , , , , Veerasenareddy Burru , Satananda Burla , "David S. Miller" , Eric Dumazet Subject: [PATCH net-next v5 3/8] octeon_ep_vf: add VF-PF mailbox communication. Date: Sun, 28 Jan 2024 21:02:49 -0800 Message-ID: <20240129050254.3047778-4-srasheed@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240129050254.3047778-1-srasheed@marvell.com> References: <20240129050254.3047778-1-srasheed@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: EAxaOEdRyJVYgHYlRuYI1qI_7KjpV3YG X-Proofpoint-GUID: EAxaOEdRyJVYgHYlRuYI1qI_7KjpV3YG X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-01-29_02,2024-01-25_01,2023-05-22_02 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789399850563012229 X-GMAIL-MSGID: 1789399850563012229 Implement VF-PF mailbox to send all control commands from VF to PF and receive responses and notifications from PF to VF. Signed-off-by: Shinas Rasheed --- V5: - No changes V4: https://lore.kernel.org/all/20240108124213.2966536-4-srasheed@marvell.com/ - No changes V3: https://lore.kernel.org/all/20240105203823.2953604-4-srasheed@marvell.com/ - No changes V2: https://lore.kernel.org/all/20231223134000.2906144-4-srasheed@marvell.com/ - No changes V1: https://lore.kernel.org/all/20231221092844.2885872-4-srasheed@marvell.com/ .../marvell/octeon_ep_vf/octep_vf_main.c | 103 ++++++ .../marvell/octeon_ep_vf/octep_vf_main.h | 1 + .../marvell/octeon_ep_vf/octep_vf_mbox.c | 336 +++++++++++++++++- .../marvell/octeon_ep_vf/octep_vf_mbox.h | 143 +++++++- 4 files changed, 581 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c index 50a2a13c5f2e..51f92c8223e8 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c @@ -187,6 +187,19 @@ static netdev_tx_t octep_vf_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } +int octep_vf_get_link_info(struct octep_vf_device *oct) +{ + int ret, size; + + ret = octep_vf_mbox_bulk_read(oct, OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO, + (u8 *)&oct->link_info, &size); + if (ret) { + dev_err(&oct->pdev->dev, "Get VF link info failed via VF Mbox\n"); + return ret; + } + return 0; +} + /** * octep_vf_tx_timeout_task - work queue task to Handle Tx queue timeout. * @@ -225,11 +238,84 @@ static void octep_vf_tx_timeout(struct net_device *netdev, unsigned int txqueue) queue_work(octep_vf_wq, &oct->tx_timeout_task); } +static int octep_vf_set_mac(struct net_device *netdev, void *p) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + struct sockaddr *addr = (struct sockaddr *)p; + int err; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + err = octep_vf_mbox_set_mac_addr(oct, addr->sa_data); + if (err) + return err; + + memcpy(oct->mac_addr, addr->sa_data, ETH_ALEN); + eth_hw_addr_set(netdev, addr->sa_data); + + return 0; +} + +static int octep_vf_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + struct octep_vf_iface_link_info *link_info; + int err; + + link_info = &oct->link_info; + if (link_info->mtu == new_mtu) + return 0; + + err = octep_vf_mbox_set_mtu(oct, new_mtu); + if (!err) { + oct->link_info.mtu = new_mtu; + netdev->mtu = new_mtu; + } + return err; +} + +static int octep_vf_set_features(struct net_device *netdev, + netdev_features_t features) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + u16 rx_offloads = 0, tx_offloads = 0; + int err; + + /* We only support features received from firmware */ + if ((features & netdev->hw_features) != features) + return -EINVAL; + + if (features & NETIF_F_TSO) + tx_offloads |= OCTEP_VF_TX_OFFLOAD_TSO; + + if (features & NETIF_F_TSO6) + tx_offloads |= OCTEP_VF_TX_OFFLOAD_TSO; + + if (features & NETIF_F_IP_CSUM) + tx_offloads |= OCTEP_VF_TX_OFFLOAD_CKSUM; + + if (features & NETIF_F_IPV6_CSUM) + tx_offloads |= OCTEP_VF_TX_OFFLOAD_CKSUM; + + if (features & NETIF_F_RXCSUM) + rx_offloads |= OCTEP_VF_RX_OFFLOAD_CKSUM; + + err = octep_vf_mbox_set_offloads(oct, tx_offloads, rx_offloads); + if (!err) + netdev->features = features; + + return err; +} + static const struct net_device_ops octep_vf_netdev_ops = { .ndo_open = octep_vf_open, .ndo_stop = octep_vf_stop, .ndo_start_xmit = octep_vf_start_xmit, .ndo_tx_timeout = octep_vf_tx_timeout, + .ndo_set_mac_address = octep_vf_set_mac, + .ndo_change_mtu = octep_vf_change_mtu, + .ndo_set_features = octep_vf_set_features, }; static const char *octep_vf_devid_to_str(struct octep_vf_device *oct) @@ -411,11 +497,28 @@ static int octep_vf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_mbox_version; } + if (octep_vf_mbox_get_fw_info(octep_vf_dev)) { + dev_err(&pdev->dev, "unable to get fw info\n"); + err = -EINVAL; + goto err_mbox_version; + } + netdev->hw_features = NETIF_F_SG; + if (OCTEP_VF_TX_IP_CSUM(octep_vf_dev->fw_info.tx_ol_flags)) + netdev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + + if (OCTEP_VF_RX_IP_CSUM(octep_vf_dev->fw_info.rx_ol_flags)) + netdev->hw_features |= NETIF_F_RXCSUM; + netdev->min_mtu = OCTEP_VF_MIN_MTU; netdev->max_mtu = OCTEP_VF_MAX_MTU; netdev->mtu = OCTEP_VF_DEFAULT_MTU; + if (OCTEP_VF_TX_TSO(octep_vf_dev->fw_info.tx_ol_flags)) { + netdev->hw_features |= NETIF_F_TSO; + netif_set_tso_max_size(netdev, netdev->max_mtu); + } + netdev->features |= netdev->hw_features; octep_vf_get_mac_addr(octep_vf_dev, octep_vf_dev->mac_addr); eth_hw_addr_set(netdev, octep_vf_dev->mac_addr); diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h index e22e393c6ee2..5a3b545ad590 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h @@ -327,6 +327,7 @@ void octep_vf_device_setup_cn93(struct octep_vf_device *oct); void octep_vf_device_setup_cnxk(struct octep_vf_device *oct); int octep_vf_iq_process_completions(struct octep_vf_iq *iq, u16 budget); int octep_vf_oq_process_rx(struct octep_vf_oq *oq, int budget); +int octep_vf_get_link_info(struct octep_vf_device *oct); int octep_vf_get_if_stats(struct octep_vf_device *oct); void octep_vf_mbox_work(struct work_struct *work); #endif /* _OCTEP_VF_MAIN_H_ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c index 1c1fe293fc50..2eab21e43048 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c @@ -10,6 +10,15 @@ #include "octep_vf_config.h" #include "octep_vf_main.h" +/* When a new command is implemented, the below table should be updated + * with new command and it's version info. + */ +static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = { + [0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1, + [OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] = + OCTEP_PFVF_MBOX_VERSION_V2 +}; + int octep_vf_setup_mbox(struct octep_vf_device *oct) { int ring = 0; @@ -23,6 +32,7 @@ int octep_vf_setup_mbox(struct octep_vf_device *oct) oct->hw_ops.setup_mbox_regs(oct, ring); INIT_WORK(&oct->mbox->wk.work, octep_vf_mbox_work); oct->mbox->wk.ctxptr = oct; + oct->mbox_neg_ver = OCTEP_PFVF_MBOX_VERSION_CURRENT; dev_info(&oct->pdev->dev, "setup vf mbox successfully\n"); return 0; } @@ -42,55 +52,379 @@ void octep_vf_delete_mbox(struct octep_vf_device *oct) int octep_vf_mbox_version_check(struct octep_vf_device *oct) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_version.opcode = OCTEP_PFVF_MBOX_CMD_VERSION; + cmd.s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret == OCTEP_PFVF_MBOX_CMD_STATUS_NACK) { + dev_err(&oct->pdev->dev, + "VF Mbox version is incompatible with PF\n"); + return -EINVAL; + } + oct->mbox_neg_ver = (u32)rsp.s_version.version; + dev_dbg(&oct->pdev->dev, + "VF Mbox version:%u Negotiated VF version with PF:%u\n", + (u32)cmd.s_version.version, + (u32)rsp.s_version.version); return 0; } void octep_vf_mbox_work(struct work_struct *work) { + struct octep_vf_mbox_wk *wk = container_of(work, struct octep_vf_mbox_wk, work); + struct octep_vf_iface_link_info *link_info; + struct octep_vf_device *oct = NULL; + struct octep_vf_mbox *mbox = NULL; + union octep_pfvf_mbox_word *notif; + u64 pf_vf_data; + + oct = (struct octep_vf_device *)wk->ctxptr; + link_info = &oct->link_info; + mbox = oct->mbox; + pf_vf_data = readq(mbox->mbox_read_reg); + + notif = (union octep_pfvf_mbox_word *)&pf_vf_data; + + switch (notif->s.opcode) { + case OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS: + if (notif->s_link_status.status) { + link_info->oper_up = OCTEP_PFVF_LINK_STATUS_UP; + netif_carrier_on(oct->netdev); + dev_info(&oct->pdev->dev, "netif_carrier_on\n"); + } else { + link_info->oper_up = OCTEP_PFVF_LINK_STATUS_DOWN; + netif_carrier_off(oct->netdev); + dev_info(&oct->pdev->dev, "netif_carrier_off\n"); + } + break; + default: + dev_err(&oct->pdev->dev, + "Received unsupported notif %d\n", notif->s.opcode); + break; + } +} + +static int __octep_vf_mbox_send_cmd(struct octep_vf_device *oct, + union octep_pfvf_mbox_word cmd, + union octep_pfvf_mbox_word *rsp) +{ + struct octep_vf_mbox *mbox = oct->mbox; + u64 reg_val = 0ull; + int count; + + if (!mbox) + return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP; + + cmd.s.type = OCTEP_PFVF_MBOX_TYPE_CMD; + writeq(cmd.u64, mbox->mbox_write_reg); + + /* No response for notification messages */ + if (!rsp) + return 0; + + for (count = 0; count < OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT; count++) { + usleep_range(1000, 1500); + reg_val = readq(mbox->mbox_write_reg); + if (reg_val != cmd.u64) { + rsp->u64 = reg_val; + break; + } + } + if (count == OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT) { + dev_err(&oct->pdev->dev, "mbox send command timed out\n"); + return OCTEP_PFVF_MBOX_CMD_STATUS_TIMEDOUT; + } + if (rsp->s.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "mbox_send: Received NACK\n"); + return OCTEP_PFVF_MBOX_CMD_STATUS_NACK; + } + rsp->u64 = reg_val; + return 0; +} + +int octep_vf_mbox_send_cmd(struct octep_vf_device *oct, union octep_pfvf_mbox_word cmd, + union octep_pfvf_mbox_word *rsp) +{ + struct octep_vf_mbox *mbox = oct->mbox; + int ret; + + if (!mbox) + return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP; + mutex_lock(&mbox->lock); + if (pfvf_cmd_versions[cmd.s.opcode] > oct->mbox_neg_ver) { + dev_dbg(&oct->pdev->dev, "CMD:%d not supported in Version:%d\n", + cmd.s.opcode, oct->mbox_neg_ver); + mutex_unlock(&mbox->lock); + return -EOPNOTSUPP; + } + ret = __octep_vf_mbox_send_cmd(oct, cmd, rsp); + mutex_unlock(&mbox->lock); + return ret; +} + +int octep_vf_mbox_bulk_read(struct octep_vf_device *oct, enum octep_pfvf_mbox_opcode opcode, + u8 *data, int *size) +{ + struct octep_vf_mbox *mbox = oct->mbox; + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int data_len = 0, tmp_len = 0; + int read_cnt, i = 0, ret; + + if (!mbox) + return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP; + + mutex_lock(&mbox->lock); + cmd.u64 = 0; + cmd.s_data.opcode = opcode; + cmd.s_data.frag = 0; + /* Send cmd to read data from PF */ + ret = __octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "send mbox cmd fail for data request\n"); + mutex_unlock(&mbox->lock); + return ret; + } + /* PF sends the data length of requested CMD + * in ACK + */ + data_len = *((int32_t *)rsp.s_data.data); + tmp_len = data_len; + cmd.u64 = 0; + rsp.u64 = 0; + cmd.s_data.opcode = opcode; + cmd.s_data.frag = 1; + while (data_len) { + ret = __octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "send mbox cmd fail for data request\n"); + mutex_unlock(&mbox->lock); + mbox->mbox_data.data_index = 0; + memset(mbox->mbox_data.recv_data, 0, OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE); + return ret; + } + if (data_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE) { + data_len -= OCTEP_PFVF_MBOX_MAX_DATA_SIZE; + read_cnt = OCTEP_PFVF_MBOX_MAX_DATA_SIZE; + } else { + read_cnt = data_len; + data_len = 0; + } + for (i = 0; i < read_cnt; i++) { + mbox->mbox_data.recv_data[mbox->mbox_data.data_index] = + rsp.s_data.data[i]; + mbox->mbox_data.data_index++; + } + cmd.u64 = 0; + rsp.u64 = 0; + cmd.s_data.opcode = opcode; + cmd.s_data.frag = 1; + } + memcpy(data, mbox->mbox_data.recv_data, tmp_len); + *size = tmp_len; + mbox->mbox_data.data_index = 0; + memset(mbox->mbox_data.recv_data, 0, OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE); + mutex_unlock(&mbox->lock); + return 0; } int octep_vf_mbox_set_mtu(struct octep_vf_device *oct, int mtu) { + int frame_size = mtu + ETH_HLEN + ETH_FCS_LEN; + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret = 0; + + if (mtu < ETH_MIN_MTU || frame_size > ETH_MAX_MTU) { + dev_err(&oct->pdev->dev, + "Failed to set MTU to %d MIN MTU:%d MAX MTU:%d\n", + mtu, ETH_MIN_MTU, ETH_MAX_MTU); + return -EINVAL; + } + + cmd.u64 = 0; + cmd.s_set_mtu.opcode = OCTEP_PFVF_MBOX_CMD_SET_MTU; + cmd.s_set_mtu.mtu = mtu; + + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Mbox send failed; err=%d\n", ret); + return ret; + } + if (rsp.s_set_mtu.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Received Mbox NACK from PF for MTU:%d\n", mtu); + return -EINVAL; + } + return 0; } int octep_vf_mbox_set_mac_addr(struct octep_vf_device *oct, char *mac_addr) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int i, ret; + + cmd.u64 = 0; + cmd.s_set_mac.opcode = OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR; + for (i = 0; i < ETH_ALEN; i++) + cmd.s_set_mac.mac_addr[i] = mac_addr[i]; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Mbox send failed; err = %d\n", ret); + return ret; + } + if (rsp.s_set_mac.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "received NACK\n"); + return -EINVAL; + } return 0; } int octep_vf_mbox_get_mac_addr(struct octep_vf_device *oct, char *mac_addr) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int i, ret; + + cmd.u64 = 0; + cmd.s_set_mac.opcode = OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "get_mac: mbox send failed; err = %d\n", ret); + return ret; + } + if (rsp.s_set_mac.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "get_mac: received NACK\n"); + return -EINVAL; + } + for (i = 0; i < ETH_ALEN; i++) + mac_addr[i] = rsp.s_set_mac.mac_addr[i]; return 0; } int octep_vf_mbox_set_rx_state(struct octep_vf_device *oct, bool state) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_link_state.opcode = OCTEP_PFVF_MBOX_CMD_SET_RX_STATE; + cmd.s_link_state.state = state; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Set Rx state via VF Mbox send failed\n"); + return ret; + } + if (rsp.s_link_state.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Set Rx state received NACK\n"); + return -EINVAL; + } return 0; } int octep_vf_mbox_set_link_status(struct octep_vf_device *oct, bool status) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_link_status.opcode = OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS; + cmd.s_link_status.status = status; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Set link status via VF Mbox send failed\n"); + return ret; + } + if (rsp.s_link_status.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Set link status received NACK\n"); + return -EINVAL; + } return 0; } int octep_vf_mbox_get_link_status(struct octep_vf_device *oct, u8 *oper_up) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_link_status.opcode = OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Get link status via VF Mbox send failed\n"); + return ret; + } + if (rsp.s_link_status.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Get link status received NACK\n"); + return -EINVAL; + } + *oper_up = rsp.s_link_status.status; return 0; } int octep_vf_mbox_dev_remove(struct octep_vf_device *oct) { - return 0; + union octep_pfvf_mbox_word cmd; + int ret; + + cmd.u64 = 0; + cmd.s.opcode = OCTEP_PFVF_MBOX_CMD_DEV_REMOVE; + ret = octep_vf_mbox_send_cmd(oct, cmd, NULL); + return ret; } int octep_vf_mbox_get_fw_info(struct octep_vf_device *oct) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_fw_info.opcode = OCTEP_PFVF_MBOX_CMD_GET_FW_INFO; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Get link status via VF Mbox send failed\n"); + return ret; + } + if (rsp.s_fw_info.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Get link status received NACK\n"); + return -EINVAL; + } + oct->fw_info.pkind = rsp.s_fw_info.pkind; + oct->fw_info.fsz = rsp.s_fw_info.fsz; + oct->fw_info.rx_ol_flags = rsp.s_fw_info.rx_ol_flags; + oct->fw_info.tx_ol_flags = rsp.s_fw_info.tx_ol_flags; + return 0; } int octep_vf_mbox_set_offloads(struct octep_vf_device *oct, u16 tx_offloads, u16 rx_offloads) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_offloads.opcode = OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS; + cmd.s_offloads.rx_ol_flags = rx_offloads; + cmd.s_offloads.tx_ol_flags = tx_offloads; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Set offloads via VF Mbox send failed\n"); + return ret; + } + if (rsp.s_link_state.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Set offloads received NACK\n"); + return -EINVAL; + } return 0; } diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h index 14f4fb19445b..9b5efad37eab 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h @@ -7,10 +7,151 @@ #ifndef _OCTEP_VF_MBOX_H_ #define _OCTEP_VF_MBOX_H_ -#define OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE 256 +/* When a new command is implemented, VF Mbox version should be bumped. + */ +enum octep_pfvf_mbox_version { + OCTEP_PFVF_MBOX_VERSION_V0, + OCTEP_PFVF_MBOX_VERSION_V1, + OCTEP_PFVF_MBOX_VERSION_V2 +}; + +#define OCTEP_PFVF_MBOX_VERSION_CURRENT OCTEP_PFVF_MBOX_VERSION_V2 + +enum octep_pfvf_mbox_opcode { + OCTEP_PFVF_MBOX_CMD_VERSION, + OCTEP_PFVF_MBOX_CMD_SET_MTU, + OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR, + OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR, + OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO, + OCTEP_PFVF_MBOX_CMD_GET_STATS, + OCTEP_PFVF_MBOX_CMD_SET_RX_STATE, + OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS, + OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS, + OCTEP_PFVF_MBOX_CMD_GET_MTU, + OCTEP_PFVF_MBOX_CMD_DEV_REMOVE, + OCTEP_PFVF_MBOX_CMD_GET_FW_INFO, + OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS, + OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS, + OCTEP_PFVF_MBOX_CMD_MAX, +}; + +enum octep_pfvf_mbox_word_type { + OCTEP_PFVF_MBOX_TYPE_CMD, + OCTEP_PFVF_MBOX_TYPE_RSP_ACK, + OCTEP_PFVF_MBOX_TYPE_RSP_NACK, +}; + +enum octep_pfvf_mbox_cmd_status { + OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP = 1, + OCTEP_PFVF_MBOX_CMD_STATUS_TIMEDOUT = 2, + OCTEP_PFVF_MBOX_CMD_STATUS_NACK = 3, + OCTEP_PFVF_MBOX_CMD_STATUS_BUSY = 4, + OCTEP_PFVF_MBOX_CMD_STATUS_ERR = 5 +}; + +enum octep_pfvf_link_status { + OCTEP_PFVF_LINK_STATUS_DOWN, + OCTEP_PFVF_LINK_STATUS_UP, +}; + +enum octep_pfvf_link_speed { + OCTEP_PFVF_LINK_SPEED_NONE, + OCTEP_PFVF_LINK_SPEED_1000, + OCTEP_PFVF_LINK_SPEED_10000, + OCTEP_PFVF_LINK_SPEED_25000, + OCTEP_PFVF_LINK_SPEED_40000, + OCTEP_PFVF_LINK_SPEED_50000, + OCTEP_PFVF_LINK_SPEED_100000, + OCTEP_PFVF_LINK_SPEED_LAST, +}; + +enum octep_pfvf_link_duplex { + OCTEP_PFVF_LINK_HALF_DUPLEX, + OCTEP_PFVF_LINK_FULL_DUPLEX, +}; + +enum octep_pfvf_link_autoneg { + OCTEP_PFVF_LINK_AUTONEG, + OCTEP_PFVF_LINK_FIXED, +}; + +#define OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT 8000 +#define OCTEP_PFVF_MBOX_TIMEOUT_WAIT_UDELAY 1000 +#define OCTEP_PFVF_MBOX_MAX_RETRIES 2 +#define OCTEP_PFVF_MBOX_VERSION 0 +#define OCTEP_PFVF_MBOX_MAX_DATA_SIZE 6 +#define OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE 320 +#define OCTEP_PFVF_MBOX_MORE_FRAG_FLAG 1 + +union octep_pfvf_mbox_word { + u64 u64; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:6; + u64 data:48; + } s; + struct { + u64 opcode:8; + u64 type:2; + u64 frag:1; + u64 rsvd:5; + u8 data[6]; + } s_data; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:6; + u64 version:48; + } s_version; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:6; + u8 mac_addr[6]; + } s_set_mac; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:6; + u64 mtu:48; + } s_set_mtu; + struct { + u64 opcode:8; + u64 type:2; + u64 state:1; + u64 rsvd:53; + } s_link_state; + struct { + u64 opcode:8; + u64 type:2; + u64 status:1; + u64 rsvd:53; + } s_link_status; + struct { + u64 opcode:8; + u64 type:2; + u64 pkind:8; + u64 fsz:8; + u64 rx_ol_flags:16; + u64 tx_ol_flags:16; + u64 rsvd:6; + } s_fw_info; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:22; + u64 rx_ol_flags:16; + u64 tx_ol_flags:16; + } s_offloads; +} __packed; int octep_vf_setup_mbox(struct octep_vf_device *oct); void octep_vf_delete_mbox(struct octep_vf_device *oct); +int octep_vf_mbox_send_cmd(struct octep_vf_device *oct, union octep_pfvf_mbox_word cmd, + union octep_pfvf_mbox_word *rsp); +int octep_vf_mbox_bulk_read(struct octep_vf_device *oct, enum octep_pfvf_mbox_opcode opcode, + u8 *data, int *size); int octep_vf_mbox_set_mtu(struct octep_vf_device *oct, int mtu); int octep_vf_mbox_set_mac_addr(struct octep_vf_device *oct, char *mac_addr); int octep_vf_mbox_get_mac_addr(struct octep_vf_device *oct, char *mac_addr); From patchwork Mon Jan 29 05:02:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shinas Rasheed X-Patchwork-Id: 193233 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2087:b0:106:209c:c626 with SMTP id gs7csp366158dyb; Sun, 28 Jan 2024 21:04:37 -0800 (PST) X-Google-Smtp-Source: AGHT+IFa40CMhWy3AyQQLTSi7ctbF1dMkoumueXEqDr/7OpUjo9WQZv0WY91CI55troiI5HKUiWH X-Received: by 2002:a05:620a:218b:b0:783:2e5b:1fdc with SMTP id g11-20020a05620a218b00b007832e5b1fdcmr4882751qka.154.1706504677651; Sun, 28 Jan 2024 21:04:37 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706504677; cv=pass; d=google.com; s=arc-20160816; b=i7TCvOmXmYFpwwhNUWWkkuJOMSy/QnD/29jm9mRsJ3C2RRRep6JMZf2FkCd7ZK16Vu 9T+H0HTXLwObVG7+1d7Kuik5UnMMl29c5Gf6WnHRVlGFbSm8XMxujPUMrIkMMVF2njbg i4H4vICk9j6E5DR7cKxJvUoSvyjpVjgNrU7/har4dqJbUjqJM8HxEPUm3VZyvl/a/zhZ Ylut3f8jn0UuDa5rOWis1kwXUPTI6oQg7gnYjr0NasyJodcYWPeUrRd5AYSMsmtWBtfH 6hFQYQfDvCUvt8sq/yj8iaDNTDuPHOonwqwhgadyYSMNVkYndHPJsdXJRQ/M0SUXYipX Jgzg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=PB+N5h7yZv9JTdTdW/MGDW07pdnWyzsKllq+tEyOXQs=; fh=Y/Zcr0YXYeEsWchgSSogMl8sJJcf/EqHGWMcPJ+i19E=; b=AO89OkkgHjQOijAdFZlKjzwq9kQomFdiPub5GgRM5szcYm5suVj5sYO5Xl5cN0DDke bczUPzBGcmSzQd/0LwAABwJ6qAqNFDOepLURnGnK2S4zNKjTXBzqzhB9PlibsUk88DH0 20mlw+E3eC6GdcSPHvmeq6yZxc3esJoe+uulx1qJbNCrCesv/kknkrbhF1wwI7NLyjZi F3yIvYBLBoT3xYnwI4pBt9NOyuShVofTPladFVZjVNs72th9KxAS3dHMSfSsOCJdodhQ A0tMLrpeYQzqhuoiynBw7QJwqzq+GvfYhI9nYbUBkIihIqUQlN6hDQNdW1EPGFPPUBPv KWVA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b="ipRr/bMi"; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42168-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42168-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id u24-20020a05620a085800b00783e46b2470si4464169qku.600.2024.01.28.21.04.37 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Jan 2024 21:04:37 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-42168-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b="ipRr/bMi"; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42168-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42168-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 421561C22441 for ; Mon, 29 Jan 2024 05:04:37 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 688294CB5B; Mon, 29 Jan 2024 05:03:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="ipRr/bMi" Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 20CC83D3AC; Mon, 29 Jan 2024 05:03:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.148.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504615; cv=none; b=i93bu5/NrPLHFxtDCKtKKYQG97Fl/0aG/S7OZ+0TBaYGZnKm25VYXo3TWN/M8SWdpG6tDKY6c0WbniecxXtz7OixY7VM7trVCy1JLhsh2GqOoXURIyobCcQAju0Fm9BoKaH0w6MIhr1ne9c1XSjzGJScoCwJqOFkkpGfqRUO/jQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504615; c=relaxed/simple; bh=1lTCkQTpZN81IgFFc3JD5K/XSqjlUGKctUGfQFoU8vU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=P7bJu3rimPghXMvA8tW+wUnlzD8xFv4Fu54TUITqj5jDcJReW2WAOAbCHuLXO6AJZRIhIV5bmLuu5QHn4EX2tdCqjczuD/+lONXYUCFb4EgJsVGMLwoPh9qkEAujMlEx1IhOS+EnorgQiztd8zLdXTo/4KvMKmj/a2nThA4irL0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com; spf=pass smtp.mailfrom=marvell.com; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b=ipRr/bMi; arc=none smtp.client-ip=67.231.148.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 40T4KEj8027114; Sun, 28 Jan 2024 21:03:24 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=PB+N5h7yZv9JTdTdW/MGDW07pdnWyzsKllq+tEyOXQs=; b=ipR r/bMiascvm0uxtKc2QDNpjZsaXNDG3TyCqADutNnyGu7sUVpCiHSXtiSnbrHDt59 mJuopI1A1p3Dkun1WrJELU79Duc1uZ4zqa+9+q2fe0V2gotFqRWQOU1LuHd8E+TG BsxN4WvisEcyhZgMFHaeVp4KVrcSGw9D1Zzfm5AKz6Lp5a8hP6WgZ8MwW+qnXRjp li/2MmNSstkyGmcfgtkwhjA2CMxk7nE/FhyRSNRpXFbv4tWZnkyxXkUZsoueMdLW a7Bo62/7K2BVlpYhP22PGLmKRiiyZ93/KVgJ4iaBxQQITo2UjTIo5Hm9vWzP5DpJ iEzs2dJ+CM/1jtoSGeg== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3vx4vr82d2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 28 Jan 2024 21:03:23 -0800 (PST) Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Sun, 28 Jan 2024 21:03:22 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Sun, 28 Jan 2024 21:03:22 -0800 Received: from ubuntu-PowerEdge-T110-II.sclab.marvell.com (unknown [10.106.27.86]) by maili.marvell.com (Postfix) with ESMTP id C47603F7045; Sun, 28 Jan 2024 21:03:21 -0800 (PST) From: Shinas Rasheed To: , CC: , , , , , , , , , , , , Veerasenareddy Burru , Satananda Burla , "David S. Miller" , Eric Dumazet Subject: [PATCH net-next v5 4/8] octeon_ep_vf: add Tx/Rx ring resource setup and cleanup Date: Sun, 28 Jan 2024 21:02:50 -0800 Message-ID: <20240129050254.3047778-5-srasheed@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240129050254.3047778-1-srasheed@marvell.com> References: <20240129050254.3047778-1-srasheed@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: yxvu4NzjFVsaFPMSMzMGaY7YvjBjuSwg X-Proofpoint-GUID: yxvu4NzjFVsaFPMSMzMGaY7YvjBjuSwg X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-01-29_02,2024-01-25_01,2023-05-22_02 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789399849000798407 X-GMAIL-MSGID: 1789399849000798407 Implement Tx/Rx ring resource allocation and cleanup. Signed-off-by: Shinas Rasheed --- V5: - No changes V4: https://lore.kernel.org/all/20240108124213.2966536-5-srasheed@marvell.com/ - No changes V3: https://lore.kernel.org/all/20240105203823.2953604-5-srasheed@marvell.com/ - Moved vfree and vzalloc null pointer casting corrections to this patch - Corrected return values to follow standard kernel error codes V2: https://lore.kernel.org/all/20231223134000.2906144-5-srasheed@marvell.com/ - No changes V1: https://lore.kernel.org/all/20231221092844.2885872-5-srasheed@marvell.com/ .../marvell/octeon_ep_vf/octep_vf_rx.c | 223 +++++++++++++++++- .../marvell/octeon_ep_vf/octep_vf_tx.c | 216 +++++++++++++++++ 2 files changed, 438 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c index 4f1a8157ce39..330d6e72bc0b 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c @@ -7,10 +7,198 @@ #include #include +#include #include "octep_vf_config.h" #include "octep_vf_main.h" +static void octep_vf_oq_reset_indices(struct octep_vf_oq *oq) +{ + oq->host_read_idx = 0; + oq->host_refill_idx = 0; + oq->refill_count = 0; + oq->last_pkt_count = 0; + oq->pkts_pending = 0; +} + +/** + * octep_vf_oq_fill_ring_buffers() - fill initial receive buffers for Rx ring. + * + * @oq: Octeon Rx queue data structure. + * + * Return: 0, if successfully filled receive buffers for all descriptors. + * -ENOMEM, if failed to allocate a buffer or failed to map for DMA. + */ +static int octep_vf_oq_fill_ring_buffers(struct octep_vf_oq *oq) +{ + struct octep_vf_oq_desc_hw *desc_ring = oq->desc_ring; + struct page *page; + u32 i; + + for (i = 0; i < oq->max_count; i++) { + page = dev_alloc_page(); + if (unlikely(!page)) { + dev_err(oq->dev, "Rx buffer alloc failed\n"); + goto rx_buf_alloc_err; + } + desc_ring[i].buffer_ptr = dma_map_page(oq->dev, page, 0, + PAGE_SIZE, + DMA_FROM_DEVICE); + if (dma_mapping_error(oq->dev, desc_ring[i].buffer_ptr)) { + dev_err(oq->dev, + "OQ-%d buffer alloc: DMA mapping error!\n", + oq->q_no); + goto dma_map_err; + } + oq->buff_info[i].page = page; + } + + return 0; + +dma_map_err: + put_page(page); +rx_buf_alloc_err: + while (i) { + i--; + dma_unmap_page(oq->dev, desc_ring[i].buffer_ptr, PAGE_SIZE, DMA_FROM_DEVICE); + put_page(oq->buff_info[i].page); + oq->buff_info[i].page = NULL; + } + + return -ENOMEM; +} + +/** + * octep_vf_setup_oq() - Setup a Rx queue. + * + * @oct: Octeon device private data structure. + * @q_no: Rx queue number to be setup. + * + * Allocate resources for a Rx queue. + */ +static int octep_vf_setup_oq(struct octep_vf_device *oct, int q_no) +{ + struct octep_vf_oq *oq; + u32 desc_ring_size; + + oq = vzalloc(sizeof(*oq)); + if (!oq) + goto create_oq_fail; + oct->oq[q_no] = oq; + + oq->octep_vf_dev = oct; + oq->netdev = oct->netdev; + oq->dev = &oct->pdev->dev; + oq->q_no = q_no; + oq->max_count = CFG_GET_OQ_NUM_DESC(oct->conf); + oq->ring_size_mask = oq->max_count - 1; + oq->buffer_size = CFG_GET_OQ_BUF_SIZE(oct->conf); + oq->max_single_buffer_size = oq->buffer_size - OCTEP_VF_OQ_RESP_HW_SIZE; + + /* When the hardware/firmware supports additional capabilities, + * additional header is filled-in by Octeon after length field in + * Rx packets. this header contains additional packet information. + */ + if (oct->fw_info.rx_ol_flags) + oq->max_single_buffer_size -= OCTEP_VF_OQ_RESP_HW_EXT_SIZE; + + oq->refill_threshold = CFG_GET_OQ_REFILL_THRESHOLD(oct->conf); + + desc_ring_size = oq->max_count * OCTEP_VF_OQ_DESC_SIZE; + oq->desc_ring = dma_alloc_coherent(oq->dev, desc_ring_size, + &oq->desc_ring_dma, GFP_KERNEL); + + if (unlikely(!oq->desc_ring)) { + dev_err(oq->dev, + "Failed to allocate DMA memory for OQ-%d !!\n", q_no); + goto desc_dma_alloc_err; + } + + oq->buff_info = vzalloc(oq->max_count * OCTEP_VF_OQ_RECVBUF_SIZE); + + if (unlikely(!oq->buff_info)) { + dev_err(&oct->pdev->dev, + "Failed to allocate buffer info for OQ-%d\n", q_no); + goto buf_list_err; + } + + if (octep_vf_oq_fill_ring_buffers(oq)) + goto oq_fill_buff_err; + + octep_vf_oq_reset_indices(oq); + oct->hw_ops.setup_oq_regs(oct, q_no); + oct->num_oqs++; + + return 0; + +oq_fill_buff_err: + vfree(oq->buff_info); + oq->buff_info = NULL; +buf_list_err: + dma_free_coherent(oq->dev, desc_ring_size, + oq->desc_ring, oq->desc_ring_dma); + oq->desc_ring = NULL; +desc_dma_alloc_err: + vfree(oq); + oct->oq[q_no] = NULL; +create_oq_fail: + return -ENOMEM; +} + +/** + * octep_vf_oq_free_ring_buffers() - Free ring buffers. + * + * @oq: Octeon Rx queue data structure. + * + * Free receive buffers in unused Rx queue descriptors. + */ +static void octep_vf_oq_free_ring_buffers(struct octep_vf_oq *oq) +{ + struct octep_vf_oq_desc_hw *desc_ring = oq->desc_ring; + int i; + + if (!oq->desc_ring || !oq->buff_info) + return; + + for (i = 0; i < oq->max_count; i++) { + if (oq->buff_info[i].page) { + dma_unmap_page(oq->dev, desc_ring[i].buffer_ptr, + PAGE_SIZE, DMA_FROM_DEVICE); + put_page(oq->buff_info[i].page); + oq->buff_info[i].page = NULL; + desc_ring[i].buffer_ptr = 0; + } + } + octep_vf_oq_reset_indices(oq); +} + +/** + * octep_vf_free_oq() - Free Rx queue resources. + * + * @oq: Octeon Rx queue data structure. + * + * Free all resources of a Rx queue. + */ +static int octep_vf_free_oq(struct octep_vf_oq *oq) +{ + struct octep_vf_device *oct = oq->octep_vf_dev; + int q_no = oq->q_no; + + octep_vf_oq_free_ring_buffers(oq); + + vfree(oq->buff_info); + + if (oq->desc_ring) + dma_free_coherent(oq->dev, + oq->max_count * OCTEP_VF_OQ_DESC_SIZE, + oq->desc_ring, oq->desc_ring_dma); + + vfree(oq); + oct->oq[q_no] = NULL; + oct->num_oqs--; + return 0; +} + /** * octep_vf_setup_oqs() - setup resources for all Rx queues. * @@ -18,7 +206,27 @@ */ int octep_vf_setup_oqs(struct octep_vf_device *oct) { - return -1; + int i, retval = 0; + + oct->num_oqs = 0; + for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) { + retval = octep_vf_setup_oq(oct, i); + if (retval) { + dev_err(&oct->pdev->dev, + "Failed to setup OQ(RxQ)-%d.\n", i); + goto oq_setup_err; + } + dev_dbg(&oct->pdev->dev, "Successfully setup OQ(RxQ)-%d.\n", i); + } + + return 0; + +oq_setup_err: + while (i) { + i--; + octep_vf_free_oq(oct->oq[i]); + } + return retval; } /** @@ -30,6 +238,10 @@ int octep_vf_setup_oqs(struct octep_vf_device *oct) */ void octep_vf_oq_dbell_init(struct octep_vf_device *oct) { + int i; + + for (i = 0; i < oct->num_oqs; i++) + writel(oct->oq[i]->max_count, oct->oq[i]->pkts_credit_reg); } /** @@ -39,4 +251,13 @@ void octep_vf_oq_dbell_init(struct octep_vf_device *oct) */ void octep_vf_free_oqs(struct octep_vf_device *oct) { + int i; + + for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) { + if (!oct->oq[i]) + continue; + octep_vf_free_oq(oct->oq[i]); + dev_dbg(&oct->pdev->dev, + "Successfully freed OQ(RxQ)-%d.\n", i); + } } diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c index 232ba479ecf6..1a3e1a651dc4 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c @@ -7,10 +7,73 @@ #include #include +#include #include "octep_vf_config.h" #include "octep_vf_main.h" +/* Reset various index of Tx queue data structure. */ +static void octep_vf_iq_reset_indices(struct octep_vf_iq *iq) +{ + iq->fill_cnt = 0; + iq->host_write_index = 0; + iq->octep_vf_read_index = 0; + iq->flush_index = 0; + iq->pkts_processed = 0; + iq->pkt_in_done = 0; +} + +/** + * octep_vf_iq_free_pending() - Free Tx buffers for pending completions. + * + * @iq: Octeon Tx queue data structure. + */ +static void octep_vf_iq_free_pending(struct octep_vf_iq *iq) +{ + struct octep_vf_tx_buffer *tx_buffer; + struct skb_shared_info *shinfo; + u32 fi = iq->flush_index; + struct sk_buff *skb; + u8 frags, i; + + while (fi != iq->host_write_index) { + tx_buffer = iq->buff_info + fi; + skb = tx_buffer->skb; + + fi++; + if (unlikely(fi == iq->max_count)) + fi = 0; + + if (!tx_buffer->gather) { + dma_unmap_single(iq->dev, tx_buffer->dma, + tx_buffer->skb->len, DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + continue; + } + + /* Scatter/Gather */ + shinfo = skb_shinfo(skb); + frags = shinfo->nr_frags; + + dma_unmap_single(iq->dev, + tx_buffer->sglist[0].dma_ptr[0], + tx_buffer->sglist[0].len[0], + DMA_TO_DEVICE); + + i = 1; /* entry 0 is main skb, unmapped above */ + while (frags--) { + dma_unmap_page(iq->dev, tx_buffer->sglist[i >> 2].dma_ptr[i & 3], + tx_buffer->sglist[i >> 2].len[i & 3], DMA_TO_DEVICE); + i++; + } + + dev_kfree_skb_any(skb); + } + + iq->flush_index = fi; + netdev_tx_reset_queue(netdev_get_tx_queue(iq->netdev, iq->q_no)); +} + /** * octep_vf_clean_iqs() - Clean Tx queues to shutdown the device. * @@ -21,6 +84,132 @@ */ void octep_vf_clean_iqs(struct octep_vf_device *oct) { + int i; + + for (i = 0; i < oct->num_iqs; i++) { + octep_vf_iq_free_pending(oct->iq[i]); + octep_vf_iq_reset_indices(oct->iq[i]); + } +} + +/** + * octep_vf_setup_iq() - Setup a Tx queue. + * + * @oct: Octeon device private data structure. + * @q_no: Tx queue number to be setup. + * + * Allocate resources for a Tx queue. + */ +static int octep_vf_setup_iq(struct octep_vf_device *oct, int q_no) +{ + u32 desc_ring_size, buff_info_size, sglist_size; + struct octep_vf_iq *iq; + int i; + + iq = vzalloc(sizeof(*iq)); + if (!iq) + goto iq_alloc_err; + oct->iq[q_no] = iq; + + iq->octep_vf_dev = oct; + iq->netdev = oct->netdev; + iq->dev = &oct->pdev->dev; + iq->q_no = q_no; + iq->max_count = CFG_GET_IQ_NUM_DESC(oct->conf); + iq->ring_size_mask = iq->max_count - 1; + iq->fill_threshold = CFG_GET_IQ_DB_MIN(oct->conf); + iq->netdev_q = netdev_get_tx_queue(iq->netdev, q_no); + + /* Allocate memory for hardware queue descriptors */ + desc_ring_size = OCTEP_VF_IQ_DESC_SIZE * CFG_GET_IQ_NUM_DESC(oct->conf); + iq->desc_ring = dma_alloc_coherent(iq->dev, desc_ring_size, + &iq->desc_ring_dma, GFP_KERNEL); + if (unlikely(!iq->desc_ring)) { + dev_err(iq->dev, + "Failed to allocate DMA memory for IQ-%d\n", q_no); + goto desc_dma_alloc_err; + } + + /* Allocate memory for hardware SGLIST descriptors */ + sglist_size = OCTEP_VF_SGLIST_SIZE_PER_PKT * + CFG_GET_IQ_NUM_DESC(oct->conf); + iq->sglist = dma_alloc_coherent(iq->dev, sglist_size, + &iq->sglist_dma, GFP_KERNEL); + if (unlikely(!iq->sglist)) { + dev_err(iq->dev, + "Failed to allocate DMA memory for IQ-%d SGLIST\n", + q_no); + goto sglist_alloc_err; + } + + /* allocate memory to manage Tx packets pending completion */ + buff_info_size = OCTEP_VF_IQ_TXBUFF_INFO_SIZE * iq->max_count; + iq->buff_info = vzalloc(buff_info_size); + if (!iq->buff_info) { + dev_err(iq->dev, + "Failed to allocate buff info for IQ-%d\n", q_no); + goto buff_info_err; + } + + /* Setup sglist addresses in tx_buffer entries */ + for (i = 0; i < CFG_GET_IQ_NUM_DESC(oct->conf); i++) { + struct octep_vf_tx_buffer *tx_buffer; + + tx_buffer = &iq->buff_info[i]; + tx_buffer->sglist = + &iq->sglist[i * OCTEP_VF_SGLIST_ENTRIES_PER_PKT]; + tx_buffer->sglist_dma = + iq->sglist_dma + (i * OCTEP_VF_SGLIST_SIZE_PER_PKT); + } + + octep_vf_iq_reset_indices(iq); + oct->hw_ops.setup_iq_regs(oct, q_no); + + oct->num_iqs++; + return 0; + +buff_info_err: + dma_free_coherent(iq->dev, sglist_size, iq->sglist, iq->sglist_dma); +sglist_alloc_err: + dma_free_coherent(iq->dev, desc_ring_size, + iq->desc_ring, iq->desc_ring_dma); +desc_dma_alloc_err: + vfree(iq); + oct->iq[q_no] = NULL; +iq_alloc_err: + return -1; +} + +/** + * octep_vf_free_iq() - Free Tx queue resources. + * + * @iq: Octeon Tx queue data structure. + * + * Free all the resources allocated for a Tx queue. + */ +static void octep_vf_free_iq(struct octep_vf_iq *iq) +{ + struct octep_vf_device *oct = iq->octep_vf_dev; + u64 desc_ring_size, sglist_size; + int q_no = iq->q_no; + + desc_ring_size = OCTEP_VF_IQ_DESC_SIZE * CFG_GET_IQ_NUM_DESC(oct->conf); + + vfree(iq->buff_info); + + if (iq->desc_ring) + dma_free_coherent(iq->dev, desc_ring_size, + iq->desc_ring, iq->desc_ring_dma); + + sglist_size = OCTEP_VF_SGLIST_SIZE_PER_PKT * + CFG_GET_IQ_NUM_DESC(oct->conf); + if (iq->sglist) + dma_free_coherent(iq->dev, sglist_size, + iq->sglist, iq->sglist_dma); + + vfree(iq); + oct->iq[q_no] = NULL; + oct->num_iqs--; } /** @@ -30,6 +219,25 @@ void octep_vf_clean_iqs(struct octep_vf_device *oct) */ int octep_vf_setup_iqs(struct octep_vf_device *oct) { + int i; + + oct->num_iqs = 0; + for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) { + if (octep_vf_setup_iq(oct, i)) { + dev_err(&oct->pdev->dev, + "Failed to setup IQ(TxQ)-%d.\n", i); + goto iq_setup_err; + } + dev_dbg(&oct->pdev->dev, "Successfully setup IQ(TxQ)-%d.\n", i); + } + + return 0; + +iq_setup_err: + while (i) { + i--; + octep_vf_free_iq(oct->iq[i]); + } return -1; } @@ -40,4 +248,12 @@ int octep_vf_setup_iqs(struct octep_vf_device *oct) */ void octep_vf_free_iqs(struct octep_vf_device *oct) { + int i; + + for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) { + octep_vf_free_iq(oct->iq[i]); + dev_dbg(&oct->pdev->dev, + "Successfully destroyed IQ(TxQ)-%d.\n", i); + } + oct->num_iqs = 0; } From patchwork Mon Jan 29 05:02:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shinas Rasheed X-Patchwork-Id: 193232 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2087:b0:106:209c:c626 with SMTP id gs7csp366043dyb; Sun, 28 Jan 2024 21:04:19 -0800 (PST) X-Google-Smtp-Source: AGHT+IHIjNeYzLg4Jwo97wzzenqIbJAbJU0+69S9X/Zi6SahFX9ZQaXrMLJp6SJU9jiQXpmujoOR X-Received: by 2002:ac8:7d11:0:b0:42a:555d:605a with SMTP id g17-20020ac87d11000000b0042a555d605amr4955304qtb.49.1706504658880; Sun, 28 Jan 2024 21:04:18 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706504658; cv=pass; d=google.com; s=arc-20160816; b=r3QbscMzQ3k/fRNxZySDP0Pmu95qznbU1fff466vyW22pQLgpBu0EBPicoNSdy8aem nFZSove719AXjeZtVaA8RP2YrTfrqh45M6zH7ASwah8sGtAjA4//yvsQncPGrXQh+fUq TrpJzx9fT0gySQttxrYjYNZeCh6aKZ7G/k5ByB9TnTrYMGYr68E3lVVXekawfARZW4Nv hnsePtE/63tZgYtT4Wwsymk/Ots1/q5mDk4Uf6oOa4Vw3gft2JcF+wZVr496Lia1jOGk 8G/mwkU4awFJsjOYY19Q1NqCyXShEzFXhElcI33x5xP0Rt1fEz4av9ObJIeffTNFQgrq Zk7A== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=ZOvduTOyCNrJIKJ8Qa9RNSmLbNmT5aw5W2vZ3KoliyQ=; fh=Y/Zcr0YXYeEsWchgSSogMl8sJJcf/EqHGWMcPJ+i19E=; b=qUKphOjpL3iUSqYCv2LS+gtEmg5iE9KFKOc+5DaHudEfaH6u5dLMnE9O6U1geL4TM0 f/AIcuYHdSGms5CrBOEDJMaPV4CPbzpbQTljOKkS0vG5sY4VOhcL/4Rum1wa+qr5aatP MXGuHB2vQLKB8Ma9PaLs10ujEEnRGOsEEC0fzsSR31IT0iJk0Lb6IHr/cUAZwKsU1N9k L2/hmshpk2oNYJGM03BgW9SBEeld9YZzgXPmHpwU3MyeLXF9qj1kSryn5Bm4IeASsBmt W55BiE5XPJlvsCsYdgEyS4TV/TLkHlDZkwEmZF6FWlWxW/42EGGB4z98s+VkgNaQ18bS BxrA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=JxKT68lB; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42167-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42167-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id g12-20020ac8580c000000b0042a956fcb40si3881539qtg.147.2024.01.28.21.04.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Jan 2024 21:04:18 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-42167-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=JxKT68lB; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42167-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42167-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id A9E3D1C21D36 for ; Mon, 29 Jan 2024 05:04:18 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 98C6C4C610; Mon, 29 Jan 2024 05:03:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="JxKT68lB" Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C275F3C49C; Mon, 29 Jan 2024 05:03:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.148.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504615; cv=none; b=WquncPy4JA1ColKiWru+SWqLw6AEGHQxlebjMWYBHI3S3UiyRgg3kLOKnrCDw3IHuUiYAk0QzYUj6aRXpqejmc617evjeA+442ZJwCS8rMeTEk2Vd6uOkVKR+ItvmmkTcA9f9hMwMb5lDeAOYhq1Kr9y49Dd2AlQvE7P69f+Gro= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504615; c=relaxed/simple; bh=j1q4tB+oOQYzR1/x6opmItWuKWDj32zm3XHggC6iVEc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=E5et+sO1ipBArzINH34KWt+imHeR2OLnIXvLJOoyzRwfOUODVxEmQ7SFp7Y+Sey4C0faACEHdEZz+chDffbyAJ9+Ptkka7xAECNwYFEtRvvJW7RcIp8ARQEWatkGSEH/A3NLSzWGTjKm0QdevSPHKXZpKtlbKVMfS3cYmPfQcW8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com; spf=pass smtp.mailfrom=marvell.com; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b=JxKT68lB; arc=none smtp.client-ip=67.231.148.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 40T4KEj9027114; Sun, 28 Jan 2024 21:03:26 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=ZOvduTOyCNrJIKJ8Qa9RNSmLbNmT5aw5W2vZ3KoliyQ=; b=JxK T68lBtY2bT+5pnFPi/7Bnmu7O6RB4yYE9gtvvwsJ17+wpyC6QqG6Tjom+yZ0/C/g evC1OwJKIUrhim3PuClpE1WiTBSK1Q8gixxUf038mFHKdNfl3WKaeIhc6KpxKTwj 61uI8g2HsRjgcoySwSkqwCix/wDSGngVZH6rrIsHRm7Qu7HOo7vQ/XRI6VCObfgI +m6stqdmzUt3oOuNambwTeMR+V+8VCzaA2c7QVrQVzrG7Lk4N5Hihu3BMJJ/TB86 pnukbgavxAaxqRlZTDUgKEwyKdHBMxhRxBSmD5yEhr0t4Y6UAIHhFFMTMTwKs0fw GTshs22gIfoZZjoAsAA== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3vx4vr82dg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 28 Jan 2024 21:03:26 -0800 (PST) Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Sun, 28 Jan 2024 21:03:25 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Sun, 28 Jan 2024 21:03:24 -0800 Received: from ubuntu-PowerEdge-T110-II.sclab.marvell.com (unknown [10.106.27.86]) by maili.marvell.com (Postfix) with ESMTP id A14733F703F; Sun, 28 Jan 2024 21:03:24 -0800 (PST) From: Shinas Rasheed To: , CC: , , , , , , , , , , , , Veerasenareddy Burru , Satananda Burla , "David S. Miller" , Eric Dumazet Subject: [PATCH net-next v5 5/8] octeon_ep_vf: add support for ndo ops Date: Sun, 28 Jan 2024 21:02:51 -0800 Message-ID: <20240129050254.3047778-6-srasheed@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240129050254.3047778-1-srasheed@marvell.com> References: <20240129050254.3047778-1-srasheed@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: pFQG03xlhIJ8uPBjJ_4l9AtQVxMHh5G7 X-Proofpoint-GUID: pFQG03xlhIJ8uPBjJ_4l9AtQVxMHh5G7 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-01-29_02,2024-01-25_01,2023-05-22_02 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789399828891746477 X-GMAIL-MSGID: 1789399828891746477 Add support for ndo ops to set MAC address, change MTU, get stats. Add control path support to set MAC address, change MTU, get stats, set speed, get and set link mode. Signed-off-by: Shinas Rasheed --- V5: - No changes V4: https://lore.kernel.org/all/20240108124213.2966536-6-srasheed@marvell.com/ - Provide more stats in ndo_get_stats64 such as tx_dropped, rx_dropped etc. V3: https://lore.kernel.org/all/20240105203823.2953604-6-srasheed@marvell.com/ - No changes V2: https://lore.kernel.org/all/20231223134000.2906144-6-srasheed@marvell.com/ - No changes V1: https://lore.kernel.org/all/20231221092844.2885872-6-srasheed@marvell.com/ .../marvell/octeon_ep_vf/octep_vf_main.c | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c index 51f92c8223e8..13084cac9ce0 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c @@ -187,6 +187,23 @@ static netdev_tx_t octep_vf_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } +int octep_vf_get_if_stats(struct octep_vf_device *oct) +{ + struct octep_vf_iface_rxtx_stats vf_stats; + int ret, size; + + memset(&vf_stats, 0, sizeof(struct octep_vf_iface_rxtx_stats)); + ret = octep_vf_mbox_bulk_read(oct, OCTEP_PFVF_MBOX_CMD_GET_STATS, + (u8 *)&vf_stats, &size); + if (!ret) { + memcpy(&oct->iface_rx_stats, &vf_stats.iface_rx_stats, + sizeof(struct octep_vf_iface_rx_stats)); + memcpy(&oct->iface_tx_stats, &vf_stats.iface_tx_stats, + sizeof(struct octep_vf_iface_tx_stats)); + } + return ret; +} + int octep_vf_get_link_info(struct octep_vf_device *oct) { int ret, size; @@ -200,6 +217,46 @@ int octep_vf_get_link_info(struct octep_vf_device *oct) return 0; } +/** + * octep_vf_get_stats64() - Get Octeon network device statistics. + * + * @netdev: kernel network device. + * @stats: pointer to stats structure to be filled in. + */ +static void octep_vf_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *stats) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + u64 tx_packets, tx_bytes, rx_packets, rx_bytes; + int q; + + tx_packets = 0; + tx_bytes = 0; + rx_packets = 0; + rx_bytes = 0; + for (q = 0; q < oct->num_oqs; q++) { + struct octep_vf_iq *iq = oct->iq[q]; + struct octep_vf_oq *oq = oct->oq[q]; + + tx_packets += iq->stats.instr_completed; + tx_bytes += iq->stats.bytes_sent; + rx_packets += oq->stats.packets; + rx_bytes += oq->stats.bytes; + } + stats->tx_packets = tx_packets; + stats->tx_bytes = tx_bytes; + stats->rx_packets = rx_packets; + stats->rx_bytes = rx_bytes; + if (!octep_vf_get_if_stats(oct)) { + stats->multicast = oct->iface_rx_stats.mcast_pkts; + stats->rx_errors = oct->iface_rx_stats.err_pkts; + stats->rx_dropped = oct->iface_rx_stats.dropped_pkts_fifo_full + + oct->iface_rx_stats.err_pkts; + stats->rx_missed_errors = oct->iface_rx_stats.dropped_pkts_fifo_full; + stats->tx_dropped = oct->iface_tx_stats.dropped; + } +} + /** * octep_vf_tx_timeout_task - work queue task to Handle Tx queue timeout. * @@ -312,6 +369,7 @@ static const struct net_device_ops octep_vf_netdev_ops = { .ndo_open = octep_vf_open, .ndo_stop = octep_vf_stop, .ndo_start_xmit = octep_vf_start_xmit, + .ndo_get_stats64 = octep_vf_get_stats64, .ndo_tx_timeout = octep_vf_tx_timeout, .ndo_set_mac_address = octep_vf_set_mac, .ndo_change_mtu = octep_vf_change_mtu, From patchwork Mon Jan 29 05:02:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shinas Rasheed X-Patchwork-Id: 193240 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2087:b0:106:209c:c626 with SMTP id gs7csp367607dyb; Sun, 28 Jan 2024 21:08:51 -0800 (PST) X-Google-Smtp-Source: AGHT+IGyjbkiVxhK8zFT7RWth8UyJFWK1xKsJojQ4VdBQhDF3QBKfXCbY34hcqIfbirj0WKJNAh0 X-Received: by 2002:a9d:7855:0:b0:6e0:f990:fc71 with SMTP id c21-20020a9d7855000000b006e0f990fc71mr5967313otm.47.1706504931815; Sun, 28 Jan 2024 21:08:51 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706504931; cv=pass; d=google.com; s=arc-20160816; b=Hhkhr6hujTEtuUrBQNu7RzcUdDIdGv21tCzwppyF82RnZUtG71ykAMPm+yRVokW04o EaglvX7pJMgWleBy+bJUbab7Kzqh0O0cMoqTBMr01UynwvIjgWYehde2XD2MbclslNLx 49U5gcws9Utc106+nVQsf7hv01yAHVeRBKIQfTPJJTZGHr+ivnekgfUR5GIBqj5VqyZx 98VCbozA13D24GMyN69HhFtnaqqMZGhhmjOc6oKv21zU74EdV5PUY6RyxOp9aqZghSvj YoMNlkj8qWMHubMlImO52nhIYCVi+ysPkxzvTlnK0Jvo7XOj19aKYLUQTq+gFE7jEVvW K16g== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=N9I5vSKBwzfMLkflcgFwe5TErIHXWb0Q1bJEtFKBB2E=; fh=Y/Zcr0YXYeEsWchgSSogMl8sJJcf/EqHGWMcPJ+i19E=; b=BCHKJbdcfJYJuSc97j1lWI2+6D8HkjJy/IF+MK97FM9jKVTUGLN+yEVprxapJEw+Y+ fkhJPi7YIahHxvYn7q47y0V5LiWP1EzHB4evbHrY+HBq0yWVL1ofNnaM34Bu6X+SRjIN 30OKgwUrySIDXy4pb7UK0uT3IxyfJK53iDpTbDi2lTuTIvtpJo/6X7ermyv4nNoYWr2w FYRE4aQoI+yjgYGFPTMzjYQndMxFKDwRXoabI873LJ6RZ+r2IQNxX4Nif9WOQoz4DvrQ cwwAAJwmZiCrQeyxH2rZM9+MK+4xwg8sJ8EvJPDO/BE4QJ/tlXvCLhsDWos3zlG0w1Bc rX4g== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=b6xxMSXs; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42173-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42173-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id y3-20020a636403000000b005ce3c33c303si5237217pgb.301.2024.01.28.21.08.51 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Jan 2024 21:08:51 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-42173-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=b6xxMSXs; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42173-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42173-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id EB650B23EC7 for ; Mon, 29 Jan 2024 05:06:00 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CFB9351C4A; Mon, 29 Jan 2024 05:03:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="b6xxMSXs" Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD55A4E1DA; Mon, 29 Jan 2024 05:03:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.156.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504627; cv=none; b=GZg58aI9TkF/sXDnN2x3vwY5GozvJ15tpI/M/o+eA308tAfL2XP7+DaIVN46D/riYetlPioa2GyS0fHgqj3pbDsUadWXX/ICYn/sqoe3zcDZTN4mXkqxjnkqGH1orWfxwGha2lCcz2Et0BKWBVx9RcycCKyQkHmFtK5kkkDrByo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504627; c=relaxed/simple; bh=rM7k46/VajRNx1gI1BHBLl7ggyJCW94sZIOID9SAO0s=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oGIC80/8Mq8G1E4W5skYQMkzOTmOw2bK53SfBwsPCF1sDX+thVe65T4JkmOjZIOELG6SEZQv+rvt9nmGTNi3l6JeCP8zdD6sVmWNAC4NAD9w76IDvpfTCn8vnQW0Dyq4cLCK/jyyq3O27XZxu9B21YClIj6SNRK9vdc2mvZjTAE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com; spf=pass smtp.mailfrom=marvell.com; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b=b6xxMSXs; arc=none smtp.client-ip=67.231.156.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 40SMWI1h020251; Sun, 28 Jan 2024 21:03:30 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=N9I5vSKBwzfMLkflcgFwe5TErIHXWb0Q1bJEtFKBB2E=; b=b6x xMSXseSMkrA5YWjntVnV00QOSwOKfdRV5lVJEItZrcoLg48sn5iJdfU7q/mEHJ0V zQl+rHMsQ0I/JSeHcOzHVfOZlE7vA3TFDyDuXdSwdIrUgy/D1gaDLBE3jhbopF3b IXL3v6x4IGSV7Er4vWQDw+B9mekBfMhOpXMGCmQdSMQubfVl8MVODD+LHxFsM19R SpDO98y1cXdoDZ0PUv0HdvVg48cU1yKJqTBVrgRynikQfMpMJoQ78KmllObQi6Bo SH5YJ4SppP5CbiwfMNcKoBeLeu/bhsHvPLDGmVFxojYROWAP7N5kZSZxaTSpH2Gh LaOvfUYmqbFp+sCiaXA== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3vw27nbj8b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 28 Jan 2024 21:03:30 -0800 (PST) Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Sun, 28 Jan 2024 21:03:28 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Sun, 28 Jan 2024 21:03:28 -0800 Received: from ubuntu-PowerEdge-T110-II.sclab.marvell.com (unknown [10.106.27.86]) by maili.marvell.com (Postfix) with ESMTP id A71A13F703F; Sun, 28 Jan 2024 21:03:27 -0800 (PST) From: Shinas Rasheed To: , CC: , , , , , , , , , , , , Veerasenareddy Burru , Satananda Burla , "David S. Miller" , Eric Dumazet Subject: [PATCH net-next v5 6/8] octeon_ep_vf: add Tx/Rx processing and interrupt support Date: Sun, 28 Jan 2024 21:02:52 -0800 Message-ID: <20240129050254.3047778-7-srasheed@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240129050254.3047778-1-srasheed@marvell.com> References: <20240129050254.3047778-1-srasheed@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: 3pQvBMT8Vl-d24efpN8DGleaTU7I75xl X-Proofpoint-GUID: 3pQvBMT8Vl-d24efpN8DGleaTU7I75xl X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-01-29_02,2024-01-25_01,2023-05-22_02 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789400114909499348 X-GMAIL-MSGID: 1789400114909499348 Add support to enable MSI-x and register interrupts. Add support to process Tx and Rx traffic. Includes processing Tx completions and Rx refill. Signed-off-by: Shinas Rasheed --- V5: - No changes V4: https://lore.kernel.org/all/20240108124213.2966536-7-srasheed@marvell.com/ - Replaced code in IQ full check function to use helper from net/netdev_queues.h - Refactored code so that NETDEV_TX_BUSY is avoided V3: https://lore.kernel.org/all/20240105203823.2953604-7-srasheed@marvell.com/ - Set static budget of 64 for tx completion processing in NAPI - Replaces napi_complete and build_skb APIs to napi_complete_done and napi_build_skb APIs respectively - Replaced code with helper from net/netdev_queues.h to wake queues in TX completion processing - Moved null pointer casting corrections to earlier patch V2: https://lore.kernel.org/all/20231223134000.2906144-7-srasheed@marvell.com/ - Corrected Makefile entry to include building octep_vf_mbox.c - Removed redundant vzalloc pointer cast and vfree pointer check V1: https://lore.kernel.org/all/20231221092844.2885872-7-srasheed@marvell.com/ .../marvell/octeon_ep_vf/octep_vf_main.c | 550 ++++++++++++++++++ .../marvell/octeon_ep_vf/octep_vf_rx.c | 247 ++++++++ .../marvell/octeon_ep_vf/octep_vf_tx.c | 71 +++ 3 files changed, 868 insertions(+) diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c index 13084cac9ce0..a2e56973c39e 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "octep_vf_config.h" #include "octep_vf_main.h" @@ -36,6 +37,372 @@ MODULE_AUTHOR("Veerasenareddy Burru "); MODULE_DESCRIPTION(OCTEP_VF_DRV_STRING); MODULE_LICENSE("GPL"); +/** + * octep_vf_alloc_ioq_vectors() - Allocate Tx/Rx Queue interrupt info. + * + * @oct: Octeon device private data structure. + * + * Allocate resources to hold per Tx/Rx queue interrupt info. + * This is the information passed to interrupt handler, from which napi poll + * is scheduled and includes quick access to private data of Tx/Rx queue + * corresponding to the interrupt being handled. + * + * Return: 0, on successful allocation of resources for all queue interrupts. + * -1, if failed to allocate any resource. + */ +static int octep_vf_alloc_ioq_vectors(struct octep_vf_device *oct) +{ + struct octep_vf_ioq_vector *ioq_vector; + int i; + + for (i = 0; i < oct->num_oqs; i++) { + oct->ioq_vector[i] = vzalloc(sizeof(*oct->ioq_vector[i])); + if (!oct->ioq_vector[i]) + goto free_ioq_vector; + + ioq_vector = oct->ioq_vector[i]; + ioq_vector->iq = oct->iq[i]; + ioq_vector->oq = oct->oq[i]; + ioq_vector->octep_vf_dev = oct; + } + + dev_info(&oct->pdev->dev, "Allocated %d IOQ vectors\n", oct->num_oqs); + return 0; + +free_ioq_vector: + while (i) { + i--; + vfree(oct->ioq_vector[i]); + oct->ioq_vector[i] = NULL; + } + return -1; +} + +/** + * octep_vf_free_ioq_vectors() - Free Tx/Rx Queue interrupt vector info. + * + * @oct: Octeon device private data structure. + */ +static void octep_vf_free_ioq_vectors(struct octep_vf_device *oct) +{ + int i; + + for (i = 0; i < oct->num_oqs; i++) { + if (oct->ioq_vector[i]) { + vfree(oct->ioq_vector[i]); + oct->ioq_vector[i] = NULL; + } + } + netdev_info(oct->netdev, "Freed IOQ Vectors\n"); +} + +/** + * octep_vf_enable_msix_range() - enable MSI-x interrupts. + * + * @oct: Octeon device private data structure. + * + * Allocate and enable all MSI-x interrupts (queue and non-queue interrupts) + * for the Octeon device. + * + * Return: 0, on successfully enabling all MSI-x interrupts. + * -1, if failed to enable any MSI-x interrupt. + */ +static int octep_vf_enable_msix_range(struct octep_vf_device *oct) +{ + int num_msix, msix_allocated; + int i; + + /* Generic interrupts apart from input/output queues */ + //num_msix = oct->num_oqs + CFG_GET_NON_IOQ_MSIX(oct->conf); + num_msix = oct->num_oqs; + oct->msix_entries = kcalloc(num_msix, sizeof(struct msix_entry), GFP_KERNEL); + if (!oct->msix_entries) + goto msix_alloc_err; + + for (i = 0; i < num_msix; i++) + oct->msix_entries[i].entry = i; + + msix_allocated = pci_enable_msix_range(oct->pdev, oct->msix_entries, + num_msix, num_msix); + if (msix_allocated != num_msix) { + dev_err(&oct->pdev->dev, + "Failed to enable %d msix irqs; got only %d\n", + num_msix, msix_allocated); + goto enable_msix_err; + } + oct->num_irqs = msix_allocated; + dev_info(&oct->pdev->dev, "MSI-X enabled successfully\n"); + + return 0; + +enable_msix_err: + if (msix_allocated > 0) + pci_disable_msix(oct->pdev); + kfree(oct->msix_entries); + oct->msix_entries = NULL; +msix_alloc_err: + return -1; +} + +/** + * octep_vf_disable_msix() - disable MSI-x interrupts. + * + * @oct: Octeon device private data structure. + * + * Disable MSI-x on the Octeon device. + */ +static void octep_vf_disable_msix(struct octep_vf_device *oct) +{ + pci_disable_msix(oct->pdev); + kfree(oct->msix_entries); + oct->msix_entries = NULL; + dev_info(&oct->pdev->dev, "Disabled MSI-X\n"); +} + +/** + * octep_vf_ioq_intr_handler() - handler for all Tx/Rx queue interrupts. + * + * @irq: Interrupt number. + * @data: interrupt data contains pointers to Tx/Rx queue private data + * and correspong NAPI context. + * + * this is common handler for all non-queue (generic) interrupts. + */ +static irqreturn_t octep_vf_ioq_intr_handler(int irq, void *data) +{ + struct octep_vf_ioq_vector *ioq_vector = data; + struct octep_vf_device *oct = ioq_vector->octep_vf_dev; + + return oct->hw_ops.ioq_intr_handler(ioq_vector); +} + +/** + * octep_vf_request_irqs() - Register interrupt handlers. + * + * @oct: Octeon device private data structure. + * + * Register handlers for all queue and non-queue interrupts. + * + * Return: 0, on successful registration of all interrupt handlers. + * -1, on any error. + */ +static int octep_vf_request_irqs(struct octep_vf_device *oct) +{ + struct net_device *netdev = oct->netdev; + struct octep_vf_ioq_vector *ioq_vector; + struct msix_entry *msix_entry; + int ret, i; + + /* Request IRQs for Tx/Rx queues */ + for (i = 0; i < oct->num_oqs; i++) { + ioq_vector = oct->ioq_vector[i]; + msix_entry = &oct->msix_entries[i]; + + snprintf(ioq_vector->name, sizeof(ioq_vector->name), + "%s-q%d", netdev->name, i); + ret = request_irq(msix_entry->vector, + octep_vf_ioq_intr_handler, 0, + ioq_vector->name, ioq_vector); + if (ret) { + netdev_err(netdev, + "request_irq failed for Q-%d; err=%d", + i, ret); + goto ioq_irq_err; + } + + cpumask_set_cpu(i % num_online_cpus(), + &ioq_vector->affinity_mask); + irq_set_affinity_hint(msix_entry->vector, + &ioq_vector->affinity_mask); + } + + return 0; +ioq_irq_err: + while (i) { + --i; + free_irq(oct->msix_entries[i].vector, oct); + } + return -1; +} + +/** + * octep_vf_free_irqs() - free all registered interrupts. + * + * @oct: Octeon device private data structure. + * + * Free all queue and non-queue interrupts of the Octeon device. + */ +static void octep_vf_free_irqs(struct octep_vf_device *oct) +{ + int i; + + for (i = 0; i < oct->num_irqs; i++) { + irq_set_affinity_hint(oct->msix_entries[i].vector, NULL); + free_irq(oct->msix_entries[i].vector, oct->ioq_vector[i]); + } + netdev_info(oct->netdev, "IRQs freed\n"); +} + +/** + * octep_vf_setup_irqs() - setup interrupts for the Octeon device. + * + * @oct: Octeon device private data structure. + * + * Allocate data structures to hold per interrupt information, allocate/enable + * MSI-x interrupt and register interrupt handlers. + * + * Return: 0, on successful allocation and registration of all interrupts. + * -1, on any error. + */ +static int octep_vf_setup_irqs(struct octep_vf_device *oct) +{ + if (octep_vf_alloc_ioq_vectors(oct)) + goto ioq_vector_err; + + if (octep_vf_enable_msix_range(oct)) + goto enable_msix_err; + + if (octep_vf_request_irqs(oct)) + goto request_irq_err; + + return 0; + +request_irq_err: + octep_vf_disable_msix(oct); +enable_msix_err: + octep_vf_free_ioq_vectors(oct); +ioq_vector_err: + return -1; +} + +/** + * octep_vf_clean_irqs() - free all interrupts and its resources. + * + * @oct: Octeon device private data structure. + */ +static void octep_vf_clean_irqs(struct octep_vf_device *oct) +{ + octep_vf_free_irqs(oct); + octep_vf_disable_msix(oct); + octep_vf_free_ioq_vectors(oct); +} + +/** + * octep_vf_enable_ioq_irq() - Enable MSI-x interrupt of a Tx/Rx queue. + * + * @iq: Octeon Tx queue data structure. + * @oq: Octeon Rx queue data structure. + */ +static void octep_vf_enable_ioq_irq(struct octep_vf_iq *iq, struct octep_vf_oq *oq) +{ + u32 pkts_pend = oq->pkts_pending; + + netdev_dbg(iq->netdev, "enabling intr for Q-%u\n", iq->q_no); + if (iq->pkts_processed) { + writel(iq->pkts_processed, iq->inst_cnt_reg); + iq->pkt_in_done -= iq->pkts_processed; + iq->pkts_processed = 0; + } + if (oq->last_pkt_count - pkts_pend) { + writel(oq->last_pkt_count - pkts_pend, oq->pkts_sent_reg); + oq->last_pkt_count = pkts_pend; + } + + /* Flush the previous wrties before writing to RESEND bit */ + smp_wmb(); + writeq(1UL << OCTEP_VF_OQ_INTR_RESEND_BIT, oq->pkts_sent_reg); + writeq(1UL << OCTEP_VF_IQ_INTR_RESEND_BIT, iq->inst_cnt_reg); +} + +/** + * octep_vf_napi_poll() - NAPI poll function for Tx/Rx. + * + * @napi: pointer to napi context. + * @budget: max number of packets to be processed in single invocation. + */ +static int octep_vf_napi_poll(struct napi_struct *napi, int budget) +{ + struct octep_vf_ioq_vector *ioq_vector = + container_of(napi, struct octep_vf_ioq_vector, napi); + u32 tx_pending, rx_done; + + tx_pending = octep_vf_iq_process_completions(ioq_vector->iq, 64); + rx_done = octep_vf_oq_process_rx(ioq_vector->oq, budget); + + /* need more polling if tx completion processing is still pending or + * processed at least 'budget' number of rx packets. + */ + if (tx_pending || rx_done >= budget) + return budget; + + if (likely(napi_complete_done(napi, rx_done))) + octep_vf_enable_ioq_irq(ioq_vector->iq, ioq_vector->oq); + + return rx_done; +} + +/** + * octep_vf_napi_add() - Add NAPI poll for all Tx/Rx queues. + * + * @oct: Octeon device private data structure. + */ +static void octep_vf_napi_add(struct octep_vf_device *oct) +{ + int i; + + for (i = 0; i < oct->num_oqs; i++) { + netdev_dbg(oct->netdev, "Adding NAPI on Q-%d\n", i); + netif_napi_add(oct->netdev, &oct->ioq_vector[i]->napi, octep_vf_napi_poll); + oct->oq[i]->napi = &oct->ioq_vector[i]->napi; + } +} + +/** + * octep_vf_napi_delete() - delete NAPI poll callback for all Tx/Rx queues. + * + * @oct: Octeon device private data structure. + */ +static void octep_vf_napi_delete(struct octep_vf_device *oct) +{ + int i; + + for (i = 0; i < oct->num_oqs; i++) { + netdev_dbg(oct->netdev, "Deleting NAPI on Q-%d\n", i); + netif_napi_del(&oct->ioq_vector[i]->napi); + oct->oq[i]->napi = NULL; + } +} + +/** + * octep_vf_napi_enable() - enable NAPI for all Tx/Rx queues. + * + * @oct: Octeon device private data structure. + */ +static void octep_vf_napi_enable(struct octep_vf_device *oct) +{ + int i; + + for (i = 0; i < oct->num_oqs; i++) { + netdev_dbg(oct->netdev, "Enabling NAPI on Q-%d\n", i); + napi_enable(&oct->ioq_vector[i]->napi); + } +} + +/** + * octep_vf_napi_disable() - disable NAPI for all Tx/Rx queues. + * + * @oct: Octeon device private data structure. + */ +static void octep_vf_napi_disable(struct octep_vf_device *oct) +{ + int i; + + for (i = 0; i < oct->num_oqs; i++) { + netdev_dbg(oct->netdev, "Disabling NAPI on Q-%d\n", i); + napi_disable(&oct->ioq_vector[i]->napi); + } +} + static void octep_vf_link_up(struct net_device *netdev) { netif_carrier_on(netdev); @@ -98,6 +465,8 @@ static int octep_vf_open(struct net_device *netdev) goto setup_iq_err; if (octep_vf_setup_oqs(oct)) goto setup_oq_err; + if (octep_vf_setup_irqs(oct)) + goto setup_irq_err; err = netif_set_real_num_tx_queues(netdev, oct->num_oqs); if (err) @@ -106,6 +475,9 @@ static int octep_vf_open(struct net_device *netdev) if (err) goto set_queues_err; + octep_vf_napi_add(oct); + octep_vf_napi_enable(oct); + oct->link_info.admin_up = 1; octep_vf_set_rx_state(oct, true); @@ -128,6 +500,10 @@ static int octep_vf_open(struct net_device *netdev) return 0; set_queues_err: + octep_vf_napi_disable(oct); + octep_vf_napi_delete(oct); + octep_vf_clean_irqs(oct); +setup_irq_err: octep_vf_free_oqs(oct); setup_oq_err: octep_vf_free_iqs(oct); @@ -161,7 +537,10 @@ static int octep_vf_stop(struct net_device *netdev) oct->link_info.oper_up = 0; oct->hw_ops.disable_interrupts(oct); + octep_vf_napi_disable(oct); + octep_vf_napi_delete(oct); + octep_vf_clean_irqs(oct); octep_vf_clean_iqs(oct); oct->hw_ops.disable_io_queues(oct); @@ -172,6 +551,39 @@ static int octep_vf_stop(struct net_device *netdev) return 0; } +/** + * octep_vf_iq_full_check() - check if a Tx queue is full. + * + * @iq: Octeon Tx queue data structure. + * + * Return: 0, if the Tx queue is not full. + * 1, if the Tx queue is full. + */ +static int octep_vf_iq_full_check(struct octep_vf_iq *iq) +{ + int ret; + + ret = netif_subqueue_maybe_stop(iq->netdev, iq->q_no, IQ_INSTR_SPACE(iq), + OCTEP_VF_WAKE_QUEUE_THRESHOLD, + OCTEP_VF_WAKE_QUEUE_THRESHOLD); + switch (ret) { + case 0: /* Stopped the queue, since IQ is full */ + return 1; + case -1: /* + * Pending updates in write index from + * iq_process_completion in other cpus + * caused queues to get re-enabled after + * being stopped + */ + iq->stats.restart_cnt++; + fallthrough; + case 1: /* Queue left enabled, since IQ is not yet full*/ + return 0; + } + + return 1; +} + /** * octep_vf_start_xmit() - Enqueue packet to Octoen hardware Tx Queue. * @@ -184,6 +596,144 @@ static int octep_vf_stop(struct net_device *netdev) static netdev_tx_t octep_vf_start_xmit(struct sk_buff *skb, struct net_device *netdev) { + struct octep_vf_device *oct = netdev_priv(netdev); + netdev_features_t feat = netdev->features; + struct octep_vf_tx_sglist_desc *sglist; + struct octep_vf_tx_buffer *tx_buffer; + struct octep_vf_tx_desc_hw *hw_desc; + struct skb_shared_info *shinfo; + struct octep_vf_instr_hdr *ih; + struct octep_vf_iq *iq; + skb_frag_t *frag; + u16 nr_frags, si; + int xmit_more; + u16 q_no, wi; + + if (skb_put_padto(skb, ETH_ZLEN)) + return NETDEV_TX_OK; + + q_no = skb_get_queue_mapping(skb); + if (q_no >= oct->num_iqs) { + netdev_err(netdev, "Invalid Tx skb->queue_mapping=%d\n", q_no); + q_no = q_no % oct->num_iqs; + } + + iq = oct->iq[q_no]; + + shinfo = skb_shinfo(skb); + nr_frags = shinfo->nr_frags; + + wi = iq->host_write_index; + hw_desc = &iq->desc_ring[wi]; + hw_desc->ih64 = 0; + + tx_buffer = iq->buff_info + wi; + tx_buffer->skb = skb; + + ih = &hw_desc->ih; + ih->tlen = skb->len; + ih->pkind = oct->fw_info.pkind; + ih->fsz = oct->fw_info.fsz; + ih->tlen = skb->len + ih->fsz; + + if (!nr_frags) { + tx_buffer->gather = 0; + tx_buffer->dma = dma_map_single(iq->dev, skb->data, + skb->len, DMA_TO_DEVICE); + if (dma_mapping_error(iq->dev, tx_buffer->dma)) + goto dma_map_err; + hw_desc->dptr = tx_buffer->dma; + } else { + /* Scatter/Gather */ + dma_addr_t dma; + u16 len; + + sglist = tx_buffer->sglist; + + ih->gsz = nr_frags + 1; + ih->gather = 1; + tx_buffer->gather = 1; + + len = skb_headlen(skb); + dma = dma_map_single(iq->dev, skb->data, len, DMA_TO_DEVICE); + if (dma_mapping_error(iq->dev, dma)) + goto dma_map_err; + + memset(sglist, 0, OCTEP_VF_SGLIST_SIZE_PER_PKT); + sglist[0].len[3] = len; + sglist[0].dma_ptr[0] = dma; + + si = 1; /* entry 0 is main skb, mapped above */ + frag = &shinfo->frags[0]; + while (nr_frags--) { + len = skb_frag_size(frag); + dma = skb_frag_dma_map(iq->dev, frag, 0, + len, DMA_TO_DEVICE); + if (dma_mapping_error(iq->dev, dma)) + goto dma_map_sg_err; + + sglist[si >> 2].len[3 - (si & 3)] = len; + sglist[si >> 2].dma_ptr[si & 3] = dma; + + frag++; + si++; + } + hw_desc->dptr = tx_buffer->sglist_dma; + } + if (oct->fw_info.tx_ol_flags) { + if ((feat & (NETIF_F_TSO)) && (skb_is_gso(skb))) { + hw_desc->txm.ol_flags = OCTEP_VF_TX_OFFLOAD_CKSUM; + hw_desc->txm.ol_flags |= OCTEP_VF_TX_OFFLOAD_TSO; + hw_desc->txm.gso_size = skb_shinfo(skb)->gso_size; + hw_desc->txm.gso_segs = skb_shinfo(skb)->gso_segs; + } else if (feat & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) { + hw_desc->txm.ol_flags = OCTEP_VF_TX_OFFLOAD_CKSUM; + } + /* due to ESR txm will be swapped by hw */ + hw_desc->txm64[0] = (__force u64)cpu_to_be64(hw_desc->txm64[0]); + } + + xmit_more = netdev_xmit_more(); + + netdev_tx_sent_queue(iq->netdev_q, skb->len); + + skb_tx_timestamp(skb); + iq->fill_cnt++; + wi++; + iq->host_write_index = wi & iq->ring_size_mask; + + /* octep_iq_full_check stops the queue and returns + * true if so, in case the queue has become full + * by inserting current packet. If so, we can + * go ahead and ring doorbell. + */ + if (!octep_vf_iq_full_check(iq) && xmit_more && + iq->fill_cnt < iq->fill_threshold) + return NETDEV_TX_OK; + + goto ring_dbell; + +dma_map_sg_err: + if (si > 0) { + dma_unmap_single(iq->dev, sglist[0].dma_ptr[0], + sglist[0].len[0], DMA_TO_DEVICE); + sglist[0].len[0] = 0; + } + while (si > 1) { + dma_unmap_page(iq->dev, sglist[si >> 2].dma_ptr[si & 3], + sglist[si >> 2].len[si & 3], DMA_TO_DEVICE); + sglist[si >> 2].len[si & 3] = 0; + si--; + } + tx_buffer->gather = 0; +dma_map_err: + dev_kfree_skb_any(skb); +ring_dbell: + /* Flush the hw descriptors before writing to doorbell */ + smp_wmb(); + writel(iq->fill_cnt, iq->doorbell_reg); + iq->stats.instr_posted += iq->fill_cnt; + iq->fill_cnt = 0; return NETDEV_TX_OK; } diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c index 330d6e72bc0b..82821bc28634 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c @@ -68,6 +68,50 @@ static int octep_vf_oq_fill_ring_buffers(struct octep_vf_oq *oq) return -ENOMEM; } +/** + * octep_vf_oq_refill() - refill buffers for used Rx ring descriptors. + * + * @oct: Octeon device private data structure. + * @oq: Octeon Rx queue data structure. + * + * Return: number of descriptors successfully refilled with receive buffers. + */ +static int octep_vf_oq_refill(struct octep_vf_device *oct, struct octep_vf_oq *oq) +{ + struct octep_vf_oq_desc_hw *desc_ring = oq->desc_ring; + struct page *page; + u32 refill_idx, i; + + refill_idx = oq->host_refill_idx; + for (i = 0; i < oq->refill_count; i++) { + page = dev_alloc_page(); + if (unlikely(!page)) { + dev_err(oq->dev, "refill: rx buffer alloc failed\n"); + oq->stats.alloc_failures++; + break; + } + + desc_ring[refill_idx].buffer_ptr = dma_map_page(oq->dev, page, 0, + PAGE_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(oq->dev, desc_ring[refill_idx].buffer_ptr)) { + dev_err(oq->dev, + "OQ-%d buffer refill: DMA mapping error!\n", + oq->q_no); + put_page(page); + oq->stats.alloc_failures++; + break; + } + oq->buff_info[refill_idx].page = page; + refill_idx++; + if (refill_idx == oq->max_count) + refill_idx = 0; + } + oq->host_refill_idx = refill_idx; + oq->refill_count -= i; + + return i; +} + /** * octep_vf_setup_oq() - Setup a Rx queue. * @@ -261,3 +305,206 @@ void octep_vf_free_oqs(struct octep_vf_device *oct) "Successfully freed OQ(RxQ)-%d.\n", i); } } + +/** + * octep_vf_oq_check_hw_for_pkts() - Check for new Rx packets. + * + * @oct: Octeon device private data structure. + * @oq: Octeon Rx queue data structure. + * + * Return: packets received after previous check. + */ +static int octep_vf_oq_check_hw_for_pkts(struct octep_vf_device *oct, + struct octep_vf_oq *oq) +{ + u32 pkt_count, new_pkts; + + pkt_count = readl(oq->pkts_sent_reg); + new_pkts = pkt_count - oq->last_pkt_count; + + /* Clear the hardware packets counter register if the rx queue is + * being processed continuously with-in a single interrupt and + * reached half its max value. + * this counter is not cleared every time read, to save write cycles. + */ + if (unlikely(pkt_count > 0xF0000000U)) { + writel(pkt_count, oq->pkts_sent_reg); + pkt_count = readl(oq->pkts_sent_reg); + new_pkts += pkt_count; + } + oq->last_pkt_count = pkt_count; + oq->pkts_pending += new_pkts; + return new_pkts; +} + +/** + * __octep_vf_oq_process_rx() - Process hardware Rx queue and push to stack. + * + * @oct: Octeon device private data structure. + * @oq: Octeon Rx queue data structure. + * @pkts_to_process: number of packets to be processed. + * + * Process the new packets in Rx queue. + * Packets larger than single Rx buffer arrive in consecutive descriptors. + * But, count returned by the API only accounts full packets, not fragments. + * + * Return: number of packets processed and pushed to stack. + */ +static int __octep_vf_oq_process_rx(struct octep_vf_device *oct, + struct octep_vf_oq *oq, u16 pkts_to_process) +{ + struct octep_vf_oq_resp_hw_ext *resp_hw_ext = NULL; + netdev_features_t feat = oq->netdev->features; + struct octep_vf_rx_buffer *buff_info; + struct octep_vf_oq_resp_hw *resp_hw; + u32 pkt, rx_bytes, desc_used; + u16 data_offset, rx_ol_flags; + struct sk_buff *skb; + u32 read_idx; + + read_idx = oq->host_read_idx; + rx_bytes = 0; + desc_used = 0; + for (pkt = 0; pkt < pkts_to_process; pkt++) { + buff_info = (struct octep_vf_rx_buffer *)&oq->buff_info[read_idx]; + dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr, + PAGE_SIZE, DMA_FROM_DEVICE); + resp_hw = page_address(buff_info->page); + buff_info->page = NULL; + + /* Swap the length field that is in Big-Endian to CPU */ + buff_info->len = be64_to_cpu(resp_hw->length); + if (oct->fw_info.rx_ol_flags) { + /* Extended response header is immediately after + * response header (resp_hw) + */ + resp_hw_ext = (struct octep_vf_oq_resp_hw_ext *) + (resp_hw + 1); + buff_info->len -= OCTEP_VF_OQ_RESP_HW_EXT_SIZE; + /* Packet Data is immediately after + * extended response header. + */ + data_offset = OCTEP_VF_OQ_RESP_HW_SIZE + + OCTEP_VF_OQ_RESP_HW_EXT_SIZE; + rx_ol_flags = resp_hw_ext->rx_ol_flags; + } else { + /* Data is immediately after + * Hardware Rx response header. + */ + data_offset = OCTEP_VF_OQ_RESP_HW_SIZE; + rx_ol_flags = 0; + } + rx_bytes += buff_info->len; + + if (buff_info->len <= oq->max_single_buffer_size) { + skb = napi_build_skb((void *)resp_hw, PAGE_SIZE); + skb_reserve(skb, data_offset); + skb_put(skb, buff_info->len); + read_idx++; + desc_used++; + if (read_idx == oq->max_count) + read_idx = 0; + } else { + struct skb_shared_info *shinfo; + u16 data_len; + + skb = napi_build_skb((void *)resp_hw, PAGE_SIZE); + skb_reserve(skb, data_offset); + /* Head fragment includes response header(s); + * subsequent fragments contains only data. + */ + skb_put(skb, oq->max_single_buffer_size); + read_idx++; + desc_used++; + if (read_idx == oq->max_count) + read_idx = 0; + + shinfo = skb_shinfo(skb); + data_len = buff_info->len - oq->max_single_buffer_size; + while (data_len) { + dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr, + PAGE_SIZE, DMA_FROM_DEVICE); + buff_info = (struct octep_vf_rx_buffer *) + &oq->buff_info[read_idx]; + if (data_len < oq->buffer_size) { + buff_info->len = data_len; + data_len = 0; + } else { + buff_info->len = oq->buffer_size; + data_len -= oq->buffer_size; + } + + skb_add_rx_frag(skb, shinfo->nr_frags, + buff_info->page, 0, + buff_info->len, + buff_info->len); + buff_info->page = NULL; + read_idx++; + desc_used++; + if (read_idx == oq->max_count) + read_idx = 0; + } + } + + skb->dev = oq->netdev; + skb->protocol = eth_type_trans(skb, skb->dev); + if (feat & NETIF_F_RXCSUM && + OCTEP_VF_RX_CSUM_VERIFIED(rx_ol_flags)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + napi_gro_receive(oq->napi, skb); + } + + oq->host_read_idx = read_idx; + oq->refill_count += desc_used; + oq->stats.packets += pkt; + oq->stats.bytes += rx_bytes; + + return pkt; +} + +/** + * octep_vf_oq_process_rx() - Process Rx queue. + * + * @oq: Octeon Rx queue data structure. + * @budget: max number of packets can be processed in one invocation. + * + * Check for newly received packets and process them. + * Keeps checking for new packets until budget is used or no new packets seen. + * + * Return: number of packets processed. + */ +int octep_vf_oq_process_rx(struct octep_vf_oq *oq, int budget) +{ + u32 pkts_available, pkts_processed, total_pkts_processed; + struct octep_vf_device *oct = oq->octep_vf_dev; + + pkts_available = 0; + pkts_processed = 0; + total_pkts_processed = 0; + while (total_pkts_processed < budget) { + /* update pending count only when current one exhausted */ + if (oq->pkts_pending == 0) + octep_vf_oq_check_hw_for_pkts(oct, oq); + pkts_available = min(budget - total_pkts_processed, + oq->pkts_pending); + if (!pkts_available) + break; + + pkts_processed = __octep_vf_oq_process_rx(oct, oq, + pkts_available); + oq->pkts_pending -= pkts_processed; + total_pkts_processed += pkts_processed; + } + + if (oq->refill_count >= oq->refill_threshold) { + u32 desc_refilled = octep_vf_oq_refill(oct, oq); + + /* flush pending writes before updating credits */ + smp_wmb(); + writel(desc_refilled, oq->pkts_credit_reg); + } + + return total_pkts_processed; +} diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c index 1a3e1a651dc4..47a5c054fdb6 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_tx.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "octep_vf_config.h" #include "octep_vf_main.h" @@ -23,6 +24,76 @@ static void octep_vf_iq_reset_indices(struct octep_vf_iq *iq) iq->pkt_in_done = 0; } +/** + * octep_vf_iq_process_completions() - Process Tx queue completions. + * + * @iq: Octeon Tx queue data structure. + * @budget: max number of completions to be processed in one invocation. + */ +int octep_vf_iq_process_completions(struct octep_vf_iq *iq, u16 budget) +{ + u32 compl_pkts, compl_bytes, compl_sg; + struct octep_vf_device *oct = iq->octep_vf_dev; + struct octep_vf_tx_buffer *tx_buffer; + struct skb_shared_info *shinfo; + u32 fi = iq->flush_index; + struct sk_buff *skb; + u8 frags, i; + + compl_pkts = 0; + compl_sg = 0; + compl_bytes = 0; + iq->octep_vf_read_index = oct->hw_ops.update_iq_read_idx(iq); + + while (likely(budget && (fi != iq->octep_vf_read_index))) { + tx_buffer = iq->buff_info + fi; + skb = tx_buffer->skb; + + fi++; + if (unlikely(fi == iq->max_count)) + fi = 0; + compl_bytes += skb->len; + compl_pkts++; + budget--; + + if (!tx_buffer->gather) { + dma_unmap_single(iq->dev, tx_buffer->dma, + tx_buffer->skb->len, DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + continue; + } + + /* Scatter/Gather */ + shinfo = skb_shinfo(skb); + frags = shinfo->nr_frags; + compl_sg++; + + dma_unmap_single(iq->dev, tx_buffer->sglist[0].dma_ptr[0], + tx_buffer->sglist[0].len[3], DMA_TO_DEVICE); + + i = 1; /* entry 0 is main skb, unmapped above */ + while (frags--) { + dma_unmap_page(iq->dev, tx_buffer->sglist[i >> 2].dma_ptr[i & 3], + tx_buffer->sglist[i >> 2].len[3 - (i & 3)], DMA_TO_DEVICE); + i++; + } + + dev_kfree_skb_any(skb); + } + + iq->pkts_processed += compl_pkts; + iq->stats.instr_completed += compl_pkts; + iq->stats.bytes_sent += compl_bytes; + iq->stats.sgentry_sent += compl_sg; + iq->flush_index = fi; + + netif_subqueue_completed_wake(iq->netdev, iq->q_no, compl_pkts, + compl_bytes, IQ_INSTR_SPACE(iq), + OCTEP_VF_WAKE_QUEUE_THRESHOLD); + + return !budget; +} + /** * octep_vf_iq_free_pending() - Free Tx buffers for pending completions. * From patchwork Mon Jan 29 05:02:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shinas Rasheed X-Patchwork-Id: 193236 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2087:b0:106:209c:c626 with SMTP id gs7csp366636dyb; Sun, 28 Jan 2024 21:05:55 -0800 (PST) X-Google-Smtp-Source: AGHT+IEoRmgIW0KvfeEGxoZrWbi5mPA0CvKc1r2w9huyDGxe3zymNkfPrLd+MDi6sFSM7CZdP/70 X-Received: by 2002:ac8:5ad3:0:b0:42a:990d:50ea with SMTP id d19-20020ac85ad3000000b0042a990d50eamr2904796qtd.6.1706504754974; Sun, 28 Jan 2024 21:05:54 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706504754; cv=pass; d=google.com; s=arc-20160816; b=RjCGqiBQAaumAdQDP1e66QfkNXEGdZdsTOjmMHNRy8AI2JRld6BMYOVEpFUEYIHjsU 3ApP8XQMskOyGZ1+xKtoaKrhIIRY+5Dt2xLXkCMiOFPXXaaAx2f2B8z/YtCqWnpwu79X Lk9jYpdHioluVQxcIBT1V895D23j+EzLuzZiN3Rt+BfB6ZqpfaEwG66tj7VHVlvekZ9q 5aXZte4OMUzBaM7aOpmI9R7qCCu5Y8J+sIH6aE0qRR814psHfDkoxG/GxSwBhQLy01u2 hKY20hWtx6QxWFc1t23sOPkCEAT70HHHNXfZK/5V7uLPbWx1cKKo3nl3nwSgiykSPVwm 7SUg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=+kvS1QxmQ/Wdk07+od8wFyszLIrQ+4l0G6m7sQhHly8=; fh=Y/Zcr0YXYeEsWchgSSogMl8sJJcf/EqHGWMcPJ+i19E=; b=mX0xVyIIjhUW6JLF+SodEz/PhG2RZ9jXs4Mu/MO8a5r4OtWU8SDmaC0WAxXrBLyE6V T8kifJu+BrR+uW93vJLhZ2Mgc+ythUacPodeKqTU7ccoVMv/TCgn9AirrGEykdxXsu9Q iP2mIiJ6uPrkDFw2KUTQFKnjIYcZ0S0a2IB1eQvbeNe7Maa6AwIkAV699X1rtFkv1rNB 8jv8cGdZbj2iRgehO5UfRnaI3fcTxUYwHG+LUsaaXPJ4sVKp3pXXYwNMOoRlORuojU4m 5b3RhVq5izNjlYYKdkBfK3a8A8mHOyyjHiSm7nM9BLCgHQu6nV/0x3+Q9YSizcr6ePBl ACpw== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=inO+zzjf; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42172-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42172-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id q16-20020a05622a04d000b0042a9d4326e7si2376157qtx.243.2024.01.28.21.05.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Jan 2024 21:05:54 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-42172-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=inO+zzjf; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42172-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42172-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 2F7401C2247B for ; Mon, 29 Jan 2024 05:05:42 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C6C1F51020; Mon, 29 Jan 2024 05:03:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="inO+zzjf" Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F27A4D5A0; Mon, 29 Jan 2024 05:03:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.148.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504625; cv=none; b=DPeVwiLL1FviRmLEqszFWhVUA++BKCcQLtnk6D1kCbWCXIbQCzGYF29pqwVsWjcs+YO418cVrLU/Enx0ypJpsXxtihjanzvygKjxH0OAgBmhnP8rad2BsELg0qBWDLZ+IvVgwvC3Jt2xQRxIGpVgPF0vx7JUKp/s3UkliS/VwbY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504625; c=relaxed/simple; bh=VDWy5ha0ML+GPRyfJelPVKo953QF9ZZ1hyJRA1u+T28=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LBga9mSVIpXqSYx9cKIx/kLiLOpx0XO6mcJD5oz34g7TjTWaGh3QOBC6yWP1Bk3Vwkfs1oGVH8g0oc6J5X0obTeRazHkie81PA5FMSvQ5c9hgDYxXTrhAABuNgjm9zS+OvcqUPOqDQldgwilYDEr2uaBT2aanmwc5DBN1F4wX4A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com; spf=pass smtp.mailfrom=marvell.com; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b=inO+zzjf; arc=none smtp.client-ip=67.231.148.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 40T4KEjA027114; Sun, 28 Jan 2024 21:03:33 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=+kvS1QxmQ/Wdk07+od8wFyszLIrQ+4l0G6m7sQhHly8=; b=inO +zzjf9kUevaCAwG+dyQQENC1txkPU9TbTboOLz0hKjDgaZmqTYVm+HHNoUKp5RYm E6wixOiI7yqYiSjQwfVawXHSdUD9LYfhbVqdWdOsERUktu6dvJYUBhgR9KWfvs1u S7IPM2z5pazgQn6d7Rm57L+tvdwCR1wTeDVpQJY/Jv/crce6/AyjradOrwnA8E14 LidyBaUdqd5xnkt9XlQzG+E3y+Iy8NSGWuBua59Mz5J4gL/pNObrV2DORoquus7r EvQvPIlkTh7mnbszzUCpQ8M5TW7wjdThpBBqytVD5pYQdXbn47CYsLOd+Cho5f6+ 82xhQco+fv7ozaohnDA== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3vx4vr82dt-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 28 Jan 2024 21:03:33 -0800 (PST) Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Sun, 28 Jan 2024 21:03:32 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Sun, 28 Jan 2024 21:03:32 -0800 Received: from ubuntu-PowerEdge-T110-II.sclab.marvell.com (unknown [10.106.27.86]) by maili.marvell.com (Postfix) with ESMTP id AB53F3F7053; Sun, 28 Jan 2024 21:03:31 -0800 (PST) From: Shinas Rasheed To: , CC: , , , , , , , , , , , , Veerasenareddy Burru , Satananda Burla , "David S. Miller" , Eric Dumazet Subject: [PATCH net-next v5 7/8] octeon_ep_vf: add ethtool support Date: Sun, 28 Jan 2024 21:02:53 -0800 Message-ID: <20240129050254.3047778-8-srasheed@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240129050254.3047778-1-srasheed@marvell.com> References: <20240129050254.3047778-1-srasheed@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: RJocwmkTICj6mYznwIA3v5xlq-RF-15_ X-Proofpoint-GUID: RJocwmkTICj6mYznwIA3v5xlq-RF-15_ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-01-29_02,2024-01-25_01,2023-05-22_02 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789399930186361110 X-GMAIL-MSGID: 1789399930186361110 Add support for the following ethtool commands: ethtool -i|--driver devname ethtool devname ethtool -S|--statistics devname Signed-off-by: Shinas Rasheed --- V5: - No changes V4: https://lore.kernel.org/all/20240108124213.2966536-8-srasheed@marvell.com/ - Removed stats which are already sent in ndo_get_stats64 V3: https://lore.kernel.org/all/20240105203823.2953604-8-srasheed@marvell.com/ - Removed duplicate reporting of TX/RX packets/bytes, which is already done during ndo_get_stats64 V2: https://lore.kernel.org/all/20231223134000.2906144-8-srasheed@marvell.com/ - No changes V1: https://lore.kernel.org/all/20231221092844.2885872-8-srasheed@marvell.com/ .../ethernet/marvell/octeon_ep_vf/Makefile | 3 +- .../marvell/octeon_ep_vf/octep_vf_ethtool.c | 273 ++++++++++++++++++ .../marvell/octeon_ep_vf/octep_vf_main.c | 1 + .../marvell/octeon_ep_vf/octep_vf_main.h | 1 + 4 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_ethtool.c diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/Makefile b/drivers/net/ethernet/marvell/octeon_ep_vf/Makefile index 694eb9b46e99..4a5f9fcb0b40 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/Makefile +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_OCTEON_EP_VF) += octeon_ep_vf.o octeon_ep_vf-y := octep_vf_main.o octep_vf_cn9k.o octep_vf_cnxk.o \ - octep_vf_tx.o octep_vf_rx.o octep_vf_mbox.o + octep_vf_tx.o octep_vf_rx.o octep_vf_mbox.o \ + octep_vf_ethtool.o diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_ethtool.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_ethtool.c new file mode 100644 index 000000000000..a1979b45e355 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_ethtool.c @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell Octeon EP (EndPoint) VF Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#include +#include +#include + +#include "octep_vf_config.h" +#include "octep_vf_main.h" + +static const char octep_vf_gstrings_global_stats[][ETH_GSTRING_LEN] = { + "rx_alloc_errors", + "tx_busy_errors", + "tx_hw_pkts", + "tx_hw_octs", + "tx_hw_bcast", + "tx_hw_mcast", + "rx_hw_pkts", + "rx_hw_bytes", + "rx_hw_bcast", + "rx_dropped_bytes_fifo_full", +}; + +#define OCTEP_VF_GLOBAL_STATS_CNT (sizeof(octep_vf_gstrings_global_stats) / ETH_GSTRING_LEN) + +static const char octep_vf_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = { + "tx_packets_posted[Q-%u]", + "tx_packets_completed[Q-%u]", + "tx_bytes[Q-%u]", + "tx_busy[Q-%u]", +}; + +#define OCTEP_VF_TX_Q_STATS_CNT (sizeof(octep_vf_gstrings_tx_q_stats) / ETH_GSTRING_LEN) + +static const char octep_vf_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = { + "rx_packets[Q-%u]", + "rx_bytes[Q-%u]", + "rx_alloc_errors[Q-%u]", +}; + +#define OCTEP_VF_RX_Q_STATS_CNT (sizeof(octep_vf_gstrings_rx_q_stats) / ETH_GSTRING_LEN) + +static void octep_vf_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + + strscpy(info->driver, OCTEP_VF_DRV_NAME, sizeof(info->driver)); + strscpy(info->bus_info, pci_name(oct->pdev), sizeof(info->bus_info)); +} + +static void octep_vf_get_strings(struct net_device *netdev, + u32 stringset, u8 *data) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + char *strings = (char *)data; + int i, j; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < OCTEP_VF_GLOBAL_STATS_CNT; i++) { + snprintf(strings, ETH_GSTRING_LEN, + octep_vf_gstrings_global_stats[i]); + strings += ETH_GSTRING_LEN; + } + + for (i = 0; i < num_queues; i++) { + for (j = 0; j < OCTEP_VF_TX_Q_STATS_CNT; j++) { + snprintf(strings, ETH_GSTRING_LEN, + octep_vf_gstrings_tx_q_stats[j], i); + strings += ETH_GSTRING_LEN; + } + } + + for (i = 0; i < num_queues; i++) { + for (j = 0; j < OCTEP_VF_RX_Q_STATS_CNT; j++) { + snprintf(strings, ETH_GSTRING_LEN, + octep_vf_gstrings_rx_q_stats[j], i); + strings += ETH_GSTRING_LEN; + } + } + break; + default: + break; + } +} + +static int octep_vf_get_sset_count(struct net_device *netdev, int sset) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + + switch (sset) { + case ETH_SS_STATS: + return OCTEP_VF_GLOBAL_STATS_CNT + (num_queues * + (OCTEP_VF_TX_Q_STATS_CNT + OCTEP_VF_RX_Q_STATS_CNT)); + break; + default: + return -EOPNOTSUPP; + } +} + +static void octep_vf_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + struct octep_vf_iface_tx_stats *iface_tx_stats; + struct octep_vf_iface_rx_stats *iface_rx_stats; + u64 rx_alloc_errors, tx_busy_errors; + int q, i; + + rx_alloc_errors = 0; + tx_busy_errors = 0; + + octep_vf_get_if_stats(oct); + iface_tx_stats = &oct->iface_tx_stats; + iface_rx_stats = &oct->iface_rx_stats; + + for (q = 0; q < oct->num_oqs; q++) { + struct octep_vf_iq *iq = oct->iq[q]; + struct octep_vf_oq *oq = oct->oq[q]; + + tx_busy_errors += iq->stats.tx_busy; + rx_alloc_errors += oq->stats.alloc_failures; + } + i = 0; + data[i++] = rx_alloc_errors; + data[i++] = tx_busy_errors; + data[i++] = iface_tx_stats->pkts; + data[i++] = iface_tx_stats->octs; + data[i++] = iface_tx_stats->bcst; + data[i++] = iface_tx_stats->mcst; + data[i++] = iface_rx_stats->pkts; + data[i++] = iface_rx_stats->octets; + data[i++] = iface_rx_stats->bcast_pkts; + data[i++] = iface_rx_stats->dropped_octets_fifo_full; + + /* Per Tx Queue stats */ + for (q = 0; q < oct->num_iqs; q++) { + struct octep_vf_iq *iq = oct->iq[q]; + + data[i++] = iq->stats.instr_posted; + data[i++] = iq->stats.instr_completed; + data[i++] = iq->stats.bytes_sent; + data[i++] = iq->stats.tx_busy; + } + + /* Per Rx Queue stats */ + for (q = 0; q < oct->num_oqs; q++) { + struct octep_vf_oq *oq = oct->oq[q]; + + data[i++] = oq->stats.packets; + data[i++] = oq->stats.bytes; + data[i++] = oq->stats.alloc_failures; + } +} + +#define OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(octep_vf_speeds, ksettings, name) \ +{ \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_T)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseT_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_R)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseR_FEC); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_CR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseCR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_KR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseKR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_LR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseLR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_SR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseSR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_CR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseCR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_KR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseKR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_SR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseSR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_CR4)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseCR4_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_KR4)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseKR4_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_LR4)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseLR4_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_SR4)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseSR4_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_CR2)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR2_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_KR2)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR2_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_SR2)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR2_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_CR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_KR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_LR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseLR_ER_FR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_SR)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_CR4)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseCR4_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_KR4)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseKR4_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_LR4)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseLR4_ER4_Full); \ + if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_SR4)) \ + ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseSR4_Full); \ +} + +static int octep_vf_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + struct octep_vf_iface_link_info *link_info; + u32 advertised_modes, supported_modes; + + ethtool_link_ksettings_zero_link_mode(cmd, supported); + ethtool_link_ksettings_zero_link_mode(cmd, advertising); + + octep_vf_get_link_info(oct); + + advertised_modes = oct->link_info.advertised_modes; + supported_modes = oct->link_info.supported_modes; + link_info = &oct->link_info; + + OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(supported_modes, cmd, supported); + OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(advertised_modes, cmd, advertising); + + if (link_info->autoneg) { + if (link_info->autoneg & OCTEP_VF_LINK_MODE_AUTONEG_SUPPORTED) + ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); + if (link_info->autoneg & OCTEP_VF_LINK_MODE_AUTONEG_ADVERTISED) { + ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); + cmd->base.autoneg = AUTONEG_ENABLE; + } else { + cmd->base.autoneg = AUTONEG_DISABLE; + } + } else { + cmd->base.autoneg = AUTONEG_DISABLE; + } + + cmd->base.port = PORT_FIBRE; + ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); + ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE); + + if (netif_carrier_ok(netdev)) { + cmd->base.speed = link_info->speed; + cmd->base.duplex = DUPLEX_FULL; + } else { + cmd->base.speed = SPEED_UNKNOWN; + cmd->base.duplex = DUPLEX_UNKNOWN; + } + return 0; +} + +static const struct ethtool_ops octep_vf_ethtool_ops = { + .get_drvinfo = octep_vf_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_strings = octep_vf_get_strings, + .get_sset_count = octep_vf_get_sset_count, + .get_ethtool_stats = octep_vf_get_ethtool_stats, + .get_link_ksettings = octep_vf_get_link_ksettings, +}; + +void octep_vf_set_ethtool_ops(struct net_device *netdev) +{ + netdev->ethtool_ops = &octep_vf_ethtool_ops; +} diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c index a2e56973c39e..f02a93cfd73b 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c @@ -1091,6 +1091,7 @@ static int octep_vf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&octep_vf_dev->tx_timeout_task, octep_vf_tx_timeout_task); netdev->netdev_ops = &octep_vf_netdev_ops; + octep_vf_set_ethtool_ops(netdev); netif_carrier_off(netdev); if (octep_vf_setup_mbox(octep_vf_dev)) { diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h index 5a3b545ad590..5769f62545cd 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h @@ -327,6 +327,7 @@ void octep_vf_device_setup_cn93(struct octep_vf_device *oct); void octep_vf_device_setup_cnxk(struct octep_vf_device *oct); int octep_vf_iq_process_completions(struct octep_vf_iq *iq, u16 budget); int octep_vf_oq_process_rx(struct octep_vf_oq *oq, int budget); +void octep_vf_set_ethtool_ops(struct net_device *netdev); int octep_vf_get_link_info(struct octep_vf_device *oct); int octep_vf_get_if_stats(struct octep_vf_device *oct); void octep_vf_mbox_work(struct work_struct *work); From patchwork Mon Jan 29 05:02:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shinas Rasheed X-Patchwork-Id: 193235 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2087:b0:106:209c:c626 with SMTP id gs7csp366281dyb; Sun, 28 Jan 2024 21:04:58 -0800 (PST) X-Google-Smtp-Source: AGHT+IGasKzit7sii++9gynkK471zTxmmeYxW8HqYzgvQ7+ty0NiuYlGPOUxxOvdvFgAhZVbx+m/ X-Received: by 2002:a25:938c:0:b0:dbe:1ccb:751a with SMTP id a12-20020a25938c000000b00dbe1ccb751amr2003713ybm.31.1706504698335; Sun, 28 Jan 2024 21:04:58 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706504698; cv=pass; d=google.com; s=arc-20160816; b=SdBAFzSOYZvqSWLEOwpXqPVsm4sGnKE4OC8gX9t5nZoXcyRF3Z6AeM7ENcuWdkxkeH ywJh3YwPkN6xCd82K5GNleWz4JT8bHLaENj3lC2gawhLicLJC65IP/le+9DjVhWwBxGh qg/kP+fYdzn8HSwPSZCzoyecZGzlnbbd+9zyMZl3ck+eYJNu2cFUQipoGhLs4wRsppvu McPtRlcz7NheemECnAnaMR/aBLgZfQO0oZRdCLIKziOMWJOrcovrbytOR9BcPOJRE735 D+Sp+m4JRK2N86S4SJ1QQCZRmts3PRj/cljqRZ+sVy7laj3dXmNP9nRX96BKlcGGX7i4 X7ug== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=JZbJQIpsxvb2F2yfcVHmxpDYI9ShTQpL8rgQ4G8yZDo=; fh=VEmtmbrSMAf7klXCiVn/miqlL6KvgVnlb9qrYPH8GrU=; b=MBT1mVHLGsrKvVUw/XXZa9exjQHh+SJ9hSZfCNCs5g50U4W4ncb1Vlrp6Kr7hfnD5A THCvYQNU7lvYGYuGgyyDZrVcTpPxBrfbtiDInMezrS6WPhwJGYQe3yYGbXPAbX3dW4As 2xqiYKUEiMxpwEIzy0e8JYF849zzF5rD3s4LlR/uqTcdaetMFnTYqjOd/eIny7j0zPsL qvFNRM8GhvhwzBAKxmYkCZXNDbR4Ur+sjTE5lloXoQuG34o9l3d3BneSp2oR8UmQdevb 7Rgk4yHs1tgs1Q8QiB3H2ejIgz44Rv5Vmh7COk+gNQ8ezyoMaXRwNeR/Ci+Xg3G68ynH nvgA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=SQX5dEuV; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42170-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42170-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id q24-20020a656858000000b005cee9118a7asi4985237pgt.600.2024.01.28.21.04.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 Jan 2024 21:04:58 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-42170-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=SQX5dEuV; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-42170-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-42170-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id F25412824BD for ; Mon, 29 Jan 2024 05:04:57 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B40184205B; Mon, 29 Jan 2024 05:03:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="SQX5dEuV" Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F05A4CB2E; Mon, 29 Jan 2024 05:03:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.148.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504622; cv=none; b=RJiEdb7Dru7nDgNqceAoCS0EPlo8gGhH0rNZSml4z4NXh9Hg7ncZQAGufyGAqRL2zgZmYQxb1qjSP72q6QjUxAUBnaStu2mcAIAeJORGn/wDoSdeoK4RLpgU17rvXj+eBq4b5U1cAf9WPd6rbajogFgz7yKlPbLu3RYyyVgRtYE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706504622; c=relaxed/simple; bh=02tLcVFEsGbvDgtG5CO32AJ9t0Jnx97kboE+P+QpW0Q=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=H9KGWKrkJ7vPWfjCy6zJh3Il9kkqtV26zS8uY3+ZHIfWVu1xRsG3wm4MFevvQbtbeshpzPZzBvuvo4LyrRbuV0jaTHE+jFamU8e2HQGdA/+b0VNAp3k+38NnDooaWx/UgmwWEk7tCDqOObYqFa7/Z4q6G4QYtvEbpHGeXieHTIM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com; spf=pass smtp.mailfrom=marvell.com; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b=SQX5dEuV; arc=none smtp.client-ip=67.231.148.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 40T4KMvI027576; Sun, 28 Jan 2024 21:03:36 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=JZbJQIpsxvb2F2yfcVHmxpDYI9ShTQpL8rgQ4G8yZDo=; b=SQX 5dEuVBB7NMoeAVqLpu0hQXJxZnC+50Iw+UIynLVYYV6zUS0LuNrMWNLuBEaY0ob6 ozMZUzrQUiVPX1HWkFQ7ogv2Ru6n+p4A9mEFNsLg8BI1tte3F3q/KXPgc8qHM4kk QAaOQQnzz15cOZJnGv8eiVPLwJft4QIYi8/Ba9RRlP+rRY7hn3Hl8uvB47RBoBtm m6rA9EOH85XNmdWLFjsv5O9PMqw4uPFDrMgLKMfpFfkKsHEf9+OSWEDPFGMW5s5O p7ZQWu6FCiiSZAyi4HwEbAwKAN8nMAZnBZW6AD2y7Frc8EMb10Zjg1EibVK9YwVw O4KN+coYK8L3JneQ9xA== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3vx4vr82dv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 28 Jan 2024 21:03:35 -0800 (PST) Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Sun, 28 Jan 2024 21:03:34 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Sun, 28 Jan 2024 21:03:34 -0800 Received: from ubuntu-PowerEdge-T110-II.sclab.marvell.com (unknown [10.106.27.86]) by maili.marvell.com (Postfix) with ESMTP id BA98B3F7048; Sun, 28 Jan 2024 21:03:33 -0800 (PST) From: Shinas Rasheed To: , CC: , , , , , , , , , , , Subject: [PATCH net-next v5 8/8] octeon_ep_vf: update MAINTAINERS Date: Sun, 28 Jan 2024 21:02:54 -0800 Message-ID: <20240129050254.3047778-9-srasheed@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240129050254.3047778-1-srasheed@marvell.com> References: <20240129050254.3047778-1-srasheed@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: rfHDmNHdZ5ctHm3RTyjLVt2Q87eSkpm- X-Proofpoint-GUID: rfHDmNHdZ5ctHm3RTyjLVt2Q87eSkpm- X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-01-29_02,2024-01-25_01,2023-05-22_02 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789399870571513879 X-GMAIL-MSGID: 1789399870571513879 add MAINTAINERS for octeon_ep_vf driver. Signed-off-by: Shinas Rasheed --- V5: - No changes V4: https://lore.kernel.org/all/20240108124213.2966536-9-srasheed@marvell.com/ - No changes V3: https://lore.kernel.org/all/20240105203823.2953604-9-srasheed@marvell.com/ - No changes V2: https://lore.kernel.org/all/20231223134000.2906144-9-srasheed@marvell.com/ - No changes V1: https://lore.kernel.org/all/20231221092844.2885872-9-srasheed@marvell.com/ MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index cec57b22d937..457ca249a651 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13058,6 +13058,15 @@ L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/marvell/octeon_ep +MARVELL OCTEON ENDPOINT VF DRIVER +M: Veerasenareddy Burru +M: Sathesh Edara +M: Shinas Rasheed +M: Satananda Burla +L: netdev@vger.kernel.org +S: Supported +F: drivers/net/ethernet/marvell/octeon_ep_vf + MARVELL OCTEONTX2 PHYSICAL FUNCTION DRIVER M: Sunil Goutham M: Geetha sowjanya