From nobody Mon Dec 1 22:37:15 2025 Received: from mail-il1-f227.google.com (mail-il1-f227.google.com [209.85.166.227]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA17B314D0C for ; Wed, 26 Nov 2025 19:50:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186612; cv=none; b=ojvYpUt8f4apnd+1v46LscsALqe5eb2PucEn3p4T4B+FComny5kvbvddiIZ2ez7w78A2bWd/01Gaxz2mkEOGR4fecnCqaf0X8lEhIxTm5BoOMsbzJ+RFFbbpKJRj0A76dQVYZZ47wvyiggeJRN3dB7kfmVg3WObNI3P5LHhqq2M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186612; c=relaxed/simple; bh=4t/T3clbMEc02QuP88g2VOCGFCPAxgGTo1n29OEQnS4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U8CvgUP6VFHxW6rxTCeGSJGz787lxLRQ2OIvN6nh+aKGOl774Fk2fgzQ6s8IKGTAh1rzFAXt82XL60QH36D6+Xc+KBaU0P4IMHCxP2o6HWvZ9ctAE4Lyps0Y5+4bfBCp0jkjpLLjabbAExphvr8nctwB4BijR6pKjlrRGL01wBw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=R4CNRnOw; arc=none smtp.client-ip=209.85.166.227 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="R4CNRnOw" Received: by mail-il1-f227.google.com with SMTP id e9e14a558f8ab-43323851d03so754245ab.0 for ; Wed, 26 Nov 2025 11:50:09 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186609; x=1764791409; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ioEZekGxYJcealgBYySnHKairs5+njvCA+/PewP3jQo=; b=XEqBViIc0ICnzPp2a0aifd3iFzte61bf6z10562v3apTJVCkSSjR8wAklyhMyTOBGg BwY15XqjL43d64NjvhVYNRNfc9GiolCaKnd9/ZHHp5LZi46OY7VJBlTIhYSJnr6kPOKI xedIEGNvJ3tRmNhhDyMGbLTy1AQ3bT9UtFCK04L/R7FIQcvTG7ngIAAivu+cgfAVQcUn yoLb+lofponX9na8EenJqHoNZHvuttBOP/UTzSM6iRSNLUkEpGzVxGqceV40XjMoNG0d abCcc9QmyB282AD1Ij2PB3EVShv+4CxoSf9UgiN92TWdUVh9bfsbPqhNlpE5fOzkTYnm 0zGA== X-Forwarded-Encrypted: i=1; AJvYcCURN6Eo+8B6TzAJ0/uSYrCwLxAEkaC+i2MXnJjaylDa7g+tkldcNd5K+CdJcJgNSquDdbjTSgBoju04MDY=@vger.kernel.org X-Gm-Message-State: AOJu0Yxqa47eTA35nmRxv+8SE+nZdI5SwG+eiSqf2he4Lk2/8XDaLoW6 XJu/1nnKCRM113O1guxJ0OmKvUfScjtWzdygbSZOHpVbJWu33863C1FjBzmjLtxIdC5WAsFe5I0 56JOCuSEKLrT4FOJ3QYlSoJLn07ooUb7Vsh8ndFBKbOrAV3khrjsIdFXlb3lOLMQptepcaXWaNl ZMbhMnpKADKtrTa6jK05ParxUzUAmEg8EvayEiIyrxLToJd2okWtwU4uwfEUWLVoRQiK694apQr t090mC/AylzgfMqL369z9frng== X-Gm-Gg: ASbGncsgqCVYkA7Mb5wXULtXfshyGrUludb70WoJ4X0QtVJcR9k58k6RsujAj2ZlwvF t17FZ1U+c4LqqYQfuavI89rWWFrvz5vgDRYJoUyWQc6ue/OHVS7dSti7PNpgSFtDNCeZGMEjLOl WjdIEQrrMBfDiANeDUPQmnUxwZ5/V4b6ZG64m7SGhYeF5OiewGd5vmzFs6CqKy6mRwFSJrkgmcf OO/1KH5IEssbwoEuty9gOc9LycwDpc9rqA99RQ+k6GR6iqSmOketIINFeGB7kfw1JoRhmiMaUnk smCA4DJvbbPbMtZdQE4/vYRAzwz1CB0nMmA0RTem4sPZ3aDvSrLz87EvlQJZf//37svFEwA2gal 4HpmPQxY6pGC6KHG4AcAupAz6iaFrVgLZwdlIlMYsbjLFGA+oW/aykXLfa3+n/g7kRNvbH735VK OLsmUJLvw+lstI6stZkw5W4DU8X547r8007lCOgKo/2uL93otkF8M= X-Google-Smtp-Source: AGHT+IFzWiDghizqyghznImeTrYolTWnQoTlR9a9Lgp281FWfARzP37hKoCYBFTDH5Q6N9rMsKCNLSSvR7CD X-Received: by 2002:a92:ca0d:0:b0:434:96ea:ff53 with SMTP id e9e14a558f8ab-435b98d7851mr129057995ab.36.1764186608835; Wed, 26 Nov 2025 11:50:08 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-11.dlp.protect.broadcom.com. [144.49.247.11]) by smtp-relay.gmail.com with ESMTPS id 8926c6da1cb9f-5b954b16f1bsm1891232173.25.2025.11.26.11.50.08 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:08 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f197.google.com with SMTP id d9443c01a7336-297dabf9fd0so1569555ad.0 for ; Wed, 26 Nov 2025 11:50:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186606; x=1764791406; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ioEZekGxYJcealgBYySnHKairs5+njvCA+/PewP3jQo=; b=R4CNRnOwG0L3mrBKP9CwhoQ0zAhqmEaZOZurH5bbKJzFWhf/X6j5rTVTnRGP+0bgeB CkWrpl0N0gpTxhpxUk0M0JCEpJQu23lEfi4/mHbvavGnksxVn1Nwe5FAxZ5ANdBxGXSn ECCxHx+Y4XtbludG2tFx8IwSlixl74sY8wnas= X-Forwarded-Encrypted: i=1; AJvYcCUeQCp2lPdRQZK3tcT23EhnHaQeLXDC1Gm/uiAqw4maxgoCJ6Xiifddkzh1VR0DXSZt1Ft6Gp+8qfNY0DE=@vger.kernel.org X-Received: by 2002:a17:903:3c30:b0:298:8a9:766a with SMTP id d9443c01a7336-29b6c6b2e57mr227289485ad.53.1764186606197; Wed, 26 Nov 2025 11:50:06 -0800 (PST) X-Received: by 2002:a17:903:3c30:b0:298:8a9:766a with SMTP id d9443c01a7336-29b6c6b2e57mr227289165ad.53.1764186605578; Wed, 26 Nov 2025 11:50:05 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:04 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 01/12] bng_en: Query PHY and report link status Date: Thu, 27 Nov 2025 01:19:20 +0530 Message-ID: <20251126194931.455830-2-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Query the PHY device and report link status, speed, flow control, and duplex settings. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- drivers/net/ethernet/broadcom/bnge/Makefile | 3 +- drivers/net/ethernet/broadcom/bnge/bnge.h | 29 ++ .../ethernet/broadcom/bnge/bnge_hwrm_lib.c | 190 +++++++ .../ethernet/broadcom/bnge/bnge_hwrm_lib.h | 4 + .../net/ethernet/broadcom/bnge/bnge_link.c | 487 ++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_link.h | 185 +++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.c | 22 + .../net/ethernet/broadcom/bnge/bnge_netdev.h | 3 + 8 files changed, 922 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_link.c create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_link.h diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethe= rnet/broadcom/bnge/Makefile index 6142d9c57f4..f30db7e5f48 100644 --- a/drivers/net/ethernet/broadcom/bnge/Makefile +++ b/drivers/net/ethernet/broadcom/bnge/Makefile @@ -9,4 +9,5 @@ bng_en-y :=3D bnge_core.o \ bnge_rmem.o \ bnge_resc.o \ bnge_netdev.o \ - bnge_ethtool.o + bnge_ethtool.o \ + bnge_link.o diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethern= et/broadcom/bnge/bnge.h index 7aed5f81cd5..68c13520a95 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h @@ -9,8 +9,10 @@ =20 #include #include +#include #include "bnge_rmem.h" #include "bnge_resc.h" +#include "bnge_link.h" =20 #define DRV_VER_MAJ 1 #define DRV_VER_MIN 15 @@ -141,6 +143,17 @@ struct bnge_dev { struct bnge_ctx_mem_info *ctx; =20 u64 flags; +#define BNGE_PF(bd) (1) +#define BNGE_VF(bd) (0) +#define BNGE_NPAR(bd) (0) +#define BNGE_MH(bd) (0) +#define BNGE_SINGLE_PF(bd) (BNGE_PF(bd) && !BNGE_NPAR(bd) && !BNGE_MH(bd)) +#define BNGE_SH_PORT_CFG_OK(bd) \ + (BNGE_PF(bd) && ((bd)->phy_flags & BNGE_PHY_FL_SHARED_PORT_CFG)) +#define BNGE_PHY_CFG_ABLE(bd) \ + ((BNGE_SINGLE_PF(bd) || \ + BNGE_SH_PORT_CFG_OK(bd)) && \ + (bd)->link_info.phy_state =3D=3D BNGE_PHY_STATE_ENABLED) =20 struct bnge_hw_resc hw_resc; =20 @@ -197,6 +210,22 @@ struct bnge_dev { =20 struct bnge_irq *irq_tbl; u16 irqs_acquired; + + /* To protect link related settings during link changes and + * ethtool settings changes. + */ + struct mutex link_lock; + struct bnge_link_info link_info; + + /* copied from flags and flags2 in hwrm_port_phy_qcaps_output */ + u32 phy_flags; +#define BNGE_PHY_FL_SHARED_PORT_CFG \ + PORT_PHY_QCAPS_RESP_FLAGS_SHARED_PHY_CFG_SUPPORTED +#define BNGE_PHY_FL_NO_FCS PORT_PHY_QCAPS_RESP_FLAGS_NO_FCS +#define BNGE_PHY_FL_SPEEDS2 \ + (PORT_PHY_QCAPS_RESP_FLAGS2_SPEEDS2_SUPPORTED << 8) + + u32 msg_enable; }; =20 static inline bool bnge_is_roce_en(struct bnge_dev *bd) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.c index 198f49b40db..9b31069fc7b 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c @@ -14,6 +14,7 @@ #include "bnge_hwrm_lib.h" #include "bnge_rmem.h" #include "bnge_resc.h" +#include "bnge_link.h" =20 int bnge_hwrm_ver_get(struct bnge_dev *bd) { @@ -981,6 +982,195 @@ void bnge_hwrm_vnic_ctx_free_one(struct bnge_dev *bd, vnic->fw_rss_cos_lb_ctx[ctx_idx] =3D INVALID_HW_RING_ID; } =20 +int bnge_hwrm_phy_qcaps(struct bnge_dev *bd) +{ + struct bnge_link_info *link_info =3D &bd->link_info; + struct hwrm_port_phy_qcaps_output *resp; + struct hwrm_port_phy_qcaps_input *req; + int rc; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_QCAPS); + if (rc) + return rc; + + resp =3D bnge_hwrm_req_hold(bd, req); + rc =3D bnge_hwrm_req_send(bd, req); + if (rc) + goto hwrm_phy_qcaps_exit; + + bd->phy_flags =3D resp->flags | (le16_to_cpu(resp->flags2) << 8); + + if (bnge_phy_qcaps_no_speed(resp)) { + link_info->phy_state =3D BNGE_PHY_STATE_DISABLED; + netdev_warn(bd->netdev, "Ethernet link disabled\n"); + } else if (link_info->phy_state =3D=3D BNGE_PHY_STATE_DISABLED) { + link_info->phy_state =3D BNGE_PHY_STATE_ENABLED; + netdev_info(bd->netdev, "Ethernet link enabled\n"); + /* Phy re-enabled, reprobe the speeds */ + link_info->support_auto_speeds =3D 0; + link_info->support_pam4_auto_speeds =3D 0; + link_info->support_auto_speeds2 =3D 0; + } + if (resp->supported_speeds_auto_mode) + link_info->support_auto_speeds =3D + le16_to_cpu(resp->supported_speeds_auto_mode); + if (resp->supported_pam4_speeds_auto_mode) + link_info->support_pam4_auto_speeds =3D + le16_to_cpu(resp->supported_pam4_speeds_auto_mode); + if (resp->supported_speeds2_auto_mode) + link_info->support_auto_speeds2 =3D + le16_to_cpu(resp->supported_speeds2_auto_mode); + + bd->port_count =3D resp->port_cnt; + +hwrm_phy_qcaps_exit: + bnge_hwrm_req_drop(bd, req); + return rc; +} + +int bnge_hwrm_set_link_setting(struct bnge_net *bn, bool set_pause) +{ + struct hwrm_port_phy_cfg_input *req; + struct bnge_dev *bd =3D bn->bd; + int rc; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_CFG); + if (rc) + return rc; + + if (set_pause) + bnge_hwrm_set_pause_common(bn, req); + + bnge_hwrm_set_link_common(bn, req); + + return bnge_hwrm_req_send(bd, req); +} + +int bnge_update_link(struct bnge_net *bn, bool chng_link_state) +{ + struct hwrm_port_phy_qcfg_output *resp; + struct hwrm_port_phy_qcfg_input *req; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + bool support_changed; + u8 link_state; + int rc; + + link_info =3D &bd->link_info; + link_state =3D link_info->link_state; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_QCFG); + if (rc) + return rc; + + resp =3D bnge_hwrm_req_hold(bd, req); + rc =3D bnge_hwrm_req_send(bd, req); + if (rc) { + bnge_hwrm_req_drop(bd, req); + return rc; + } + + memcpy(&link_info->phy_qcfg_resp, resp, sizeof(*resp)); + link_info->phy_link_status =3D resp->link; + link_info->duplex =3D resp->duplex_state; + link_info->pause =3D resp->pause; + link_info->auto_mode =3D resp->auto_mode; + link_info->auto_pause_setting =3D resp->auto_pause; + link_info->lp_pause =3D resp->link_partner_adv_pause; + link_info->force_pause_setting =3D resp->force_pause; + link_info->duplex_setting =3D resp->duplex_cfg; + if (link_info->phy_link_status =3D=3D BNGE_LINK_LINK) { + link_info->link_speed =3D le16_to_cpu(resp->link_speed); + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) + link_info->active_lanes =3D resp->active_lanes; + } else { + link_info->link_speed =3D 0; + link_info->active_lanes =3D 0; + } + link_info->force_link_speed =3D le16_to_cpu(resp->force_link_speed); + link_info->force_pam4_link_speed =3D + le16_to_cpu(resp->force_pam4_link_speed); + link_info->force_link_speed2 =3D le16_to_cpu(resp->force_link_speeds2); + link_info->support_speeds =3D le16_to_cpu(resp->support_speeds); + link_info->support_pam4_speeds =3D le16_to_cpu(resp->support_pam4_speeds); + link_info->support_speeds2 =3D le16_to_cpu(resp->support_speeds2); + link_info->auto_link_speeds =3D le16_to_cpu(resp->auto_link_speed_mask); + link_info->auto_pam4_link_speeds =3D + le16_to_cpu(resp->auto_pam4_link_speed_mask); + link_info->auto_link_speeds2 =3D le16_to_cpu(resp->auto_link_speeds2); + link_info->lp_auto_link_speeds =3D + le16_to_cpu(resp->link_partner_adv_speeds); + link_info->lp_auto_pam4_link_speeds =3D + resp->link_partner_pam4_adv_speeds; + link_info->preemphasis =3D le32_to_cpu(resp->preemphasis); + link_info->phy_ver[0] =3D resp->phy_maj; + link_info->phy_ver[1] =3D resp->phy_min; + link_info->phy_ver[2] =3D resp->phy_bld; + link_info->media_type =3D resp->media_type; + link_info->phy_type =3D resp->phy_type; + link_info->transceiver =3D resp->xcvr_pkg_type; + link_info->phy_addr =3D resp->eee_config_phy_addr & + PORT_PHY_QCFG_RESP_PHY_ADDR_MASK; + link_info->module_status =3D resp->module_status; + + link_info->fec_cfg =3D PORT_PHY_QCFG_RESP_FEC_CFG_FEC_NONE_SUPPORTED; + link_info->fec_cfg =3D le16_to_cpu(resp->fec_cfg); + link_info->active_fec_sig_mode =3D resp->active_fec_signal_mode; + /* TODO: need to add more logic to report VF link */ + if (chng_link_state) { + if (link_info->phy_link_status =3D=3D BNGE_LINK_LINK) + link_info->link_state =3D BNGE_LINK_STATE_UP; + else + link_info->link_state =3D BNGE_LINK_STATE_DOWN; + if (link_state !=3D link_info->link_state) + bnge_report_link(bd); + } else { + /* always link down if not require to update link state */ + link_info->link_state =3D BNGE_LINK_STATE_DOWN; + } + bnge_hwrm_req_drop(bd, req); + + if (!BNGE_PHY_CFG_ABLE(bd)) + return 0; + + support_changed =3D bnge_support_speed_dropped(bn); + if (support_changed && (bn->eth_link_info.autoneg & BNGE_AUTONEG_SPEED)) + bnge_hwrm_set_link_setting(bn, true); + return 0; +} + +int bnge_hwrm_set_pause(struct bnge_net *bn) +{ + struct hwrm_port_phy_cfg_input *req; + struct bnge_dev *bd =3D bn->bd; + int rc; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_CFG); + if (rc) + return rc; + + bnge_hwrm_set_pause_common(bn, req); + + if ((bn->eth_link_info.autoneg & BNGE_AUTONEG_FLOW_CTRL) || + bn->eth_link_info.force_link_chng) + bnge_hwrm_set_link_common(bn, req); + + rc =3D bnge_hwrm_req_send(bd, req); + if (!rc && !(bn->eth_link_info.autoneg & BNGE_AUTONEG_FLOW_CTRL)) { + /* since changing of pause setting doesn't trigger any link + * change event, the driver needs to update the current pause + * result upon successfully return of the phy_cfg command + */ + bd->link_info.force_pause_setting =3D + bd->link_info.pause =3D bn->eth_link_info.req_flow_ctrl; + bd->link_info.auto_pause_setting =3D 0; + if (!bn->eth_link_info.force_link_chng) + bnge_report_link(bd); + } + bn->eth_link_info.force_link_chng =3D false; + return rc; +} + void bnge_hwrm_stat_ctx_free(struct bnge_net *bn) { struct hwrm_stat_ctx_free_input *req; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.h index 042f28e84a0..b063f62ae06 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h @@ -55,4 +55,8 @@ int hwrm_ring_alloc_send_msg(struct bnge_net *bn, struct bnge_ring_struct *ring, u32 ring_type, u32 map_index); int bnge_hwrm_set_async_event_cr(struct bnge_dev *bd, int idx); +int bnge_update_link(struct bnge_net *bn, bool chng_link_state); +int bnge_hwrm_phy_qcaps(struct bnge_dev *bd); +int bnge_hwrm_set_link_setting(struct bnge_net *bn, bool set_pause); +int bnge_hwrm_set_pause(struct bnge_net *bn); #endif /* _BNGE_HWRM_LIB_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.c b/drivers/net/e= thernet/broadcom/bnge/bnge_link.c new file mode 100644 index 00000000000..02deb38d81d --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.c @@ -0,0 +1,487 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2025 Broadcom. + +#include + +#include "bnge.h" +#include "bnge_link.h" +#include "bnge_hwrm_lib.h" + +u32 bnge_fw_to_ethtool_speed(u16 fw_link_speed) +{ + switch (fw_link_speed) { + case BNGE_LINK_SPEED_50GB: + case BNGE_LINK_SPEED_50GB_PAM4: + return SPEED_50000; + case BNGE_LINK_SPEED_100GB: + case BNGE_LINK_SPEED_100GB_PAM4: + case BNGE_LINK_SPEED_100GB_PAM4_112: + return SPEED_100000; + case BNGE_LINK_SPEED_200GB: + case BNGE_LINK_SPEED_200GB_PAM4: + case BNGE_LINK_SPEED_200GB_PAM4_112: + return SPEED_200000; + case BNGE_LINK_SPEED_400GB: + case BNGE_LINK_SPEED_400GB_PAM4: + case BNGE_LINK_SPEED_400GB_PAM4_112: + return SPEED_400000; + case BNGE_LINK_SPEED_800GB: + case BNGE_LINK_SPEED_800GB_PAM4_112: + return SPEED_800000; + default: + return SPEED_UNKNOWN; + } +} + +bool bnge_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *resp) +{ + if (!resp->supported_speeds_auto_mode && + !resp->supported_speeds_force_mode && + !resp->supported_pam4_speeds_auto_mode && + !resp->supported_pam4_speeds_force_mode && + !resp->supported_speeds2_auto_mode && + !resp->supported_speeds2_force_mode) + return true; + return false; +} + +static void bnge_set_auto_speed(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + elink_info->advertising =3D link_info->auto_link_speeds2; + return; + } + elink_info->advertising =3D link_info->auto_link_speeds; + elink_info->advertising_pam4 =3D link_info->auto_pam4_link_speeds; +} + +static void bnge_set_force_speed(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + elink_info->req_link_speed =3D link_info->force_link_speed2; + elink_info->req_signal_mode =3D BNGE_SIG_MODE_NRZ; + switch (elink_info->req_link_speed) { + case BNGE_LINK_SPEED_50GB_PAM4: + case BNGE_LINK_SPEED_100GB_PAM4: + case BNGE_LINK_SPEED_200GB_PAM4: + case BNGE_LINK_SPEED_400GB_PAM4: + elink_info->req_signal_mode =3D BNGE_SIG_MODE_PAM4; + break; + case BNGE_LINK_SPEED_100GB_PAM4_112: + case BNGE_LINK_SPEED_200GB_PAM4_112: + case BNGE_LINK_SPEED_400GB_PAM4_112: + case BNGE_LINK_SPEED_800GB_PAM4_112: + elink_info->req_signal_mode =3D BNGE_SIG_MODE_PAM4_112; + break; + default: + elink_info->req_signal_mode =3D BNGE_SIG_MODE_NRZ; + } + return; + } + elink_info->req_link_speed =3D link_info->force_link_speed; + elink_info->req_signal_mode =3D BNGE_SIG_MODE_NRZ; + if (link_info->force_pam4_link_speed) { + elink_info->req_link_speed =3D link_info->force_pam4_link_speed; + elink_info->req_signal_mode =3D BNGE_SIG_MODE_PAM4; + } +} + +void bnge_init_ethtool_link_settings(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (BNGE_AUTO_MODE(link_info->auto_mode)) { + elink_info->autoneg =3D BNGE_AUTONEG_SPEED; + if (link_info->auto_pause_setting & + PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE) + elink_info->autoneg |=3D BNGE_AUTONEG_FLOW_CTRL; + bnge_set_auto_speed(bn); + } else { + bnge_set_force_speed(bn); + elink_info->req_duplex =3D link_info->duplex_setting; + } + if (elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) + elink_info->req_flow_ctrl =3D + link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH; + else + elink_info->req_flow_ctrl =3D link_info->force_pause_setting; +} + +int bnge_probe_phy(struct bnge_net *bn, bool fw_dflt) +{ + struct bnge_dev *bd =3D bn->bd; + int rc; + + bd->phy_flags =3D 0; + rc =3D bnge_hwrm_phy_qcaps(bd); + if (rc) { + netdev_err(bn->netdev, + "Probe phy can't get phy qcaps (rc: %d)\n", rc); + return rc; + } + if (bd->phy_flags & BNGE_PHY_FL_NO_FCS) + bn->netdev->priv_flags |=3D IFF_SUPP_NOFCS; + else + bn->netdev->priv_flags &=3D ~IFF_SUPP_NOFCS; + if (!fw_dflt) + return 0; + + mutex_lock(&bd->link_lock); + rc =3D bnge_update_link(bn, false); + if (rc) { + mutex_unlock(&bd->link_lock); + netdev_err(bn->netdev, "Probe phy can't update link (rc: %d)\n", + rc); + return rc; + } + + bnge_init_ethtool_link_settings(bn); + mutex_unlock(&bd->link_lock); + return 0; +} + +void bnge_hwrm_set_link_common(struct bnge_net *bn, + struct hwrm_port_phy_cfg_input *req) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_dev *bd =3D bn->bd; + + if (elink_info->autoneg & BNGE_AUTONEG_SPEED) { + req->auto_mode |=3D PORT_PHY_CFG_REQ_AUTO_MODE_SPEED_MASK; + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + req->enables |=3D cpu_to_le32(BNGE_PHY_AUTO_SPEEDS2_MASK); + req->auto_link_speeds2_mask =3D + cpu_to_le16(elink_info->advertising); + } else if (elink_info->advertising) { + req->enables |=3D cpu_to_le32(BNGE_PHY_AUTO_SPEED_MASK); + req->auto_link_speed_mask =3D + cpu_to_le16(elink_info->advertising); + } + if (elink_info->advertising_pam4) { + req->enables |=3D + cpu_to_le32(BNGE_PHY_AUTO_PAM4_SPEED_MASK); + req->auto_link_pam4_speed_mask =3D + cpu_to_le16(elink_info->advertising_pam4); + } + req->enables |=3D cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE); + req->flags |=3D cpu_to_le32(BNGE_PHY_FLAGS_RESTART_AUTO); + } else { + req->flags |=3D cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE); + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + req->force_link_speeds2 =3D + cpu_to_le16(elink_info->req_link_speed); + req->enables |=3D + cpu_to_le32(BNGE_PHY_FLAGS_ENA_FORCE_SPEEDS2); + netif_info(bd, link, bn->netdev, + "Forcing FW speed2: %d\n", + (u32)elink_info->req_link_speed); + } else if (elink_info->req_signal_mode =3D=3D BNGE_SIG_MODE_PAM4) { + req->force_pam4_link_speed =3D + cpu_to_le16(elink_info->req_link_speed); + req->enables |=3D + cpu_to_le32(BNGE_PHY_FLAGS_ENA_FORCE_PM4_SPEED); + } else { + req->force_link_speed =3D + cpu_to_le16(elink_info->req_link_speed); + } + } + + /* tell FW that the setting takes effect immediately */ + req->flags |=3D cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESET_PHY); +} + +static bool bnge_auto_speed_updated(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + if (elink_info->advertising !=3D link_info->auto_link_speeds2) + return true; + return false; + } + if (elink_info->advertising !=3D link_info->auto_link_speeds || + elink_info->advertising_pam4 !=3D link_info->auto_pam4_link_speeds) + return true; + return false; +} + +void bnge_hwrm_set_pause_common(struct bnge_net *bn, + struct hwrm_port_phy_cfg_input *req) +{ + if (bn->eth_link_info.autoneg & BNGE_AUTONEG_FLOW_CTRL) { + req->auto_pause =3D PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE; + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_RX) + req->auto_pause |=3D PORT_PHY_CFG_REQ_AUTO_PAUSE_RX; + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_TX) + req->auto_pause |=3D PORT_PHY_CFG_REQ_AUTO_PAUSE_TX; + req->enables |=3D + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE); + } else { + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_RX) + req->force_pause |=3D PORT_PHY_CFG_REQ_FORCE_PAUSE_RX; + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_TX) + req->force_pause |=3D PORT_PHY_CFG_REQ_FORCE_PAUSE_TX; + req->enables |=3D + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_FORCE_PAUSE); + req->auto_pause =3D req->force_pause; + req->enables |=3D + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE); + } +} + +static bool bnge_force_speed_updated(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + if (elink_info->req_link_speed !=3D link_info->force_link_speed2) + return true; + return false; + } + if (elink_info->req_signal_mode =3D=3D BNGE_SIG_MODE_NRZ && + elink_info->req_link_speed !=3D link_info->force_link_speed) + return true; + if (elink_info->req_signal_mode =3D=3D BNGE_SIG_MODE_PAM4 && + elink_info->req_link_speed !=3D link_info->force_pam4_link_speed) + return true; + return false; +} + +int bnge_update_phy_setting(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + bool update_pause =3D false; + bool update_link =3D false; + int rc; + + link_info =3D &bd->link_info; + elink_info =3D &bn->eth_link_info; + rc =3D bnge_update_link(bn, true); + if (rc) { + netdev_err(bn->netdev, "failed to update link (rc: %d)\n", + rc); + return rc; + } + if (!BNGE_SINGLE_PF(bd)) + return 0; + + if ((elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) && + (link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH) !=3D + elink_info->req_flow_ctrl) + update_pause =3D true; + if (!(elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) && + link_info->force_pause_setting !=3D elink_info->req_flow_ctrl) + update_pause =3D true; + if (!(elink_info->autoneg & BNGE_AUTONEG_SPEED)) { + if (BNGE_AUTO_MODE(link_info->auto_mode)) + update_link =3D true; + if (bnge_force_speed_updated(bn)) + update_link =3D true; + if (elink_info->req_duplex !=3D link_info->duplex_setting) + update_link =3D true; + } else { + if (link_info->auto_mode =3D=3D BNGE_LINK_AUTO_NONE) + update_link =3D true; + if (bnge_auto_speed_updated(bn)) + update_link =3D true; + } + + /* The last close may have shutdown the link, so need to call + * PHY_CFG to bring it back up. + */ + if (!BNGE_LINK_IS_UP(bd)) + update_link =3D true; + + if (update_link) + rc =3D bnge_hwrm_set_link_setting(bn, update_pause); + else if (update_pause) + rc =3D bnge_hwrm_set_pause(bn); + + if (rc) { + netdev_err(bn->netdev, + "failed to update phy setting (rc: %d)\n", rc); + return rc; + } + + return rc; +} + +void bnge_get_port_module_status(struct bnge_net *bn) +{ + struct hwrm_port_phy_qcfg_output *resp; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + u8 module_status; + + link_info =3D &bd->link_info; + resp =3D &link_info->phy_qcfg_resp; + + if (bnge_update_link(bn, true)) + return; + + module_status =3D link_info->module_status; + switch (module_status) { + case PORT_PHY_QCFG_RESP_MODULE_STATUS_DISABLETX: + case PORT_PHY_QCFG_RESP_MODULE_STATUS_PWRDOWN: + case PORT_PHY_QCFG_RESP_MODULE_STATUS_WARNINGMSG: + netdev_warn(bn->netdev, + "Unqualified SFP+ module detected on port %d\n", + bd->pf.port_id); + netdev_warn(bn->netdev, "Module part number %s\n", + resp->phy_vendor_partnumber); + if (module_status =3D=3D PORT_PHY_QCFG_RESP_MODULE_STATUS_DISABLETX) + netdev_warn(bn->netdev, "TX is disabled\n"); + if (module_status =3D=3D PORT_PHY_QCFG_RESP_MODULE_STATUS_PWRDOWN) + netdev_warn(bn->netdev, "SFP+ module is shutdown\n"); + } +} + +static bool bnge_support_dropped(u16 advertising, u16 supported) +{ + u16 diff =3D advertising ^ supported; + + return ((supported | diff) !=3D supported); +} + +bool bnge_support_speed_dropped(struct bnge_net *bn) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + /* Check if any advertised speeds are no longer supported. The caller + * holds the link_lock mutex, so we can modify link_info settings. + */ + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + if (bnge_support_dropped(elink_info->advertising, + link_info->support_auto_speeds2)) { + elink_info->advertising =3D + link_info->support_auto_speeds2; + return true; + } + return false; + } + if (bnge_support_dropped(elink_info->advertising, + link_info->support_auto_speeds)) { + elink_info->advertising =3D link_info->support_auto_speeds; + return true; + } + if (bnge_support_dropped(elink_info->advertising_pam4, + link_info->support_pam4_auto_speeds)) { + elink_info->advertising_pam4 =3D + link_info->support_pam4_auto_speeds; + return true; + } + return false; +} + +static char *bnge_report_fec(struct bnge_link_info *link_info) +{ + u8 active_fec =3D link_info->active_fec_sig_mode & + PORT_PHY_QCFG_RESP_ACTIVE_FEC_MASK; + + switch (active_fec) { + default: + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_NONE_ACTIVE: + return "None"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_CLAUSE74_ACTIVE: + return "Clause 74 BaseR"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_CLAUSE91_ACTIVE: + return "Clause 91 RS(528,514)"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS544_1XN_ACTIVE: + return "Clause 91 RS544_1XN"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS544_IEEE_ACTIVE: + return "Clause 91 RS(544,514)"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS272_1XN_ACTIVE: + return "Clause 91 RS272_1XN"; + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS272_IEEE_ACTIVE: + return "Clause 91 RS(272,257)"; + } +} + +void bnge_report_link(struct bnge_dev *bd) +{ + if (BNGE_LINK_IS_UP(bd)) { + const char *signal =3D ""; + const char *flow_ctrl; + const char *duplex; + u32 speed; + u16 fec; + + netif_carrier_on(bd->netdev); + speed =3D bnge_fw_to_ethtool_speed(bd->link_info.link_speed); + if (speed =3D=3D SPEED_UNKNOWN) { + netdev_info(bd->netdev, + "NIC Link is Up, speed unknown\n"); + return; + } + if (bd->link_info.duplex =3D=3D BNGE_LINK_DUPLEX_FULL) + duplex =3D "full"; + else + duplex =3D "half"; + if (bd->link_info.pause =3D=3D BNGE_LINK_PAUSE_BOTH) + flow_ctrl =3D "ON - receive & transmit"; + else if (bd->link_info.pause =3D=3D BNGE_LINK_PAUSE_TX) + flow_ctrl =3D "ON - transmit"; + else if (bd->link_info.pause =3D=3D BNGE_LINK_PAUSE_RX) + flow_ctrl =3D "ON - receive"; + else + flow_ctrl =3D "none"; + if (bd->link_info.phy_qcfg_resp.option_flags & + PORT_PHY_QCFG_RESP_OPTION_FLAGS_SIGNAL_MODE_KNOWN) { + u8 sig_mode =3D bd->link_info.active_fec_sig_mode & + PORT_PHY_QCFG_RESP_SIGNAL_MODE_MASK; + switch (sig_mode) { + case PORT_PHY_QCFG_RESP_SIGNAL_MODE_NRZ: + signal =3D "(NRZ) "; + break; + case PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4: + signal =3D "(PAM4 56Gbps) "; + break; + case PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4_112: + signal =3D "(PAM4 112Gbps) "; + break; + default: + break; + } + } + netdev_info(bd->netdev, "NIC Link is Up, %u Mbps %s%s duplex, Flow contr= ol: %s\n", + speed, signal, duplex, flow_ctrl); + fec =3D bd->link_info.fec_cfg; + if (!(fec & PORT_PHY_QCFG_RESP_FEC_CFG_FEC_NONE_SUPPORTED)) + netdev_info(bd->netdev, "FEC autoneg %s encoding: %s\n", + (fec & BNGE_FEC_AUTONEG) ? "on" : "off", + bnge_report_fec(&bd->link_info)); + } else { + netif_carrier_off(bd->netdev); + netdev_err(bd->netdev, "NIC Link is Down\n"); + } +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.h b/drivers/net/e= thernet/broadcom/bnge/bnge_link.h new file mode 100644 index 00000000000..65da27c510b --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.h @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2025 Broadcom */ + +#ifndef _BNGE_LINK_H_ +#define _BNGE_LINK_H_ + +#define BNGE_PHY_AUTO_SPEEDS2_MASK \ + PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEEDS2_MASK +#define BNGE_PHY_AUTO_SPEED_MASK \ + PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED_MASK +#define BNGE_PHY_AUTO_PAM4_SPEED_MASK \ + PORT_PHY_CFG_REQ_ENABLES_AUTO_PAM4_LINK_SPEED_MASK +#define BNGE_PHY_FLAGS_RESTART_AUTO \ + PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG +#define BNGE_PHY_FLAGS_ENA_FORCE_SPEEDS2 \ + PORT_PHY_CFG_REQ_ENABLES_FORCE_LINK_SPEEDS2 +#define BNGE_PHY_FLAGS_ENA_FORCE_PM4_SPEED \ + PORT_PHY_CFG_REQ_ENABLES_FORCE_PAM4_LINK_SPEED + +struct bnge_link_info { + u8 phy_type; + u8 media_type; + u8 transceiver; + u8 phy_addr; + u8 phy_link_status; +#define BNGE_LINK_LINK PORT_PHY_QCFG_RESP_LINK_LINK + u8 phy_state; +#define BNGE_PHY_STATE_ENABLED 0 +#define BNGE_PHY_STATE_DISABLED 1 + + u8 link_state; +#define BNGE_LINK_STATE_UNKNOWN 0 +#define BNGE_LINK_STATE_DOWN 1 +#define BNGE_LINK_STATE_UP 2 +#define BNGE_LINK_IS_UP(bd) \ + ((bd)->link_info.link_state =3D=3D BNGE_LINK_STATE_UP) + u8 active_lanes; + u8 duplex; +#define BNGE_LINK_DUPLEX_FULL PORT_PHY_QCFG_RESP_DUPLEX_STATE_FULL + u8 pause; +#define BNGE_LINK_PAUSE_TX PORT_PHY_QCFG_RESP_PAUSE_TX +#define BNGE_LINK_PAUSE_RX PORT_PHY_QCFG_RESP_PAUSE_RX +#define BNGE_LINK_PAUSE_BOTH (PORT_PHY_QCFG_RESP_PAUSE_RX | \ + PORT_PHY_QCFG_RESP_PAUSE_TX) + u8 lp_pause; + u8 auto_pause_setting; + u8 force_pause_setting; + u8 duplex_setting; + u8 auto_mode; +#define BNGE_AUTO_MODE(mode) ((mode) > BNGE_LINK_AUTO_NONE && \ + (mode) <=3D BNGE_LINK_AUTO_MSK) +#define BNGE_LINK_AUTO_NONE PORT_PHY_QCFG_RESP_AUTO_MODE_NONE +#define BNGE_LINK_AUTO_MSK PORT_PHY_QCFG_RESP_AUTO_MODE_SPEED_MASK +#define PHY_VER_LEN 3 + u8 phy_ver[PHY_VER_LEN]; + u16 link_speed; +#define BNGE_LINK_SPEED_50GB PORT_PHY_QCFG_RESP_LINK_SPEED_50GB +#define BNGE_LINK_SPEED_100GB PORT_PHY_QCFG_RESP_LINK_SPEED_100GB +#define BNGE_LINK_SPEED_200GB PORT_PHY_QCFG_RESP_LINK_SPEED_200GB +#define BNGE_LINK_SPEED_400GB PORT_PHY_QCFG_RESP_LINK_SPEED_400GB +#define BNGE_LINK_SPEED_800GB PORT_PHY_QCFG_RESP_LINK_SPEED_800GB + u16 support_speeds; + u16 support_pam4_speeds; + u16 support_speeds2; + + u16 auto_link_speeds; /* fw adv setting */ +#define BNGE_LINK_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB +#define BNGE_LINK_SPEED_MSK_100GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100GB + u16 auto_pam4_link_speeds; +#define BNGE_LINK_PAM4_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEE= DS_50G +#define BNGE_LINK_PAM4_SPEED_MSK_100GB \ + PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEEDS_100G +#define BNGE_LINK_PAM4_SPEED_MSK_200GB \ + PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEEDS_200G + u16 auto_link_speeds2; +#define BNGE_LINK_SPEEDS2_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_50GB +#define BNGE_LINK_SPEEDS2_MSK_100GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100= GB +#define BNGE_LINK_SPEEDS2_MSK_50GB_PAM4 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_50GB_PAM4_56 +#define BNGE_LINK_SPEEDS2_MSK_100GB_PAM4 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100GB_PAM4_56 +#define BNGE_LINK_SPEEDS2_MSK_200GB_PAM4 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_200GB_PAM4_56 +#define BNGE_LINK_SPEEDS2_MSK_400GB_PAM4 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_400GB_PAM4_56 +#define BNGE_LINK_SPEEDS2_MSK_100GB_PAM4_112 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100GB_PAM4_112 +#define BNGE_LINK_SPEEDS2_MSK_200GB_PAM4_112 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_200GB_PAM4_112 +#define BNGE_LINK_SPEEDS2_MSK_400GB_PAM4_112 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_400GB_PAM4_112 +#define BNGE_LINK_SPEEDS2_MSK_800GB_PAM4_112 \ + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_800GB_PAM4_112 + + u16 support_auto_speeds; + u16 support_pam4_auto_speeds; + u16 support_auto_speeds2; + + u16 lp_auto_link_speeds; + u16 lp_auto_pam4_link_speeds; + u16 force_link_speed; + u16 force_pam4_link_speed; + u16 force_link_speed2; +#define BNGE_LINK_SPEED_50GB_PAM4 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_50GB_PAM4_56 +#define BNGE_LINK_SPEED_100GB_PAM4 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_100GB_PAM4_56 +#define BNGE_LINK_SPEED_200GB_PAM4 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_200GB_PAM4_56 +#define BNGE_LINK_SPEED_400GB_PAM4 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_400GB_PAM4_56 +#define BNGE_LINK_SPEED_100GB_PAM4_112 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_100GB_PAM4_112 +#define BNGE_LINK_SPEED_200GB_PAM4_112 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_200GB_PAM4_112 +#define BNGE_LINK_SPEED_400GB_PAM4_112 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_400GB_PAM4_112 +#define BNGE_LINK_SPEED_800GB_PAM4_112 \ + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_800GB_PAM4_112 + + u32 preemphasis; + u8 module_status; + u8 active_fec_sig_mode; + u16 fec_cfg; +#define BNGE_FEC_NONE PORT_PHY_QCFG_RESP_FEC_CFG_FEC_NONE_SUPPORTED +#define BNGE_FEC_AUTONEG_CAP PORT_PHY_QCFG_RESP_FEC_CFG_FEC_AUTONEG_SUPPOR= TED +#define BNGE_FEC_AUTONEG PORT_PHY_QCFG_RESP_FEC_CFG_FEC_AUTONEG_ENABLED +#define BNGE_FEC_ENC_BASE_R_CAP \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE74_SUPPORTED +#define BNGE_FEC_ENC_BASE_R PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE74_ENABLED +#define BNGE_FEC_ENC_RS_CAP \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE91_SUPPORTED +#define BNGE_FEC_ENC_LLRS_CAP \ + (PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_1XN_SUPPORTED | \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_IEEE_SUPPORTED) +#define BNGE_FEC_ENC_RS \ + (PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE91_ENABLED | \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS544_1XN_ENABLED | \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS544_IEEE_ENABLED) +#define BNGE_FEC_ENC_LLRS \ + (PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_1XN_ENABLED | \ + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_IEEE_ENABLED) + + bool phy_retry; + unsigned long phy_retry_expires; + + /* a copy of phy_qcfg output used to report link + * info to VF + */ + struct hwrm_port_phy_qcfg_output phy_qcfg_resp; +}; + +struct bnge_ethtool_link_info { + /* copy of requested setting from ethtool cmd */ + u8 autoneg; +#define BNGE_AUTONEG_SPEED 1 +#define BNGE_AUTONEG_FLOW_CTRL 2 + u8 req_signal_mode; +#define BNGE_SIG_MODE_NRZ PORT_PHY_QCFG_RESP_SIGNAL_MODE_NRZ +#define BNGE_SIG_MODE_PAM4 PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4 +#define BNGE_SIG_MODE_PAM4_112 PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4_112 +#define BNGE_SIG_MODE_MAX (PORT_PHY_QCFG_RESP_SIGNAL_MODE_LAST + 1) + u8 req_duplex; + u8 req_flow_ctrl; + u16 req_link_speed; + u16 advertising; /* user adv setting */ + u16 advertising_pam4; + bool force_link_chng; +}; + +void bnge_hwrm_set_eee(struct bnge_dev *bd, + struct hwrm_port_phy_cfg_input *req); +void bnge_hwrm_set_link_common(struct bnge_net *bn, + struct hwrm_port_phy_cfg_input *req); +void bnge_hwrm_set_pause_common(struct bnge_net *bn, + struct hwrm_port_phy_cfg_input *req); +int bnge_update_phy_setting(struct bnge_net *bn); +void bnge_get_port_module_status(struct bnge_net *bn); +void bnge_report_link(struct bnge_dev *bd); +bool bnge_support_speed_dropped(struct bnge_net *bn); +void bnge_init_ethtool_link_settings(struct bnge_net *bn); +u32 bnge_fw_to_ethtool_speed(u16 fw_link_speed); +int bnge_probe_phy(struct bnge_net *bd, bool fw_dflt); +bool bnge_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *resp); +#endif /* _BNGE_LINK_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 832eeb960bd..4172278900b 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -2192,7 +2192,25 @@ static int bnge_open_core(struct bnge_net *bn) netdev_err(bn->netdev, "bnge_init_nic err: %d\n", rc); goto err_free_irq; } + + mutex_lock(&bd->link_lock); + rc =3D bnge_update_phy_setting(bn); + mutex_unlock(&bd->link_lock); + if (rc) { + netdev_warn(bn->netdev, "failed to update phy settings\n"); + if (BNGE_SINGLE_PF(bd)) { + bd->link_info.phy_retry =3D true; + bd->link_info.phy_retry_expires =3D + jiffies + 5 * HZ; + } + } + set_bit(BNGE_STATE_OPEN, &bd->state); + + /* Poll link status and check for SFP+ module status */ + mutex_lock(&bd->link_lock); + bnge_get_port_module_status(bn); + mutex_unlock(&bd->link_lock); return 0; =20 err_free_irq: @@ -2461,6 +2479,10 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_i= rqs) bnge_init_l2_fltr_tbl(bn); bnge_init_mac_addr(bd); =20 + rc =3D bnge_probe_phy(bn, true); + if (rc) + goto err_netdev; + netdev->request_ops_lock =3D true; rc =3D register_netdev(netdev); if (rc) { diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index fb3b961536b..85c4f6f5371 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -8,6 +8,7 @@ #include #include #include "bnge_db.h" +#include "bnge_link.h" =20 struct tx_bd { __le32 tx_bd_len_flags_type; @@ -231,6 +232,8 @@ struct bnge_net { u8 rss_hash_key_updated:1; int rsscos_nr_ctxs; u32 stats_coal_ticks; + + struct bnge_ethtool_link_info eth_link_info; }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-yx1-f97.google.com (mail-yx1-f97.google.com [74.125.224.97]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EC41A340283 for ; Wed, 26 Nov 2025 19:50:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.97 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186615; cv=none; b=dWfVs6NQofMoGrjBivfpyL1tzdfgvJpuwQsUuo4ei1KSpwE1b+nTNYAVFCFLh2RgmhAoBbn9wXiqe0rgfGkxW10bQW7OMgCgpVVajJQch5bCFSpjxHp11FpxYWJZ1rTXrdHQudtaLDx1YcriZN7HfbI9hOyAi5+Br4jcsgJT1Vk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186615; c=relaxed/simple; bh=hk0dXykGCmNbrFeThn9+TK9B/my7uHNR3BCQlXSq/ms=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lg2+uKy7Y64/1yEZ1UIFSabSLl11EG7Uqpdvcw92gE+Di8dEk/roCI5SDq9xo2rxmPKNrLuJTWJ7/TvS60l5+Ey+61ZwSVBm0ublola3Nmlk65fHDm3nBytXgGT/9/hi0jmegui/nJXL6g3c/TJ66zE6lRe+hBRX9UQFkjJtgCY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=Zsjbv/6v; arc=none smtp.client-ip=74.125.224.97 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="Zsjbv/6v" Received: by mail-yx1-f97.google.com with SMTP id 956f58d0204a3-640daf41b19so259313d50.0 for ; Wed, 26 Nov 2025 11:50:13 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186613; x=1764791413; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=lolwq9gTk1seDw4oQyBfgaM19vDbI49PtwNcLlnVu/g=; b=Z9ciEQsqzRar/RVNz0drA5YAMjrT+bhCl2LExEnCWzO4SAjtoDs9d9IwHN2G6Dt1ZP YebuzgxaZM84G5PjuEOIpn9zucZxEQ0QoOA1D74hLinu8wAkGLu6EXVmak4sE6yBDGjg 62vm/nKd4+EevASEBylKVbvU2XU5+vSfgXKfuh9M3DqE4TwlqR1d01Xh9ZfPsvUfUYOv h4cgllzU+nk1J98TFCoCbpjpx2ismCdRR2S1f6JTqAhCUkJFy10uZH1sUm+Of9FBQVTl mp0KUdqw+hU00cqOlPlBCcM2/Rg1iELYFdOQcBO12opcwt/rsaHAI2+uaEO6CrR+H8D0 Smkw== X-Forwarded-Encrypted: i=1; AJvYcCVsAIEsGhDCzeCwczpSjc+J75h2VMH1IdXRlodWk4SbmbS3+XOYxfLFmItx7WC2Y5Yeg8TkF1F3F5oRhLU=@vger.kernel.org X-Gm-Message-State: AOJu0YzYhGAMHOK/dznCjBDc/hVJS1VrL25NRGpZaK8FHm7PRZjxiPTo fl706xFWDwxgFMo4iRyos5ePkBMlB5Gro0ccPdQdLYBHhL0j56hltJ7VBsjQltYQKzrz9w0qXaU WZSl2AFl8P6EPhO98km99hn+Xt9ebIhTDJRtFYmJht9QhAo9tRakxzMbLWsun8ADXZrI7iGZBfG NREqmLuL+8HeBGXecDL6ecKtbrrOlWbiIbpMEqVBJm3+D4jk+BxiE2WfnnlgZBsW+xOfLSE54YS ll1W7v+V475amrmnfkuVfnHNpl1 X-Gm-Gg: ASbGnctQGlqjq746K6vt3KGQ+xbfy+qXZdXxxsu9WtyNPdvWipiXKjMlyqirg4yCmho ENrUbepDa4cxmJEq99WEhoVlPBboM7gGaqRaphb33gxW2+deLTG8KqxDhwdYO06yYqpBNU6Wqi/ zAvg19+Dx9Tjd0FFnMrtbZGRxMhywF/ADM0OPhNvYugCx0nZuHR0xgR78ozXZkmMXjjOFT65IBq GLb6vlO3cg9NjT6yJKSxK9vgeII+EvpUVY2ZQe0VeK9vTKG+Upx4GWiGYrokscojgy1U2/HrU/6 tWq9pgwW4AmBUrSmrgC+/jkpkeBM3YCFc2g26mPEpBVtidJZCfG++udaaQo2XLHO6LHATHEP0P3 yvmtVyU+4lj0ejymIYF5yu3flzN2UCB2RX1gOXKusMHhjEoofPiUX/6uukykEYzNQQcKl3w0RwJ XfoQQJHtGGXmhWxluwxncrtf4e60jr+w77Vste+Q4F2ylYZeani8s= X-Google-Smtp-Source: AGHT+IF7jrX7sM9p2JhjPdUB4oo5bwlOjc3wUVomdHYQUF1GGdaai447fPtcdUyqGAWZ77cXzufF4Pthruay X-Received: by 2002:a05:690e:1c1a:b0:63f:b985:66b5 with SMTP id 956f58d0204a3-64302592bf6mr13454564d50.6.1764186612651; Wed, 26 Nov 2025 11:50:12 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-77.dlp.protect.broadcom.com. [144.49.247.77]) by smtp-relay.gmail.com with ESMTPS id 956f58d0204a3-642f70cf301sm1786957d50.7.2025.11.26.11.50.12 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:12 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pg1-f200.google.com with SMTP id 41be03b00d2f7-bd74e95f05aso752155a12.1 for ; Wed, 26 Nov 2025 11:50:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186610; x=1764791410; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lolwq9gTk1seDw4oQyBfgaM19vDbI49PtwNcLlnVu/g=; b=Zsjbv/6vyIoaHUJokIehU4X0px4LHVkMKeUw3RbDPiYNqcKVM7hDpG0qRlz9sYCJP8 9FvecrqNhUufb0hJxJ1VF+kYLUpVxDp26yDuDI04e9XhKpXi/nkxOJrfeRgAMnHPWB7v aKdXzbyKf1j8uNTrDaVJNdcf7oONK+W8Yw/50= X-Forwarded-Encrypted: i=1; AJvYcCWDg0SrPiXojtIZ/YNBZAyaC5FHXA2LoENpL3Ua9xVRTFEHswuZa7xuLGTK+8o5v8Z7wbMENGb3ZxL5Mco=@vger.kernel.org X-Received: by 2002:a17:902:ea0e:b0:295:5898:ff5c with SMTP id d9443c01a7336-29b6bfa9738mr273543195ad.16.1764186610639; Wed, 26 Nov 2025 11:50:10 -0800 (PST) X-Received: by 2002:a17:902:ea0e:b0:295:5898:ff5c with SMTP id d9443c01a7336-29b6bfa9738mr273542975ad.16.1764186610174; Wed, 26 Nov 2025 11:50:10 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:09 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 02/12] bng_en: Extend bnge_set_ring_params() for rx-copybreak Date: Thu, 27 Nov 2025 01:19:21 +0530 Message-ID: <20251126194931.455830-3-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Add rx-copybreak support in bnge_set_ring_params() Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 19 +++++++++++++++++-- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 5 +++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 4172278900b..d0462bd1db0 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include =20 @@ -2313,7 +2314,6 @@ void bnge_set_ring_params(struct bnge_dev *bd) rx_space =3D rx_size + ALIGN(NET_SKB_PAD, 8) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); =20 - bn->rx_copy_thresh =3D BNGE_RX_COPY_THRESH; ring_size =3D bn->rx_ring_size; bn->rx_agg_ring_size =3D 0; bn->rx_agg_nr_pages =3D 0; @@ -2352,7 +2352,10 @@ void bnge_set_ring_params(struct bnge_dev *bd) bn->rx_agg_ring_size =3D agg_ring_size; bn->rx_agg_ring_mask =3D (bn->rx_agg_nr_pages * RX_DESC_CNT) - 1; =20 - rx_size =3D SKB_DATA_ALIGN(BNGE_RX_COPY_THRESH + NET_IP_ALIGN); + rx_size =3D max3(BNGE_DEFAULT_RX_COPYBREAK, + bn->rx_copybreak, + bn->netdev->cfg_pending->hds_thresh); + rx_size =3D SKB_DATA_ALIGN(rx_size + NET_IP_ALIGN); rx_space =3D rx_size + NET_SKB_PAD + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); } @@ -2385,6 +2388,17 @@ void bnge_set_ring_params(struct bnge_dev *bd) bn->cp_ring_mask =3D bn->cp_bit - 1; } =20 +static void bnge_init_ring_params(struct bnge_net *bn) +{ + u32 rx_size; + + bn->rx_copybreak =3D BNGE_DEFAULT_RX_COPYBREAK; + /* Try to fit 4 chunks into a 4k page */ + rx_size =3D SZ_1K - + NET_SKB_PAD - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + bn->netdev->cfg->hds_thresh =3D max(BNGE_DEFAULT_RX_COPYBREAK, rx_size); +} + int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs) { struct net_device *netdev; @@ -2474,6 +2488,7 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_ir= qs) bn->rx_dir =3D DMA_FROM_DEVICE; =20 bnge_set_tpa_flags(bd); + bnge_init_ring_params(bn); bnge_set_ring_params(bd); =20 bnge_init_l2_fltr_tbl(bn); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 85c4f6f5371..b267f0b14c1 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -136,7 +136,8 @@ struct bnge_ring_grp_info { u16 nq_fw_ring_id; }; =20 -#define BNGE_RX_COPY_THRESH 256 +#define BNGE_DEFAULT_RX_COPYBREAK 256 +#define BNGE_MAX_RX_COPYBREAK 1024 =20 #define BNGE_HW_FEATURE_VLAN_ALL_RX \ (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX) @@ -187,7 +188,7 @@ struct bnge_net { u32 rx_buf_size; u32 rx_buf_use_size; /* usable size */ u32 rx_agg_ring_size; - u32 rx_copy_thresh; + u32 rx_copybreak; u32 rx_ring_mask; u32 rx_agg_ring_mask; u16 rx_nr_pages; --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-il1-f226.google.com (mail-il1-f226.google.com [209.85.166.226]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4EFC9340D82 for ; Wed, 26 Nov 2025 19:50:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186621; cv=none; b=LJJv+m17O1s1yLOHRIAUUnuskVPeKL4a9dM+jcuIzdekn/5tgVowF7WkMWZspyk5lqUf8cftiu43f2Rlawzul61rGluqt8j+i5n6pDP3IMFfg/kaP8RWgKp1BLGwwZ+jHNI5P/TS5lGF4nE2s4EYdIpsQYZDQrvSasCT50xYiHE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186621; c=relaxed/simple; bh=/xupJY2WCU0xeyZVlDKTg1msZC+jRsSrfUBQ+gjZpgA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u+78n4GLEgLMirazsd1Hn7AfjK6ArW8nF16mUmPuMiSuIg3LmJXN87T/xPnw4nIUlqX7rtU6cvk4ub8g9fhkQ9iwNm8mJT5arZT5LOF68Jsb6FX5mHxirhRet133zu9fXreN4N5koeNHwudMoA2ZBdn7ulQxn59EGRvVjWovg+s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=Q2ZJF/cL; arc=none smtp.client-ip=209.85.166.226 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="Q2ZJF/cL" Received: by mail-il1-f226.google.com with SMTP id e9e14a558f8ab-433100c59dcso821465ab.0 for ; Wed, 26 Nov 2025 11:50:18 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186617; x=1764791417; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=WM4eDdGVsyHwewDLhOnVtUgbzbQBp9gKhp+mhCWvBsY=; b=YVzQOkAigo/ovC84o8/S2sstwnDEBKlBmbPm6ksx5xhoYHZgg3t5IUXOI1eaWF44He 3/4b6V+xk4BAEDxSbEK1h6I9t1A6gzd/RV8GXvSMXe+u4NihGMFQKJVu1MYtw9YfqZiw o6BjF1/zYeHchduPHE6jU3LjdLZ3NrSaEm7pv8EkGpgMSLmE19XgPHYFStDi/OwELl0T 6acyNqPHwR428Y9lMXwhB5a3/dF/p7ZzECf9GBIIy3i6n2WNQlHRJfoS7TwItonA2KnZ 3ojpwRWvpJ3DWOBAl6Pt9IyzlKf/r4zvLjBwxcjPX/cs0m+yVzte0z8OxcfXYWoC6oiM Qdew== X-Forwarded-Encrypted: i=1; AJvYcCX8RKhlD4K8jUfvfY8KYSwoR4xd1+DhvH+qxfiBfljKZ36QY5aNYM56aCT4r4Es8CACb3+epTlcKThDyyM=@vger.kernel.org X-Gm-Message-State: AOJu0Yx9uimGRDYr5+ahtFRgK7Pajb+LewIdAimBbi9bgNMkaLizzHYK e593GJ0+M1gMPT5A/Zoa0JyR4S6mCAsd7l5L+iEaAvCSLqRj1A56nPX8Wd15zc1KLwjzFW9GmEE tncmQwtRbKrECTgeAgqaKD+iqjzVknyKIoYBLj9mPkRIb9U2r8GgzYBq4f4vzJSsw3Fd8n4F0Ll X3Mtkd9WNX3/4xXYKwN2Fs0fTA9651iLfpCjyOVfOkZR6hdrDtiVc947PUSJKskN6x6L8n/sajx L950lNqdSJVP48XhUnYnTcmwA== X-Gm-Gg: ASbGnctEm/Y9LO6BmnW3oPm9BmmXFnnd7rrFeVC5euO9OV54EKHaK5R7KbsbjBtNOLm xdaGAy+h2JKAuibIlrZYyGCqfrCT+OBMx6y4kQujWhGcEuFVixTpcm8Ro7cF7Je3rjZQPCiK95V D7YzBf1tLtxdjXL5nqIv5s3Dpa4s+CW0rkvkfuLGDc9idFrljoL2w6dX90UvuMKaC0fxtA1XNit ZpZueqBzScGVMnjkLeHEiMH5JcD1/P85YblN0X88xQanae/sYu5KNGboD+eZP/g2bD1W9ToLRBa u7fMiwlpkG1EWMi1rw4kOJpZVVXmjlfRJzd7ym2003z8/wa3HDYAJ/Sc33HknHHciG4FR+5TKYb ebbXu42hWZ54CtLwNxg01clAkKRrjEo/JCK7WOw/oePXgATPhmjfK2NR+wwZCPpF/lr6v260CYf uzv7QNWcmYj2wABTnSSW9aVGtQMhEVNLHWg5cbL1zA1mzbpE/D+WR4jg== X-Google-Smtp-Source: AGHT+IFMbn2BHEa2hqQ0bh+nbnQOVymxpgOhmZ0n8ovx29Ds8gN5S2xVhOQZKBng6QmoX2R4b+zYZvZodjVv X-Received: by 2002:a92:ca08:0:b0:433:3316:17db with SMTP id e9e14a558f8ab-435dd051100mr62351925ab.4.1764186617412; Wed, 26 Nov 2025 11:50:17 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-116.dlp.protect.broadcom.com. [144.49.247.116]) by smtp-relay.gmail.com with ESMTPS id e9e14a558f8ab-435a905df3csm18166295ab.13.2025.11.26.11.50.16 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:17 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-299ddb0269eso1316615ad.0 for ; Wed, 26 Nov 2025 11:50:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186616; x=1764791416; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WM4eDdGVsyHwewDLhOnVtUgbzbQBp9gKhp+mhCWvBsY=; b=Q2ZJF/cL91krL7zToohUAOc+kEZ0rmkHFOTBPHsyMw6F20VQUjOFGC7Sv2/PWk+wCF uyJhw9xOgChJR2e+hFAHoVu6lsoj4kqHMzZEGe1b3YSg9HyElgjSyggNImJTIs98VKNI a/nsniP7U6TxJaeCSSwOl/R7tOQdgIz+eSsN4= X-Forwarded-Encrypted: i=1; AJvYcCXlL9CpExKCJUzcInSklzu7zQ86Tdc9FtZAKUoQZ1ZoCVAOv0LJzSJlksOQqyvDUIJvXEv6mDhm0cS+tME=@vger.kernel.org X-Received: by 2002:a17:902:da82:b0:269:82a5:f9e9 with SMTP id d9443c01a7336-29bab148972mr90227655ad.29.1764186615464; Wed, 26 Nov 2025 11:50:15 -0800 (PST) X-Received: by 2002:a17:902:da82:b0:269:82a5:f9e9 with SMTP id d9443c01a7336-29bab148972mr90227265ad.29.1764186614866; Wed, 26 Nov 2025 11:50:14 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:14 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 03/12] bng_en: Add RX support Date: Thu, 27 Nov 2025 01:19:22 +0530 Message-ID: <20251126194931.455830-4-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Add support to receive packet using NAPI, build and deliver the skb to stac= k. With help of meta data available in completions, fill the appropriate information in skb. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- drivers/net/ethernet/broadcom/bnge/Makefile | 3 +- .../net/ethernet/broadcom/bnge/bnge_hw_def.h | 198 ++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.c | 111 +++- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 60 +- .../net/ethernet/broadcom/bnge/bnge_txrx.c | 579 ++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_txrx.h | 83 +++ 6 files changed, 1013 insertions(+), 21 deletions(-) create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_txrx.c create mode 100644 drivers/net/ethernet/broadcom/bnge/bnge_txrx.h diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethe= rnet/broadcom/bnge/Makefile index f30db7e5f48..1fedd7a0f14 100644 --- a/drivers/net/ethernet/broadcom/bnge/Makefile +++ b/drivers/net/ethernet/broadcom/bnge/Makefile @@ -10,4 +10,5 @@ bng_en-y :=3D bnge_core.o \ bnge_resc.o \ bnge_netdev.o \ bnge_ethtool.o \ - bnge_link.o + bnge_link.o \ + bnge_txrx.o diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h b/drivers/net= /ethernet/broadcom/bnge/bnge_hw_def.h new file mode 100644 index 00000000000..4da4259095f --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2025 Broadcom */ + +#ifndef _BNGE_HW_DEF_H_ +#define _BNGE_HW_DEF_H_ + +struct tx_bd_ext { + __le32 tx_bd_hsize_lflags; + #define TX_BD_FLAGS_TCP_UDP_CHKSUM (1 << 0) + #define TX_BD_FLAGS_IP_CKSUM (1 << 1) + #define TX_BD_FLAGS_NO_CRC (1 << 2) + #define TX_BD_FLAGS_STAMP (1 << 3) + #define TX_BD_FLAGS_T_IP_CHKSUM (1 << 4) + #define TX_BD_FLAGS_LSO (1 << 5) + #define TX_BD_FLAGS_IPID_FMT (1 << 6) + #define TX_BD_FLAGS_T_IPID (1 << 7) + #define TX_BD_HSIZE (0xff << 16) + #define TX_BD_HSIZE_SHIFT 16 + + __le32 tx_bd_mss; + __le32 tx_bd_cfa_action; + #define TX_BD_CFA_ACTION (0xffff << 16) + #define TX_BD_CFA_ACTION_SHIFT 16 + + __le32 tx_bd_cfa_meta; + #define TX_BD_CFA_META_MASK 0xfffffff + #define TX_BD_CFA_META_VID_MASK 0xfff + #define TX_BD_CFA_META_PRI_MASK (0xf << 12) + #define TX_BD_CFA_META_PRI_SHIFT 12 + #define TX_BD_CFA_META_TPID_MASK (3 << 16) + #define TX_BD_CFA_META_TPID_SHIFT 16 + #define TX_BD_CFA_META_KEY (0xf << 28) + #define TX_BD_CFA_META_KEY_SHIFT 28 + #define TX_BD_CFA_META_KEY_VLAN (1 << 28) +}; + +#define TX_CMP_SQ_CONS_IDX(txcmp) \ + (le32_to_cpu((txcmp)->sq_cons_idx) & TX_CMP_SQ_CONS_IDX_MASK) + +struct rx_cmp { + __le32 rx_cmp_len_flags_type; + #define RX_CMP_CMP_TYPE (0x3f << 0) + #define RX_CMP_FLAGS_ERROR (1 << 6) + #define RX_CMP_FLAGS_PLACEMENT (7 << 7) + #define RX_CMP_FLAGS_RSS_VALID (1 << 10) + #define RX_CMP_FLAGS_PKT_METADATA_PRESENT (1 << 11) + #define RX_CMP_FLAGS_ITYPES_SHIFT 12 + #define RX_CMP_FLAGS_ITYPES_MASK 0xf000 + #define RX_CMP_FLAGS_ITYPE_UNKNOWN (0 << 12) + #define RX_CMP_FLAGS_ITYPE_IP (1 << 12) + #define RX_CMP_FLAGS_ITYPE_TCP (2 << 12) + #define RX_CMP_FLAGS_ITYPE_UDP (3 << 12) + #define RX_CMP_FLAGS_ITYPE_FCOE (4 << 12) + #define RX_CMP_FLAGS_ITYPE_ROCE (5 << 12) + #define RX_CMP_FLAGS_ITYPE_PTP_WO_TS (8 << 12) + #define RX_CMP_FLAGS_ITYPE_PTP_W_TS (9 << 12) + #define RX_CMP_LEN (0xffff << 16) + #define RX_CMP_LEN_SHIFT 16 + + u32 rx_cmp_opaque; + __le32 rx_cmp_misc_v1; + #define RX_CMP_V1 (1 << 0) + #define RX_CMP_AGG_BUFS (0x1f << 1) + #define RX_CMP_AGG_BUFS_SHIFT 1 + #define RX_CMP_RSS_HASH_TYPE (0x7f << 9) + #define RX_CMP_RSS_HASH_TYPE_SHIFT 9 + #define RX_CMP_V3_RSS_EXT_OP_LEGACY (0xf << 12) + #define RX_CMP_V3_RSS_EXT_OP_LEGACY_SHIFT 12 + #define RX_CMP_V3_RSS_EXT_OP_NEW (0xf << 8) + #define RX_CMP_V3_RSS_EXT_OP_NEW_SHIFT 8 + #define RX_CMP_PAYLOAD_OFFSET (0xff << 16) + #define RX_CMP_PAYLOAD_OFFSET_SHIFT 16 + #define RX_CMP_SUB_NS_TS (0xf << 16) + #define RX_CMP_SUB_NS_TS_SHIFT 16 + #define RX_CMP_METADATA1 (0xf << 28) + #define RX_CMP_METADATA1_SHIFT 28 + #define RX_CMP_METADATA1_TPID_SEL (0x7 << 28) + #define RX_CMP_METADATA1_TPID_8021Q (0x1 << 28) + #define RX_CMP_METADATA1_TPID_8021AD (0x0 << 28) + #define RX_CMP_METADATA1_VALID (0x8 << 28) + + __le32 rx_cmp_rss_hash; +}; + +struct rx_cmp_ext { + __le32 rx_cmp_flags2; + #define RX_CMP_FLAGS2_IP_CS_CALC 0x1 + #define RX_CMP_FLAGS2_L4_CS_CALC (0x1 << 1) + #define RX_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2) + #define RX_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3) + #define RX_CMP_FLAGS2_META_FORMAT_VLAN (0x1 << 4) + __le32 rx_cmp_meta_data; + #define RX_CMP_FLAGS2_METADATA_TCI_MASK 0xffff + #define RX_CMP_FLAGS2_METADATA_VID_MASK 0xfff + #define RX_CMP_FLAGS2_METADATA_TPID_MASK 0xffff0000 + #define RX_CMP_FLAGS2_METADATA_TPID_SFT 16 + __le32 rx_cmp_cfa_code_errors_v2; + #define RX_CMP_V (1 << 0) + #define RX_CMPL_ERRORS_MASK (0x7fff << 1) + #define RX_CMPL_ERRORS_SFT 1 + #define RX_CMPL_ERRORS_BUFFER_ERROR_MASK (0x7 << 1) + #define RX_CMPL_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) + #define RX_CMPL_ERRORS_BUFFER_ERROR_DID_NOT_FIT (0x1 << 1) + #define RX_CMPL_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (0x2 << 1) + #define RX_CMPL_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) + #define RX_CMPL_ERRORS_IP_CS_ERROR (0x1 << 4) + #define RX_CMPL_ERRORS_L4_CS_ERROR (0x1 << 5) + #define RX_CMPL_ERRORS_T_IP_CS_ERROR (0x1 << 6) + #define RX_CMPL_ERRORS_T_L4_CS_ERROR (0x1 << 7) + #define RX_CMPL_ERRORS_CRC_ERROR (0x1 << 8) + #define RX_CMPL_ERRORS_T_PKT_ERROR_MASK (0x7 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_NO_ERROR (0x0 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_VERSION (0x1 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_HDR_LEN (0x2 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_TUNNEL_TOTAL_ERROR (0x3 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_T_IP_TOTAL_ERROR (0x4 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_T_UDP_TOTAL_ERROR (0x5 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL (0x6 << 9) + #define RX_CMPL_ERRORS_PKT_ERROR_MASK (0xf << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_NO_ERROR (0x0 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_VERSION (0x1 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_HDR_LEN (0x2 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_TTL (0x3 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_IP_TOTAL_ERROR (0x4 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_UDP_TOTAL_ERROR (0x5 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN (0x6 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN_TOO_SMALL (0x7 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN (0x8 << 12) + + #define RX_CMPL_CFA_CODE_MASK (0xffff << 16) + #define RX_CMPL_CFA_CODE_SFT 16 + #define RX_CMPL_METADATA0_TCI_MASK (0xffff << 16) + #define RX_CMPL_METADATA0_VID_MASK (0x0fff << 16) + #define RX_CMPL_METADATA0_SFT 16 + + __le32 rx_cmp_timestamp; +}; + +#define RX_CMP_L2_ERRORS \ + cpu_to_le32(RX_CMPL_ERRORS_BUFFER_ERROR_MASK | RX_CMPL_ERRORS_CRC_ERROR) + +#define RX_CMP_L4_CS_BITS \ + (cpu_to_le32(RX_CMP_FLAGS2_L4_CS_CALC | RX_CMP_FLAGS2_T_L4_CS_CALC)) + +#define RX_CMP_L4_CS_ERR_BITS \ + (cpu_to_le32(RX_CMPL_ERRORS_L4_CS_ERROR | RX_CMPL_ERRORS_T_L4_CS_ERROR)) + +#define RX_CMP_L4_CS_OK(rxcmp1) \ + (((rxcmp1)->rx_cmp_flags2 & RX_CMP_L4_CS_BITS) && \ + !((rxcmp1)->rx_cmp_cfa_code_errors_v2 & RX_CMP_L4_CS_ERR_BITS)) + +#define RX_CMP_METADATA0_TCI(rxcmp1) \ + ((le32_to_cpu((rxcmp1)->rx_cmp_cfa_code_errors_v2) & \ + RX_CMPL_METADATA0_TCI_MASK) >> RX_CMPL_METADATA0_SFT) + +#define RX_CMP_ENCAP(rxcmp1) \ + ((le32_to_cpu((rxcmp1)->rx_cmp_flags2) & \ + RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3) + +#define RX_CMP_V3_HASH_TYPE_LEGACY(rxcmp) \ + ((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & \ + RX_CMP_V3_RSS_EXT_OP_LEGACY) >> RX_CMP_V3_RSS_EXT_OP_LEGACY_SHIFT) + +#define RX_CMP_V3_HASH_TYPE_NEW(rxcmp) \ + ((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_V3_RSS_EXT_OP_NEW) >>\ + RX_CMP_V3_RSS_EXT_OP_NEW_SHIFT) + +#define RX_CMP_V3_HASH_TYPE(bd, rxcmp) \ + (((bd)->rss_cap & BNGE_RSS_CAP_RSS_TCAM) ? \ + RX_CMP_V3_HASH_TYPE_NEW(rxcmp) : \ + RX_CMP_V3_HASH_TYPE_LEGACY(rxcmp)) + +#define EXT_OP_INNER_4 0x0 +#define EXT_OP_OUTER_4 0x2 +#define EXT_OP_INNFL_3 0x8 +#define EXT_OP_OUTFL_3 0xa + +#define RX_CMP_VLAN_VALID(rxcmp) \ + ((rxcmp)->rx_cmp_misc_v1 & cpu_to_le32(RX_CMP_METADATA1_VALID)) + +#define RX_CMP_VLAN_TPID_SEL(rxcmp) \ + (le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_METADATA1_TPID_SEL) + +#define RSS_PROFILE_ID_MASK 0x1f + +#define RX_CMP_HASH_TYPE(rxcmp) \ + (((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_RSS_HASH_TYPE) >>\ + RX_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK) + +#define RX_CMP_HASH_VALID(rxcmp) \ + ((rxcmp)->rx_cmp_len_flags_type & cpu_to_le32(RX_CMP_FLAGS_RSS_VALID)) + +#define HWRM_RING_ALLOC_TX 0x1 +#define HWRM_RING_ALLOC_RX 0x2 +#define HWRM_RING_ALLOC_AGG 0x4 +#define HWRM_RING_ALLOC_CMPL 0x8 +#define HWRM_RING_ALLOC_NQ 0x10 +#endif /* _BNGE_HW_DEF_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index d0462bd1db0..c43b729e23c 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -21,6 +21,7 @@ #include "bnge_hwrm_lib.h" #include "bnge_ethtool.h" #include "bnge_rmem.h" +#include "bnge_txrx.h" =20 #define BNGE_RING_TO_TC_OFF(bd, tx) \ ((tx) % (bd)->tx_nr_rings_per_tc) @@ -857,6 +858,13 @@ u16 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr) return txr->tx_cpr->ring_struct.fw_ring_id; } =20 +static void bnge_db_nq_arm(struct bnge_net *bn, + struct bnge_db_info *db, u32 idx) +{ + bnge_writeq(bn->bd, db->db_key64 | DBR_TYPE_NQ_ARM | + DB_RING_IDX(db, idx), db->doorbell); +} + static void bnge_db_nq(struct bnge_net *bn, struct bnge_db_info *db, u32 i= dx) { bnge_writeq(bn->bd, db->db_key64 | DBR_TYPE_NQ_MASK | @@ -879,12 +887,6 @@ static int bnge_cp_num_to_irq_num(struct bnge_net *bn,= int n) return nqr->ring_struct.map_idx; } =20 -static irqreturn_t bnge_msix(int irq, void *dev_instance) -{ - /* NAPI scheduling to be added in a future patch */ - return IRQ_HANDLED; -} - static void bnge_init_nq_tree(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; @@ -942,9 +944,8 @@ static u8 *__bnge_alloc_rx_frag(struct bnge_net *bn, dm= a_addr_t *mapping, return page_address(page) + offset; } =20 -static int bnge_alloc_rx_data(struct bnge_net *bn, - struct bnge_rx_ring_info *rxr, - u16 prod, gfp_t gfp) +int bnge_alloc_rx_data(struct bnge_net *bn, struct bnge_rx_ring_info *rxr, + u16 prod, gfp_t gfp) { struct bnge_sw_rx_bd *rx_buf =3D &rxr->rx_buf_ring[RING_RX(bn, prod)]; struct rx_bd *rxbd; @@ -1756,6 +1757,78 @@ static int bnge_cfg_def_vnic(struct bnge_net *bn) return rc; } =20 +static void bnge_disable_int(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i; + + if (!bn->bnapi) + return; + + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; + struct bnge_ring_struct *ring =3D &nqr->ring_struct; + + if (ring->fw_ring_id !=3D INVALID_HW_RING_ID) + bnge_db_nq(bn, &nqr->nq_db, nqr->nq_raw_cons); + } +} + +static void bnge_disable_int_sync(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i; + + bnge_disable_int(bn); + for (i =3D 0; i < bd->nq_nr_rings; i++) { + int map_idx =3D bnge_cp_num_to_irq_num(bn, i); + + synchronize_irq(bd->irq_tbl[map_idx].vector); + } +} + +static void bnge_enable_int(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i; + + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; + + bnge_db_nq_arm(bn, &nqr->nq_db, nqr->nq_raw_cons); + } +} + +static void bnge_disable_napi(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i; + + if (test_and_set_bit(BNGE_STATE_NAPI_DISABLED, &bn->state)) + return; + + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + + napi_disable_locked(&bnapi->napi); + } +} + +static void bnge_enable_napi(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i; + + clear_bit(BNGE_STATE_NAPI_DISABLED, &bn->state); + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + + napi_enable_locked(&bnapi->napi); + } +} + static void bnge_hwrm_vnic_free(struct bnge_net *bn) { int i; @@ -1887,6 +1960,12 @@ static void bnge_hwrm_ring_free(struct bnge_net *bn,= bool close_path) bnge_hwrm_rx_agg_ring_free(bn, &bn->rx_ring[i], close_path); } =20 + /* The completion rings are about to be freed. After that the + * IRQ doorbell will not work anymore. So we need to disable + * IRQ here. + */ + bnge_disable_int_sync(bn); + for (i =3D 0; i < bd->nq_nr_rings; i++) { struct bnge_napi *bnapi =3D bn->bnapi[i]; struct bnge_nq_ring_info *nqr; @@ -2086,16 +2165,6 @@ static int bnge_init_chip(struct bnge_net *bn) return rc; } =20 -static int bnge_napi_poll(struct napi_struct *napi, int budget) -{ - int work_done =3D 0; - - /* defer NAPI implementation to next patch series */ - napi_complete_done(napi, work_done); - - return work_done; -} - static void bnge_init_napi(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; @@ -2194,6 +2263,8 @@ static int bnge_open_core(struct bnge_net *bn) goto err_free_irq; } =20 + bnge_enable_napi(bn); + mutex_lock(&bd->link_lock); rc =3D bnge_update_phy_setting(bn); mutex_unlock(&bd->link_lock); @@ -2208,6 +2279,7 @@ static int bnge_open_core(struct bnge_net *bn) =20 set_bit(BNGE_STATE_OPEN, &bd->state); =20 + bnge_enable_int(bn); /* Poll link status and check for SFP+ module status */ mutex_lock(&bd->link_lock); bnge_get_port_module_status(bn); @@ -2254,6 +2326,7 @@ static void bnge_close_core(struct bnge_net *bn) =20 clear_bit(BNGE_STATE_OPEN, &bd->state); bnge_shutdown_nic(bn); + bnge_disable_napi(bn); bnge_free_all_rings_bufs(bn); bnge_free_irq(bn); bnge_del_napi(bn); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index b267f0b14c1..41af5827a25 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -9,6 +9,7 @@ #include #include "bnge_db.h" #include "bnge_link.h" +#include "bnge_hw_def.h" =20 struct tx_bd { __le32 tx_bd_len_flags_type; @@ -174,10 +175,16 @@ enum { #define RING_RX_AGG(bn, idx) ((idx) & (bn)->rx_agg_ring_mask) #define NEXT_RX_AGG(idx) ((idx) + 1) =20 +#define BNGE_NQ_HDL_IDX_MASK 0x00ffffff +#define BNGE_NQ_HDL_TYPE_MASK 0xff000000 #define BNGE_NQ_HDL_TYPE_SHIFT 24 #define BNGE_NQ_HDL_TYPE_RX 0x00 #define BNGE_NQ_HDL_TYPE_TX 0x01 =20 +#define BNGE_NQ_HDL_IDX(hdl) ((hdl) & BNGE_NQ_HDL_IDX_MASK) +#define BNGE_NQ_HDL_TYPE(hdl) (((hdl) & BNGE_NQ_HDL_TYPE_MASK) >> \ + BNGE_NQ_HDL_TYPE_SHIFT) + struct bnge_net { struct bnge_dev *bd; struct net_device *netdev; @@ -235,6 +242,9 @@ struct bnge_net { u32 stats_coal_ticks; =20 struct bnge_ethtool_link_info eth_link_info; + + unsigned long state; +#define BNGE_STATE_NAPI_DISABLED 0 }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 @@ -281,9 +291,25 @@ void bnge_set_ring_params(struct bnge_dev *bd); txr =3D (iter < BNGE_MAX_TXR_PER_NAPI - 1) ? \ (bnapi)->tx_ring[++iter] : NULL) =20 +#define DB_EPOCH(db, idx) (((idx) & (db)->db_epoch_mask) << \ + ((db)->db_epoch_shift)) + +#define DB_TOGGLE(tgl) ((tgl) << DBR_TOGGLE_SFT) + +#define DB_RING_IDX(db, idx) (((idx) & (db)->db_ring_mask) | \ + DB_EPOCH(db, idx)) + #define BNGE_SET_NQ_HDL(cpr) \ (((cpr)->cp_ring_type << BNGE_NQ_HDL_TYPE_SHIFT) | (cpr)->cp_idx) =20 +#define BNGE_DB_NQ(bd, db, idx) \ + bnge_writeq(bd, (db)->db_key64 | DBR_TYPE_NQ | DB_RING_IDX(db, idx),\ + (db)->doorbell) + +#define BNGE_DB_NQ_ARM(bd, db, idx) \ + bnge_writeq(bd, (db)->db_key64 | DBR_TYPE_NQ_ARM | \ + DB_RING_IDX(db, idx), (db)->doorbell) + struct bnge_stats_mem { u64 *sw_stats; u64 *hw_masks; @@ -292,6 +318,25 @@ struct bnge_stats_mem { int len; }; =20 +struct nqe_cn { + __le16 type; + #define NQ_CN_TYPE_MASK 0x3fUL + #define NQ_CN_TYPE_SFT 0 + #define NQ_CN_TYPE_CQ_NOTIFICATION 0x30UL + #define NQ_CN_TYPE_LAST NQ_CN_TYPE_CQ_NOTIFICATION + #define NQ_CN_TOGGLE_MASK 0xc0UL + #define NQ_CN_TOGGLE_SFT 6 + __le16 reserved16; + __le32 cq_handle_low; + __le32 v; + #define NQ_CN_V 0x1UL + __le32 cq_handle_high; +}; + +#define NQE_CN_TYPE(type) ((type) & NQ_CN_TYPE_MASK) +#define NQE_CN_TOGGLE(type) (((type) & NQ_CN_TOGGLE_MASK) >> \ + NQ_CN_TOGGLE_SFT) + struct bnge_cp_ring_info { struct bnge_napi *bnapi; dma_addr_t *desc_mapping; @@ -301,6 +346,10 @@ struct bnge_cp_ring_info { u8 cp_idx; u32 cp_raw_cons; struct bnge_db_info cp_db; + u8 had_work_done:1; + u8 has_more_work:1; + u8 had_nqe_notify:1; + u8 toggle; }; =20 struct bnge_nq_ring_info { @@ -313,8 +362,9 @@ struct bnge_nq_ring_info { =20 struct bnge_stats_mem stats; u32 hw_stats_ctx_id; + u8 has_more_work:1; =20 - int cp_ring_count; + u16 cp_ring_count; struct bnge_cp_ring_info *cp_ring_arr; }; =20 @@ -377,6 +427,12 @@ struct bnge_napi { struct bnge_nq_ring_info nq_ring; struct bnge_rx_ring_info *rx_ring; struct bnge_tx_ring_info *tx_ring[BNGE_MAX_TXR_PER_NAPI]; + u8 events; +#define BNGE_RX_EVENT 1 +#define BNGE_AGG_EVENT 2 +#define BNGE_TX_EVENT 4 +#define BNGE_REDIRECT_EVENT 8 +#define BNGE_TX_CMP_EVENT 0x10 }; =20 #define INVALID_STATS_CTX_ID -1 @@ -455,4 +511,6 @@ struct bnge_l2_filter { u16 bnge_cp_ring_for_rx(struct bnge_rx_ring_info *rxr); u16 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr); void bnge_fill_hw_rss_tbl(struct bnge_net *bn, struct bnge_vnic_info *vnic= ); +int bnge_alloc_rx_data(struct bnge_net *bn, struct bnge_rx_ring_info *rxr, + u16 prod, gfp_t gfp); #endif /* _BNGE_NETDEV_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c new file mode 100644 index 00000000000..f4168729c7d --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -0,0 +1,579 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2025 Broadcom. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bnge.h" +#include "bnge_hwrm.h" +#include "bnge_hwrm_lib.h" +#include "bnge_netdev.h" +#include "bnge_rmem.h" +#include "bnge_txrx.h" + +irqreturn_t bnge_msix(int irq, void *dev_instance) +{ + struct bnge_napi *bnapi =3D dev_instance; + struct bnge_nq_ring_info *nqr; + struct bnge_net *bn; + u32 cons; + + bn =3D bnapi->bn; + nqr =3D &bnapi->nq_ring; + cons =3D RING_CMP(bn, nqr->nq_raw_cons); + + prefetch(&nqr->desc_ring[CP_RING(cons)][CP_IDX(cons)]); + napi_schedule(&bnapi->napi); + return IRQ_HANDLED; +} + +static void bnge_sched_reset_rxr(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr) +{ + rxr->rx_next_cons =3D 0xffff; +} + +void bnge_reuse_rx_data(struct bnge_rx_ring_info *rxr, u16 cons, void *dat= a) +{ + struct bnge_sw_rx_bd *cons_rx_buf, *prod_rx_buf; + struct bnge_net *bn =3D rxr->bnapi->bn; + struct rx_bd *cons_bd, *prod_bd; + u16 prod =3D rxr->rx_prod; + + prod_rx_buf =3D &rxr->rx_buf_ring[RING_RX(bn, prod)]; + cons_rx_buf =3D &rxr->rx_buf_ring[cons]; + + prod_rx_buf->data =3D data; + prod_rx_buf->data_ptr =3D cons_rx_buf->data_ptr; + + prod_rx_buf->mapping =3D cons_rx_buf->mapping; + + prod_bd =3D &rxr->rx_desc_ring[RX_RING(bn, prod)][RX_IDX(prod)]; + cons_bd =3D &rxr->rx_desc_ring[RX_RING(bn, cons)][RX_IDX(cons)]; + + prod_bd->rx_bd_haddr =3D cons_bd->rx_bd_haddr; +} + +static void bnge_deliver_skb(struct bnge_net *bn, struct bnge_napi *bnapi, + struct sk_buff *skb) +{ + skb_mark_for_recycle(skb); + skb_record_rx_queue(skb, bnapi->index); + napi_gro_receive(&bnapi->napi, skb); +} + +static struct sk_buff *bnge_copy_skb(struct bnge_napi *bnapi, u8 *data, + unsigned int len, dma_addr_t mapping) +{ + struct bnge_net *bn =3D bnapi->bn; + struct bnge_dev *bd =3D bn->bd; + struct sk_buff *skb; + + skb =3D napi_alloc_skb(&bnapi->napi, len); + if (!skb) + return NULL; + + dma_sync_single_for_cpu(bd->dev, mapping, bn->rx_copybreak, + bn->rx_dir); + + memcpy(skb->data - NET_IP_ALIGN, data - NET_IP_ALIGN, + len + NET_IP_ALIGN); + + dma_sync_single_for_device(bd->dev, mapping, bn->rx_copybreak, + bn->rx_dir); + + skb_put(skb, len); + + return skb; +} + +static enum pkt_hash_types bnge_rss_ext_op(struct bnge_net *bn, + struct rx_cmp *rxcmp) +{ + u8 ext_op =3D RX_CMP_V3_HASH_TYPE(bn->bd, rxcmp); + + switch (ext_op) { + case EXT_OP_INNER_4: + case EXT_OP_OUTER_4: + case EXT_OP_INNFL_3: + case EXT_OP_OUTFL_3: + return PKT_HASH_TYPE_L4; + default: + return PKT_HASH_TYPE_L3; + } +} + +static struct sk_buff *bnge_rx_vlan(struct sk_buff *skb, u8 cmp_type, + struct rx_cmp *rxcmp, + struct rx_cmp_ext *rxcmp1) +{ + __be16 vlan_proto; + u16 vtag; + + if (cmp_type =3D=3D CMP_TYPE_RX_L2_CMP) { + __le32 flags2 =3D rxcmp1->rx_cmp_flags2; + u32 meta_data; + + if (!(flags2 & cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN))) + return skb; + + meta_data =3D le32_to_cpu(rxcmp1->rx_cmp_meta_data); + vtag =3D meta_data & RX_CMP_FLAGS2_METADATA_TCI_MASK; + vlan_proto =3D + htons(meta_data >> RX_CMP_FLAGS2_METADATA_TPID_SFT); + if (eth_type_vlan(vlan_proto)) + __vlan_hwaccel_put_tag(skb, vlan_proto, vtag); + else + goto vlan_err; + } else if (cmp_type =3D=3D CMP_TYPE_RX_L2_V3_CMP) { + if (RX_CMP_VLAN_VALID(rxcmp)) { + u32 tpid_sel =3D RX_CMP_VLAN_TPID_SEL(rxcmp); + + if (tpid_sel =3D=3D RX_CMP_METADATA1_TPID_8021Q) + vlan_proto =3D htons(ETH_P_8021Q); + else if (tpid_sel =3D=3D RX_CMP_METADATA1_TPID_8021AD) + vlan_proto =3D htons(ETH_P_8021AD); + else + goto vlan_err; + vtag =3D RX_CMP_METADATA0_TCI(rxcmp1); + __vlan_hwaccel_put_tag(skb, vlan_proto, vtag); + } + } + return skb; + +vlan_err: + skb_mark_for_recycle(skb); + dev_kfree_skb(skb); + return NULL; +} + +static struct sk_buff *bnge_rx_skb(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr, u16 cons, + void *data, u8 *data_ptr, + dma_addr_t dma_addr, + unsigned int offset_and_len) +{ + struct bnge_dev *bd =3D bn->bd; + u16 prod =3D rxr->rx_prod; + struct sk_buff *skb; + int err; + + err =3D bnge_alloc_rx_data(bn, rxr, prod, GFP_ATOMIC); + if (unlikely(err)) { + bnge_reuse_rx_data(rxr, cons, data); + return NULL; + } + + skb =3D napi_build_skb(data, bn->rx_buf_size); + dma_sync_single_for_cpu(bd->dev, dma_addr, bn->rx_buf_use_size, + bn->rx_dir); + if (!skb) { + page_pool_free_va(rxr->head_pool, data, true); + return NULL; + } + + skb_mark_for_recycle(skb); + skb_reserve(skb, bn->rx_offset); + skb_put(skb, offset_and_len & 0xffff); + return skb; +} + +/* returns the following: + * 1 - 1 packet successfully received + * -EBUSY - completion ring does not have all the agg buffers yet + * -ENOMEM - packet aborted due to out of memory + * -EIO - packet aborted due to hw error indicated in BD + */ +static int bnge_rx_pkt(struct bnge_net *bn, struct bnge_cp_ring_info *cpr, + u32 *raw_cons, u8 *event) +{ + struct bnge_napi *bnapi =3D cpr->bnapi; + struct bnge_rx_ring_info *rxr; + u32 tmp_raw_cons, flags, misc; + struct bnge_sw_rx_bd *rx_buf; + struct rx_cmp_ext *rxcmp1; + u16 cons, prod, cp_cons; + u8 *data_ptr, cmp_type; + struct net_device *dev; + struct rx_cmp *rxcmp; + dma_addr_t dma_addr; + struct sk_buff *skb; + unsigned int len; + void *data; + int rc =3D 0; + + dev =3D bn->netdev; + rxr =3D bnapi->rx_ring; + + tmp_raw_cons =3D *raw_cons; + cp_cons =3D RING_CMP(bn, tmp_raw_cons); + rxcmp =3D (struct rx_cmp *) + &cpr->desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + + cmp_type =3D RX_CMP_TYPE(rxcmp); + + tmp_raw_cons =3D NEXT_RAW_CMP(tmp_raw_cons); + cp_cons =3D RING_CMP(bn, tmp_raw_cons); + rxcmp1 =3D (struct rx_cmp_ext *) + &cpr->desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + + if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons)) + return -EBUSY; + + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + prod =3D rxr->rx_prod; + + cons =3D rxcmp->rx_cmp_opaque; + if (unlikely(cons !=3D rxr->rx_next_cons)) { + /* 0xffff is forced error, don't print it */ + if (rxr->rx_next_cons !=3D 0xffff) + netdev_warn(bn->netdev, "RX cons %x !=3D expected cons %x\n", + cons, rxr->rx_next_cons); + bnge_sched_reset_rxr(bn, rxr); + goto next_rx_no_prod_no_len; + } + rx_buf =3D &rxr->rx_buf_ring[cons]; + data =3D rx_buf->data; + data_ptr =3D rx_buf->data_ptr; + prefetch(data_ptr); + + misc =3D le32_to_cpu(rxcmp->rx_cmp_misc_v1); + *event |=3D BNGE_RX_EVENT; + + rx_buf->data =3D NULL; + if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L2_ERRORS) { + bnge_reuse_rx_data(rxr, cons, data); + rc =3D -EIO; + goto next_rx_no_len; + } + + flags =3D le32_to_cpu(rxcmp->rx_cmp_len_flags_type); + len =3D flags >> RX_CMP_LEN_SHIFT; + dma_addr =3D rx_buf->mapping; + + if (len <=3D bn->rx_copybreak) { + skb =3D bnge_copy_skb(bnapi, data_ptr, len, dma_addr); + bnge_reuse_rx_data(rxr, cons, data); + if (!skb) + goto oom_next_rx; + } else { + u32 payload; + + if (rx_buf->data_ptr =3D=3D data_ptr) + payload =3D misc & RX_CMP_PAYLOAD_OFFSET; + else + payload =3D 0; + skb =3D bnge_rx_skb(bn, rxr, cons, data, data_ptr, dma_addr, + payload | len); + if (!skb) + goto oom_next_rx; + } + + if (RX_CMP_HASH_VALID(rxcmp)) { + enum pkt_hash_types type; + + if (cmp_type =3D=3D CMP_TYPE_RX_L2_V3_CMP) { + type =3D bnge_rss_ext_op(bn, rxcmp); + } else { +#define RX_CMP_ITYPES(rxcmp) \ + (le32_to_cpu((rxcmp)->rx_cmp_len_flags_type) & RX_CMP_FLAGS_ITYPES_MASK) + + u32 itypes =3D RX_CMP_ITYPES(rxcmp); + + if (itypes =3D=3D RX_CMP_FLAGS_ITYPE_TCP || + itypes =3D=3D RX_CMP_FLAGS_ITYPE_UDP) + type =3D PKT_HASH_TYPE_L4; + else + type =3D PKT_HASH_TYPE_L3; + } + skb_set_hash(skb, le32_to_cpu(rxcmp->rx_cmp_rss_hash), type); + } + +#define RX_CMP_CFA_CODE(rxcmpl1) \ + ((le32_to_cpu((rxcmpl1)->rx_cmp_cfa_code_errors_v2) & \ + RX_CMPL_CFA_CODE_MASK) >> RX_CMPL_CFA_CODE_SFT) + + skb->protocol =3D eth_type_trans(skb, dev); + + if (skb->dev->features & BNGE_HW_FEATURE_VLAN_ALL_RX) { + skb =3D bnge_rx_vlan(skb, cmp_type, rxcmp, rxcmp1); + if (!skb) + goto next_rx; + } + + skb_checksum_none_assert(skb); + if (RX_CMP_L4_CS_OK(rxcmp1)) { + if (dev->features & NETIF_F_RXCSUM) { + skb->ip_summed =3D CHECKSUM_UNNECESSARY; + skb->csum_level =3D RX_CMP_ENCAP(rxcmp1); + } + } + + bnge_deliver_skb(bn, bnapi, skb); + rc =3D 1; + +next_rx: + /* Update Stats */ +next_rx_no_len: + rxr->rx_prod =3D NEXT_RX(prod); + rxr->rx_next_cons =3D RING_RX(bn, NEXT_RX(cons)); + +next_rx_no_prod_no_len: + *raw_cons =3D tmp_raw_cons; + return rc; + +oom_next_rx: + rc =3D -ENOMEM; + goto next_rx; +} + +/* In netpoll mode, if we are using a combined completion ring, we need to + * discard the rx packets and recycle the buffers. + */ +static int bnge_force_rx_discard(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + u32 *raw_cons, u8 *event) +{ + u32 tmp_raw_cons =3D *raw_cons; + struct rx_cmp_ext *rxcmp1; + struct rx_cmp *rxcmp; + u16 cp_cons; + u8 cmp_type; + int rc; + + cp_cons =3D RING_CMP(bn, tmp_raw_cons); + rxcmp =3D (struct rx_cmp *) + &cpr->desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + + tmp_raw_cons =3D NEXT_RAW_CMP(tmp_raw_cons); + cp_cons =3D RING_CMP(bn, tmp_raw_cons); + rxcmp1 =3D (struct rx_cmp_ext *) + &cpr->desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + + if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons)) + return -EBUSY; + + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + cmp_type =3D RX_CMP_TYPE(rxcmp); + if (cmp_type =3D=3D CMP_TYPE_RX_L2_CMP || + cmp_type =3D=3D CMP_TYPE_RX_L2_V3_CMP) { + rxcmp1->rx_cmp_cfa_code_errors_v2 |=3D + cpu_to_le32(RX_CMPL_ERRORS_CRC_ERROR); + } + rc =3D bnge_rx_pkt(bn, cpr, raw_cons, event); + return rc; +} + +static void __bnge_poll_work_done(struct bnge_net *bn, struct bnge_napi *b= napi, + int budget) +{ + if ((bnapi->events & BNGE_RX_EVENT)) { + struct bnge_rx_ring_info *rxr =3D bnapi->rx_ring; + + bnge_db_write(bn->bd, &rxr->rx_db, rxr->rx_prod); + bnapi->events &=3D ~BNGE_RX_EVENT; + } +} + +static int __bnge_poll_work(struct bnge_net *bn, struct bnge_cp_ring_info = *cpr, + int budget) +{ + struct bnge_napi *bnapi =3D cpr->bnapi; + u32 raw_cons =3D cpr->cp_raw_cons; + struct tx_cmp *txcmp; + int rx_pkts =3D 0; + u8 event =3D 0; + u32 cons; + + cpr->has_more_work =3D 0; + cpr->had_work_done =3D 1; + while (1) { + u8 cmp_type; + int rc; + + cons =3D RING_CMP(bn, raw_cons); + txcmp =3D &cpr->desc_ring[CP_RING(cons)][CP_IDX(cons)]; + + if (!TX_CMP_VALID(bn, txcmp, raw_cons)) + break; + + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + cmp_type =3D TX_CMP_TYPE(txcmp); + if (cmp_type =3D=3D CMP_TYPE_TX_L2_CMP || + cmp_type =3D=3D CMP_TYPE_TX_L2_COAL_CMP) { + /* + * Tx Compl Processng + */ + } else if (cmp_type >=3D CMP_TYPE_RX_L2_CMP && + cmp_type <=3D CMP_TYPE_RX_L2_TPA_START_V3_CMP) { + if (likely(budget)) + rc =3D bnge_rx_pkt(bn, cpr, &raw_cons, &event); + else + rc =3D bnge_force_rx_discard(bn, cpr, &raw_cons, + &event); + if (likely(rc >=3D 0)) + rx_pkts +=3D rc; + /* Increment rx_pkts when rc is -ENOMEM to count towards + * the NAPI budget. Otherwise, we may potentially loop + * here forever if we consistently cannot allocate + * buffers. + */ + else if (rc =3D=3D -ENOMEM && budget) + rx_pkts++; + else if (rc =3D=3D -EBUSY) /* partial completion */ + break; + } + + raw_cons =3D NEXT_RAW_CMP(raw_cons); + + if (rx_pkts && rx_pkts =3D=3D budget) { + cpr->has_more_work =3D 1; + break; + } + } + + cpr->cp_raw_cons =3D raw_cons; + bnapi->events |=3D event; + return rx_pkts; +} + +static void __bnge_poll_cqs_done(struct bnge_net *bn, struct bnge_napi *bn= api, + u64 dbr_type, int budget) +{ + struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; + int i; + + for (i =3D 0; i < nqr->cp_ring_count; i++) { + struct bnge_cp_ring_info *cpr =3D &nqr->cp_ring_arr[i]; + struct bnge_db_info *db; + + if (cpr->had_work_done) { + u32 tgl =3D 0; + + if (dbr_type =3D=3D DBR_TYPE_CQ_ARMALL) { + cpr->had_nqe_notify =3D 0; + tgl =3D cpr->toggle; + } + db =3D &cpr->cp_db; + bnge_writeq(bn->bd, + db->db_key64 | dbr_type | DB_TOGGLE(tgl) | + DB_RING_IDX(db, cpr->cp_raw_cons), + db->doorbell); + cpr->had_work_done =3D 0; + } + } + __bnge_poll_work_done(bn, bnapi, budget); +} + +static int __bnge_poll_cqs(struct bnge_net *bn, struct bnge_napi *bnapi, + int budget) +{ + struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; + int i, work_done =3D 0; + + for (i =3D 0; i < nqr->cp_ring_count; i++) { + struct bnge_cp_ring_info *cpr =3D &nqr->cp_ring_arr[i]; + + if (cpr->had_nqe_notify) { + work_done +=3D __bnge_poll_work(bn, cpr, + budget - work_done); + nqr->has_more_work |=3D cpr->has_more_work; + } + } + return work_done; +} + +int bnge_napi_poll(struct napi_struct *napi, int budget) +{ + struct bnge_napi *bnapi =3D container_of(napi, struct bnge_napi, napi); + struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; + u32 raw_cons =3D nqr->nq_raw_cons; + struct bnge_net *bn =3D bnapi->bn; + struct bnge_dev *bd =3D bn->bd; + struct nqe_cn *nqcmp; + int work_done =3D 0; + u32 cons; + + if (nqr->has_more_work) { + nqr->has_more_work =3D 0; + work_done =3D __bnge_poll_cqs(bn, bnapi, budget); + } + + while (1) { + u16 type; + + cons =3D RING_CMP(bn, raw_cons); + nqcmp =3D &nqr->desc_ring[CP_RING(cons)][CP_IDX(cons)]; + + if (!NQ_CMP_VALID(bn, nqcmp, raw_cons)) { + if (nqr->has_more_work) + break; + + __bnge_poll_cqs_done(bn, bnapi, DBR_TYPE_CQ_ARMALL, + budget); + nqr->nq_raw_cons =3D raw_cons; + if (napi_complete_done(napi, work_done)) + BNGE_DB_NQ_ARM(bd, &nqr->nq_db, nqr->nq_raw_cons); + goto poll_done; + } + + /* The valid test of the entry must be done first before + * reading any further. + */ + dma_rmb(); + + type =3D le16_to_cpu(nqcmp->type); + if (NQE_CN_TYPE(type) =3D=3D NQ_CN_TYPE_CQ_NOTIFICATION) { + u32 idx =3D le32_to_cpu(nqcmp->cq_handle_low); + u32 cq_type =3D BNGE_NQ_HDL_TYPE(idx); + struct bnge_cp_ring_info *cpr; + + /* No more budget for RX work */ + if (budget && work_done >=3D budget && + cq_type =3D=3D BNGE_NQ_HDL_TYPE_RX) + break; + + idx =3D BNGE_NQ_HDL_IDX(idx); + cpr =3D &nqr->cp_ring_arr[idx]; + cpr->had_nqe_notify =3D 1; + cpr->toggle =3D NQE_CN_TOGGLE(type); + work_done +=3D __bnge_poll_work(bn, cpr, + budget - work_done); + nqr->has_more_work |=3D cpr->has_more_work; + } + raw_cons =3D NEXT_RAW_CMP(raw_cons); + } + + __bnge_poll_cqs_done(bn, bnapi, DBR_TYPE_CQ, budget); + if (raw_cons !=3D nqr->nq_raw_cons) { + nqr->nq_raw_cons =3D raw_cons; + BNGE_DB_NQ(bd, &nqr->nq_db, raw_cons); + } +poll_done: + return work_done; +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.h new file mode 100644 index 00000000000..9cd6c7ae65e --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2025 Broadcom */ + +#ifndef _BNGE_TXRX_H_ +#define _BNGE_TXRX_H_ + +#include +#include "bnge_netdev.h" + +#define BNGE_MIN_PKT_SIZE 52 + +#define TX_OPAQUE_IDX_MASK 0x0000ffff +#define TX_OPAQUE_BDS_MASK 0x00ff0000 +#define TX_OPAQUE_BDS_SHIFT 16 +#define TX_OPAQUE_RING_MASK 0xff000000 +#define TX_OPAQUE_RING_SHIFT 24 + +#define SET_TX_OPAQUE(bn, txr, idx, bds) \ + (((txr)->tx_napi_idx << TX_OPAQUE_RING_SHIFT) | \ + ((bds) << TX_OPAQUE_BDS_SHIFT) | ((idx) & (bn)->tx_ring_mask)) + +#define TX_OPAQUE_IDX(opq) ((opq) & TX_OPAQUE_IDX_MASK) +#define TX_OPAQUE_RING(opq) (((opq) & TX_OPAQUE_RING_MASK) >> \ + TX_OPAQUE_RING_SHIFT) +#define TX_OPAQUE_BDS(opq) (((opq) & TX_OPAQUE_BDS_MASK) >> \ + TX_OPAQUE_BDS_SHIFT) +#define TX_OPAQUE_PROD(bn, opq) ((TX_OPAQUE_IDX(opq) + TX_OPAQUE_BDS(opq))= &\ + (bn)->tx_ring_mask) + +/* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1. We need one ext= ra + * BD because the first TX BD is always a long BD. + */ +#define BNGE_MIN_TX_DESC_CNT (MAX_SKB_FRAGS + 2) + +#define RX_RING(bn, x) (((x) & (bn)->rx_ring_mask) >> (BNGE_PAGE_SHIFT - 4= )) +#define RX_AGG_RING(bn, x) (((x) & (bn)->rx_agg_ring_mask) >> \ + (BNGE_PAGE_SHIFT - 4)) +#define RX_IDX(x) ((x) & (RX_DESC_CNT - 1)) + +#define TX_RING(bn, x) (((x) & (bn)->tx_ring_mask) >> (BNGE_PAGE_SHIFT - 4= )) +#define TX_IDX(x) ((x) & (TX_DESC_CNT - 1)) + +#define CP_RING(x) (((x) & ~(CP_DESC_CNT - 1)) >> (BNGE_PAGE_SHIFT - 4)) +#define CP_IDX(x) ((x) & (CP_DESC_CNT - 1)) + +#define TX_CMP_VALID(bn, txcmp, raw_cons) \ + (!!((txcmp)->tx_cmp_errors_v & cpu_to_le32(TX_CMP_V)) =3D=3D \ + !((raw_cons) & (bn)->cp_bit)) + +#define RX_CMP_VALID(rxcmp1, raw_cons) \ + (!!((rxcmp1)->rx_cmp_cfa_code_errors_v2 & cpu_to_le32(RX_CMP_V)) =3D=3D\ + !((raw_cons) & (bn)->cp_bit)) + +#define RX_AGG_CMP_VALID(bn, agg, raw_cons) \ + (!!((agg)->rx_agg_cmp_v & cpu_to_le32(RX_AGG_CMP_V)) =3D=3D \ + !((raw_cons) & (bn)->cp_bit)) + +#define NQ_CMP_VALID(bn, nqcmp, raw_cons) \ + (!!((nqcmp)->v & cpu_to_le32(NQ_CN_V)) =3D=3D !((raw_cons) & (bn)->cp_bit= )) + +#define TX_CMP_TYPE(txcmp) \ + (le32_to_cpu((txcmp)->tx_cmp_flags_type) & CMP_TYPE) + +#define RX_CMP_TYPE(rxcmp) \ + (le32_to_cpu((rxcmp)->rx_cmp_len_flags_type) & RX_CMP_CMP_TYPE) + +#define RING_RX(bn, idx) ((idx) & (bn)->rx_ring_mask) +#define NEXT_RX(idx) ((idx) + 1) + +#define RING_RX_AGG(bn, idx) ((idx) & (bn)->rx_agg_ring_mask) +#define NEXT_RX_AGG(idx) ((idx) + 1) + +#define RING_TX(bn, idx) ((idx) & (bn)->tx_ring_mask) +#define NEXT_TX(idx) ((idx) + 1) + +#define ADV_RAW_CMP(idx, n) ((idx) + (n)) +#define NEXT_RAW_CMP(idx) ADV_RAW_CMP(idx, 1) +#define RING_CMP(bn, idx) ((idx) & (bn)->cp_ring_mask) + +irqreturn_t bnge_msix(int irq, void *dev_instance); +void bnge_reuse_rx_data(struct bnge_rx_ring_info *rxr, u16 cons, void *dat= a); +int bnge_napi_poll(struct napi_struct *napi, int budget); +#endif /* _BNGE_TXRX_H_ */ --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-qv1-f98.google.com (mail-qv1-f98.google.com [209.85.219.98]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3318E340A5A for ; Wed, 26 Nov 2025 19:50:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.98 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186624; cv=none; b=P+8pqmkCJ+TM0DcDAlK1yXGcZ5QWP5+zop+nDjKbdJ1ws84D4IlDyPuw8whx0Tek47TUHA/FNPy36KY2WXna+UlMIfUObsBxXvXXr+qHd0RyCkoxB+cjNsEFDOA55nYz8/mzCERXOMAIY0xGi/dTvyTh8B7D5Jws/9wKacXnHPs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186624; c=relaxed/simple; bh=fjEmRoB9hUx/yTwurdRWTC5wYfnnnQ1F55aOcDeaZLA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=l+Sy+8nkThmgdkody4GryoldAIhm4sBDiGe8e+U+2QhYSIEp+uVsP1A5MCUrhasnUvmxGvhNpmjnnevOM9QVMtcnjMa3nlg02w5b6/ytapaPj/nZoX5GpKTlrv/lu6vPAD+g9zq9imF5bDytoj75ajOVvpakMi9dJfm44V2jg/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=QxLyMBqy; arc=none smtp.client-ip=209.85.219.98 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="QxLyMBqy" Received: by mail-qv1-f98.google.com with SMTP id 6a1803df08f44-882451b353fso776196d6.1 for ; Wed, 26 Nov 2025 11:50:21 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186621; x=1764791421; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=j/O6TymoVT0YLWv0CCYV9EkHA+o+pWNxKmyURfVFr0c=; b=AeWqnovYDkVceZGnzRAYo2fxbC1BObWm+ncZb+KTYDYQXbzu3KCUtoMZGrXw7MGoOo H1citNhKsm0QNRG6lFy1JetM2Buh2BLQcLCrkjvOi8OXKbr4Z0q2CSpbbVRojqrxKqYR dNBleKchUc/OUm0zccHFKNdn14YeZ+xWtx576Rt4NQ6WoEVkUHmwtjKKDYNYaWky2uSK 9cIVf1HkykOHWGoV0sfPPoPBZcDLI31YWdEPLJ7ZmjRIbLw6stNmuB5Hj52Q2Qj08SMi oqg3dZU8XXf8xPtmA79Swwj1Qd1kYOizW4ihPbxIcQulF59cVYWhWK3BHCh4M7uKXAHA gFew== X-Forwarded-Encrypted: i=1; AJvYcCWFH3UE+rATngEI3KxGkB3YHptixOmJWWwobJ3gFJbqtkcJAD72ixW3Q18MzFOoosw89Kti5vj4Z9U3QnQ=@vger.kernel.org X-Gm-Message-State: AOJu0YyW1opapB/TjWpZ2R517pBkXNec+NFqCedT0SXyIgZy+6xXB8JE kKPJxGUL3UPDIgDyoisPDi1MKkbAANi4Mr218I2IBWBZaboQlRVv5msfEjiTgzE4xfLoqw/PWYc 5gBmYWdCOw0EjeajVrKGHHzAfDBeDZcrbuUBL0dbVZPRUPDWpLlJ6QDwX2YT18w75JrjoVAuhLp heIh3xMaZaYiusr//rA7mW2Q4cdQ91/edp/kBvkoYNigzculT+WW8ze3iODrvOjDrbCOIZWbsS6 3CRpO+fRYnPCykKQWXNOB39Di4L X-Gm-Gg: ASbGnctVA9iUKdImncxoLEXHgCRDypjeDOmQ0ief9MbFv0rxU6UANmy1y9/Jlp3fNec yD+3KOmVZUIFjdz154GmOqZUZquuRCQbYpfgoPXCj0dfv+9xO9ri4MVQARwCu4hg+N7INn0aAWd LEuT0/7hCZiPhDbyhiRJw8dZZ0P9b4fK/48RF9G5vKOxuVY0SL8yFlZgpgLlJZMQRhiSHi5ygG9 NI6Tlc+U7hZ0/+1CEPUoQKira0Xn31iXadM49mBN4n/dOqmLXSDKuKQepArqfYUX0/nl78xDYnI cIm0aDWuwPW5vG64WkigmBXTDAd3ONFdjGeGqxhOgys/sxcpAIeGGbmRQa+tH/lHsD4mL6g40cJ T3S/rU8sxBiRv8LZPrnSnX/aC3rGj7Y2XG+lFiQaPNdLfUtki1G6kT6a1eRjIlTZfHPyjiJV+H6 ZHRr9aPV+GWNonbb2atYT5AANfkbmthfwSXKI5kvCdqLHsNviZQIE= X-Google-Smtp-Source: AGHT+IHic71/FFzKYEZVJElfwk6p2cQ2hiPr1C8RbXw+pFASoeCgvhqo2PHadQYlmQLR+WKAkd+SZ8eoN1JL X-Received: by 2002:a05:6214:240a:b0:880:4b29:d96f with SMTP id 6a1803df08f44-8863af9e2femr125051506d6.39.1764186620974; Wed, 26 Nov 2025 11:50:20 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-11.dlp.protect.broadcom.com. [144.49.247.11]) by smtp-relay.gmail.com with ESMTPS id 6a1803df08f44-8846e457e7csm23358586d6.7.2025.11.26.11.50.20 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:20 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-297e66542afso3559725ad.3 for ; Wed, 26 Nov 2025 11:50:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186620; x=1764791420; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=j/O6TymoVT0YLWv0CCYV9EkHA+o+pWNxKmyURfVFr0c=; b=QxLyMBqyHYHo6fnFL8Re4JuZPo+G+i4mbooIMTp2xD2S4CRQTW2RR6kJO0vQTGbISM mDfybrlZdzjsvnNgMhHukfsxArc1j1pCaNji7za5tgvUOdncqtpCihYY+RfmrH7bNlDq JWMcHpRa4xXOsrzUiNIdQr72yx0yEZHFhxORU= X-Forwarded-Encrypted: i=1; AJvYcCXJwJY/akCj6KMoY6NTDIjnx54vCcUmCElY+zlpY906k4nB0m01hPA3Wo16/JzPXR/HyEOB2jsOzjVFVaM=@vger.kernel.org X-Received: by 2002:a17:903:2f07:b0:298:2cdf:56c8 with SMTP id d9443c01a7336-29bab300f4dmr79404275ad.60.1764186619736; Wed, 26 Nov 2025 11:50:19 -0800 (PST) X-Received: by 2002:a17:903:2f07:b0:298:2cdf:56c8 with SMTP id d9443c01a7336-29bab300f4dmr79404015ad.60.1764186619349; Wed, 26 Nov 2025 11:50:19 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:18 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 04/12] bng_en: Handle an HWRM completion request Date: Thu, 27 Nov 2025 01:19:23 +0530 Message-ID: <20251126194931.455830-5-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Since the HWRM completion for a sent request lands on the NQ, add functions to handle the HWRM completion event. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 4 +- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 1 + .../net/ethernet/broadcom/bnge/bnge_txrx.c | 44 ++++++++++++++++++- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index c43b729e23c..bb9223a00b5 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -18,6 +18,7 @@ #include =20 #include "bnge.h" +#include "bnge_hwrm.h" #include "bnge_hwrm_lib.h" #include "bnge_ethtool.h" #include "bnge_rmem.h" @@ -2315,8 +2316,7 @@ static int bnge_open(struct net_device *dev) =20 static int bnge_shutdown_nic(struct bnge_net *bn) { - /* TODO: close_path =3D 0 until we make NAPI functional */ - bnge_hwrm_resource_free(bn, 0); + bnge_hwrm_resource_free(bn, 1); return 0; } =20 diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 41af5827a25..3c8fffb5e2d 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -78,6 +78,7 @@ struct tx_cmp { #define CMPL_BASE_TYPE_HWRM_FWD_REQ 0x22UL #define CMPL_BASE_TYPE_HWRM_FWD_RESP 0x24UL #define CMPL_BASE_TYPE_HWRM_ASYNC_EVENT 0x2eUL + #define CMPL_BA_TY_HWRM_ASY_EVT CMPL_BASE_TYPE_HWRM_ASYNC_EVENT #define TX_CMP_FLAGS_ERROR (1 << 6) #define TX_CMP_FLAGS_PUSH (1 << 7) u32 tx_cmp_opaque; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index f4168729c7d..c8e9b96aa1c 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -397,6 +397,43 @@ static void __bnge_poll_work_done(struct bnge_net *bn,= struct bnge_napi *bnapi, } } =20 +static void +bnge_hwrm_update_token(struct bnge_dev *bd, u16 seq_id, + enum bnge_hwrm_wait_state state) +{ + struct bnge_hwrm_wait_token *token; + + rcu_read_lock(); + hlist_for_each_entry_rcu(token, &bd->hwrm_pending_list, node) { + if (token->seq_id =3D=3D seq_id) { + WRITE_ONCE(token->state, state); + rcu_read_unlock(); + return; + } + } + rcu_read_unlock(); + dev_err(bd->dev, "Invalid hwrm seq id %d\n", seq_id); +} + +static int bnge_hwrm_handler(struct bnge_dev *bd, struct tx_cmp *txcmp) +{ + struct hwrm_cmpl *h_cmpl =3D (struct hwrm_cmpl *)txcmp; + u16 cmpl_type =3D TX_CMP_TYPE(txcmp), seq_id; + + switch (cmpl_type) { + case CMPL_BASE_TYPE_HWRM_DONE: + seq_id =3D le16_to_cpu(h_cmpl->sequence_id); + bnge_hwrm_update_token(bd, seq_id, BNGE_HWRM_COMPLETE); + break; + + case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT: + default: + break; + } + + return 0; +} + static int __bnge_poll_work(struct bnge_net *bn, struct bnge_cp_ring_info = *cpr, int budget) { @@ -447,8 +484,11 @@ static int __bnge_poll_work(struct bnge_net *bn, struc= t bnge_cp_ring_info *cpr, rx_pkts++; else if (rc =3D=3D -EBUSY) /* partial completion */ break; + } else if (unlikely(cmp_type =3D=3D CMPL_BASE_TYPE_HWRM_DONE || + cmp_type =3D=3D CMPL_BASE_TYPE_HWRM_FWD_REQ || + cmp_type =3D=3D CMPL_BA_TY_HWRM_ASY_EVT)) { + bnge_hwrm_handler(bn->bd, txcmp); } - raw_cons =3D NEXT_RAW_CMP(raw_cons); =20 if (rx_pkts && rx_pkts =3D=3D budget) { @@ -565,6 +605,8 @@ int bnge_napi_poll(struct napi_struct *napi, int budget) work_done +=3D __bnge_poll_work(bn, cpr, budget - work_done); nqr->has_more_work |=3D cpr->has_more_work; + } else { + bnge_hwrm_handler(bn->bd, (struct tx_cmp *)nqcmp); } raw_cons =3D NEXT_RAW_CMP(raw_cons); } --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-io1-f97.google.com (mail-io1-f97.google.com [209.85.166.97]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 12781343201 for ; Wed, 26 Nov 2025 19:50:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.97 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186629; cv=none; b=CUStsFTgtXsPZwSnD+7GXhZvYqv9LSA/y4pryOslSIDlqfrca4f6oLS++Hpp65Be1H46FdIrI0I6dmpsQv+lLw2OwMoJFIzieyNf9hYsbCDadJcKgge4Gqln1gAmg9TfVW9peO2pOsvLW8QAOM3ivQqYlQmW+Em9FWrb/X4+ZsY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186629; c=relaxed/simple; bh=YPSL1mgcj6xzfmC4ZziAgv4PZhMPkiaGbY/3iHvop+Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=W9yN3Lou7HMtdDgs1IhR3GgNappHr0/yKU7VkHB0KVE+RklehjP73tNYzhg5WBuaHkMg8MHoLZeSOgh+yrgX5IcSgnxrZHztNJfE7Slimy8yGdDuBnUM7TBGxNqw3k03BgxTsTP0WfHmB2SanBP3AdqQ0JRJ4ycaVUg/4fRz0Nw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=eIg/ayiq; arc=none smtp.client-ip=209.85.166.97 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="eIg/ayiq" Received: by mail-io1-f97.google.com with SMTP id ca18e2360f4ac-94900d3ef9bso5863139f.1 for ; Wed, 26 Nov 2025 11:50:26 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186626; x=1764791426; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=f7fp5me0oZSx3ZLWm9dZJtiRJ0vWaTMFJ3W4w7RFxlk=; b=UZ47JelGEfmgej9OBIh1D/xbGFuGoR24HSh+jJStMP18fIH5jxZHh9GvYlZrSU6Xvw mA5lFtSRZuXLbk3DRAmMJJpjVPSLraFxOdkQ6yhbCYmH/EnnYZnjwQ99zrQUxt17xf4Z wtlGU7YITwWZPSENTPFIfibUdcxsjwDW+QQGpU1uyMsmVy50WZHU3pCgrThBOJ+FE4ux OP0MdZqgjZ2JsS8omPhMG/N0Ak+XitUoSPeZKvRmYz2hDEQSaMvxhTULnnNVjfhykyRN GVg3hZKdvnxiI9E3PZL6ZQWKAa5TKQu8R+kHH79R+JuSl4O71f4jD2yagGvEFmDZtqM3 eEYw== X-Forwarded-Encrypted: i=1; AJvYcCWU5zUCBP0hzwbwW1VUUSVieaVXhvApN3XjCGJh6Me5WBEmSk/b02XXcmAzqHQsnIBm7+T2TMt3MK9xS6s=@vger.kernel.org X-Gm-Message-State: AOJu0Yyk90Fuh4FBKZXXA6p6Y9BtYGyn7tV+GnNnCZRdmwYF5ScHcFRv I/fUF+9dJAUoJkRRIbdZrGOfmaXnbV8P/aZQ97pHPnRQJA8PTcW636d7ZJVr3p1olm+8F/6k9K5 NoN8gdi3DSu+PXeW798nvUU8a13u15LeKmBL2bzK8YzvGw41KSeExUrnL2neoFAvTuCIL9HBnvh RuyB7e8GQH1R+ow4Eygkiz83y7w87yIDs2qCHkT5m578KzRL7pJdEiCYyykxkegIUvy3InwNbL0 BvzK92AY7F0iIoshJ4pxPpEHvCJ X-Gm-Gg: ASbGncuxewK3JuaxgjzPxQuQjAoGqeFZimhMtT7x4/niRInaXipRsmjhkSGXmI9Gavl hT8RwrtVHYhdqoIxh+HkpvzhyEfcYPPzuwm75w2+G8CULaVaQfbl3Oz3i8iIovNubXFDdfah7KB bgeg90mI+PuE1JaNBxTBWAKiVBUpAVZJzSd5KMVZs9jlskJUzPwpu211BNUVuBQ41n0O/smywN7 Zw5JoNjph11E/Jzs2RnxQBG2Q6GN+dj/HmjVjqyClJJxIAA51/wmScgJLVE/YKy13vTJjK3qKtf 56zjjSWB4dapLI9Fl3FD5cu0tEB0cZczUfIFqT0dUUztU5mEk9OJnAll9xxgBX+msuDe/+D+ds/ WW3OSxpQyUjGHR4xXuMQz3+MrpNQDhybnN0Yssud13vfL0nXVn+5hMKcx0Cd/bKPZA2wiMo0nUv RjWmSn3hdlv1dSLgvqSJ+efOnJIqRVToRhrZ0ZzI7395qNlmput8E= X-Google-Smtp-Source: AGHT+IH3G5KHXtqcqkGbl5MdI/DH+yN/iES1fVMofaMZUgcWS470eOFMdmFYCDvbN2XVfxfoppfqledBtpIT X-Received: by 2002:a05:6638:a48e:b0:5ad:5b64:ce47 with SMTP id 8926c6da1cb9f-5b967a1b905mr14430227173.9.1764186626167; Wed, 26 Nov 2025 11:50:26 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-11.dlp.protect.broadcom.com. [144.49.247.11]) by smtp-relay.gmail.com with ESMTPS id 8926c6da1cb9f-5b954a08435sm1799167173.4.2025.11.26.11.50.25 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:26 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f197.google.com with SMTP id d9443c01a7336-297f3710070so2108625ad.2 for ; Wed, 26 Nov 2025 11:50:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186625; x=1764791425; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=f7fp5me0oZSx3ZLWm9dZJtiRJ0vWaTMFJ3W4w7RFxlk=; b=eIg/ayiqGdTkiHj86lCFohZAi6dFZeDQGI51UALMCOUPwKiDRXVZGlatkukUgBwOeh k2XocsNekBkqDXnpK50pdANnc3Zq6My6ZU6JgAMa694q8wMTo3WK8O4UBlSfNZVP0hr4 534JwqiABgIj9i6xOe44Mveg5ApoboEauOdrc= X-Forwarded-Encrypted: i=1; AJvYcCU4s3tO3h9v3UggONUJPeNPDYkbI4QpCA7oqwQFaeerqgSoX6mZgON7YpPkJKGY7toLoc+o76iGMikYGtM=@vger.kernel.org X-Received: by 2002:a17:902:cf4b:b0:295:7b8c:6611 with SMTP id d9443c01a7336-29b6c404112mr220840955ad.15.1764186624435; Wed, 26 Nov 2025 11:50:24 -0800 (PST) X-Received: by 2002:a17:902:cf4b:b0:295:7b8c:6611 with SMTP id d9443c01a7336-29b6c404112mr220840835ad.15.1764186624018; Wed, 26 Nov 2025 11:50:24 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:23 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 05/12] bng_en: Add TX support Date: Thu, 27 Nov 2025 01:19:24 +0530 Message-ID: <20251126194931.455830-6-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Add functions to support xmit along with TSO/GSO. Also, add functions to handle TX completion events in the NAPI context. This commit introduces the fundamental transmit data path Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 99 ++++- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 2 + .../net/ethernet/broadcom/bnge/bnge_txrx.c | 370 +++++++++++++++++- .../net/ethernet/broadcom/bnge/bnge_txrx.h | 34 ++ 4 files changed, 495 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index bb9223a00b5..1af2c4e29c6 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -394,9 +394,60 @@ static void bnge_free_rx_ring_pair_bufs(struct bnge_ne= t *bn) bnge_free_one_rx_ring_pair_bufs(bn, &bn->rx_ring[i]); } =20 +static void bnge_free_tx_skbs(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + u16 max_idx; + int i; + + max_idx =3D bn->tx_nr_pages * TX_DESC_CNT; + for (i =3D 0; i < bd->tx_nr_rings; i++) { + struct bnge_tx_ring_info *txr =3D &bn->tx_ring[i]; + int j; + + if (!txr->tx_buf_ring) + continue; + + for (j =3D 0; j < max_idx;) { + struct bnge_sw_tx_bd *tx_buf =3D &txr->tx_buf_ring[j]; + struct sk_buff *skb; + int k, last; + + skb =3D tx_buf->skb; + if (!skb) { + j++; + continue; + } + + tx_buf->skb =3D NULL; + + dma_unmap_single(bd->dev, + dma_unmap_addr(tx_buf, mapping), + skb_headlen(skb), + DMA_TO_DEVICE); + + last =3D tx_buf->nr_frags; + j +=3D 2; + for (k =3D 0; k < last; k++, j++) { + int ring_idx =3D j & bn->tx_ring_mask; + skb_frag_t *frag =3D &skb_shinfo(skb)->frags[k]; + + tx_buf =3D &txr->tx_buf_ring[ring_idx]; + dma_unmap_page(bd->dev, + dma_unmap_addr(tx_buf, mapping), + skb_frag_size(frag), + DMA_TO_DEVICE); + } + dev_kfree_skb(skb); + } + netdev_tx_reset_queue(netdev_get_tx_queue(bd->netdev, i)); + } +} + static void bnge_free_all_rings_bufs(struct bnge_net *bn) { bnge_free_rx_ring_pair_bufs(bn); + bnge_free_tx_skbs(bn); } =20 static void bnge_free_rx_rings(struct bnge_net *bn) @@ -2232,6 +2283,44 @@ static int bnge_init_nic(struct bnge_net *bn) return rc; } =20 +static void bnge_tx_disable(struct bnge_net *bn) +{ + struct bnge_tx_ring_info *txr; + int i; + + if (bn->tx_ring) { + for (i =3D 0; i < bn->bd->tx_nr_rings; i++) { + txr =3D &bn->tx_ring[i]; + WRITE_ONCE(txr->dev_state, BNGE_DEV_STATE_CLOSING); + } + } + /* Make sure napi polls see @dev_state change */ + synchronize_net(); + + if (!bn->netdev) + return; + /* Drop carrier first to prevent TX timeout */ + netif_carrier_off(bn->netdev); + /* Stop all TX queues */ + netif_tx_disable(bn->netdev); +} + +static void bnge_tx_enable(struct bnge_net *bn) +{ + struct bnge_tx_ring_info *txr; + int i; + + for (i =3D 0; i < bn->bd->tx_nr_rings; i++) { + txr =3D &bn->tx_ring[i]; + WRITE_ONCE(txr->dev_state, 0); + } + /* Make sure napi polls see @dev_state change */ + synchronize_net(); + netif_tx_wake_all_queues(bn->netdev); + if (BNGE_LINK_IS_UP(bn->bd)) + netif_carrier_on(bn->netdev); +} + static int bnge_open_core(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; @@ -2281,6 +2370,7 @@ static int bnge_open_core(struct bnge_net *bn) set_bit(BNGE_STATE_OPEN, &bd->state); =20 bnge_enable_int(bn); + bnge_tx_enable(bn); /* Poll link status and check for SFP+ module status */ mutex_lock(&bd->link_lock); bnge_get_port_module_status(bn); @@ -2295,13 +2385,6 @@ static int bnge_open_core(struct bnge_net *bn) return rc; } =20 -static netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struct net_device = *dev) -{ - dev_kfree_skb_any(skb); - - return NETDEV_TX_OK; -} - static int bnge_open(struct net_device *dev) { struct bnge_net *bn =3D netdev_priv(dev); @@ -2324,6 +2407,8 @@ static void bnge_close_core(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; =20 + bnge_tx_disable(bn); + clear_bit(BNGE_STATE_OPEN, &bd->state); bnge_shutdown_nic(bn); bnge_disable_napi(bn); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 3c8fffb5e2d..94d03d1e76b 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -246,6 +246,8 @@ struct bnge_net { =20 unsigned long state; #define BNGE_STATE_NAPI_DISABLED 0 + + u32 msg_enable; }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index c8e9b96aa1c..7470a705aae 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -386,9 +386,83 @@ static int bnge_force_rx_discard(struct bnge_net *bn, return rc; } =20 +static bool __bnge_tx_int(struct bnge_net *bn, struct bnge_tx_ring_info *t= xr, + int budget) +{ + u16 hw_cons =3D txr->tx_hw_cons; + struct bnge_dev *bd =3D bn->bd; + unsigned int tx_bytes =3D 0; + unsigned int tx_pkts =3D 0; + struct netdev_queue *txq; + u16 cons =3D txr->tx_cons; + skb_frag_t *frag; + bool rc =3D false; + + txq =3D netdev_get_tx_queue(bn->netdev, txr->txq_index); + + while (RING_TX(bn, cons) !=3D hw_cons) { + struct bnge_sw_tx_bd *tx_buf; + struct sk_buff *skb; + int j, last; + + tx_buf =3D &txr->tx_buf_ring[RING_TX(bn, cons)]; + skb =3D tx_buf->skb; + + cons =3D NEXT_TX(cons); + tx_pkts++; + tx_bytes +=3D skb->len; + tx_buf->skb =3D NULL; + + dma_unmap_single(bd->dev, dma_unmap_addr(tx_buf, mapping), + skb_headlen(skb), DMA_TO_DEVICE); + last =3D tx_buf->nr_frags; + + for (j =3D 0; j < last; j++) { + frag =3D &skb_shinfo(skb)->frags[j]; + cons =3D NEXT_TX(cons); + tx_buf =3D &txr->tx_buf_ring[RING_TX(bn, cons)]; + netmem_dma_unmap_page_attrs(bd->dev, + dma_unmap_addr(tx_buf, + mapping), + skb_frag_size(frag), + DMA_TO_DEVICE, 0); + } + + cons =3D NEXT_TX(cons); + + dev_consume_skb_any(skb); + } + + WRITE_ONCE(txr->tx_cons, cons); + + __netif_txq_completed_wake(txq, tx_pkts, tx_bytes, + bnge_tx_avail(bn, txr), bn->tx_wake_thresh, + (READ_ONCE(txr->dev_state) =3D=3D + BNGE_DEV_STATE_CLOSING)); + + return rc; +} + +static void bnge_tx_int(struct bnge_net *bn, struct bnge_napi *bnapi, + int budget) +{ + struct bnge_tx_ring_info *txr; + bool more =3D false; + int i; + + bnge_for_each_napi_tx(i, bnapi, txr) { + if (txr->tx_hw_cons !=3D RING_TX(bn, txr->tx_cons)) + more |=3D __bnge_tx_int(bn, txr, budget); + } + if (!more) + bnapi->events &=3D ~BNGE_TX_CMP_EVENT; +} + static void __bnge_poll_work_done(struct bnge_net *bn, struct bnge_napi *b= napi, int budget) { + if ((bnapi->events & BNGE_TX_CMP_EVENT)) + bnge_tx_int(bn, bnapi, budget); if ((bnapi->events & BNGE_RX_EVENT)) { struct bnge_rx_ring_info *rxr =3D bnapi->rx_ring; =20 @@ -463,9 +537,26 @@ static int __bnge_poll_work(struct bnge_net *bn, struc= t bnge_cp_ring_info *cpr, cmp_type =3D TX_CMP_TYPE(txcmp); if (cmp_type =3D=3D CMP_TYPE_TX_L2_CMP || cmp_type =3D=3D CMP_TYPE_TX_L2_COAL_CMP) { - /* - * Tx Compl Processng - */ + u32 opaque =3D txcmp->tx_cmp_opaque; + struct bnge_tx_ring_info *txr; + u16 tx_freed; + + txr =3D bnapi->tx_ring[TX_OPAQUE_RING(opaque)]; + event |=3D BNGE_TX_CMP_EVENT; + if (cmp_type =3D=3D CMP_TYPE_TX_L2_COAL_CMP) + txr->tx_hw_cons =3D TX_CMP_SQ_CONS_IDX(txcmp); + else + txr->tx_hw_cons =3D TX_OPAQUE_PROD(bn, opaque); + tx_freed =3D ((txr->tx_hw_cons - txr->tx_cons) & + bn->tx_ring_mask); + /* return full budget so NAPI will complete. */ + if (unlikely(tx_freed >=3D bn->tx_wake_thresh)) { + rx_pkts =3D budget; + raw_cons =3D NEXT_RAW_CMP(raw_cons); + if (budget) + cpr->has_more_work =3D 1; + break; + } } else if (cmp_type >=3D CMP_TYPE_RX_L2_CMP && cmp_type <=3D CMP_TYPE_RX_L2_TPA_START_V3_CMP) { if (likely(budget)) @@ -619,3 +710,276 @@ int bnge_napi_poll(struct napi_struct *napi, int budg= et) poll_done: return work_done; } + +static u16 bnge_xmit_get_cfa_action(struct sk_buff *skb) +{ + struct metadata_dst *md_dst =3D skb_metadata_dst(skb); + + if (!md_dst || md_dst->type !=3D METADATA_HW_PORT_MUX) + return 0; + + return md_dst->u.port_info.port_id; +} + +static const u16 bnge_lhint_arr[] =3D { + TX_BD_FLAGS_LHINT_512_AND_SMALLER, + TX_BD_FLAGS_LHINT_512_TO_1023, + TX_BD_FLAGS_LHINT_1024_TO_2047, + TX_BD_FLAGS_LHINT_1024_TO_2047, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, +}; + +static void bnge_txr_db_kick(struct bnge_net *bn, struct bnge_tx_ring_info= *txr, + u16 prod) +{ + /* Sync BD data before updating doorbell */ + wmb(); + bnge_db_write(bn->bd, &txr->tx_db, prod); + txr->kick_pending =3D 0; +} + +netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + u32 len, free_size, vlan_tag_flags, cfa_action, flags; + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_tx_ring_info *txr; + struct bnge_dev *bd =3D bn->bd; + unsigned int length, pad =3D 0; + struct bnge_sw_tx_bd *tx_buf; + struct tx_bd *txbd, *txbd0; + struct netdev_queue *txq; + struct tx_bd_ext *txbd1; + u16 prod, last_frag; + dma_addr_t mapping; + __le32 lflags =3D 0; + skb_frag_t *frag; + int i; + + i =3D skb_get_queue_mapping(skb); + if (unlikely(i >=3D bd->tx_nr_rings)) { + dev_kfree_skb_any(skb); + dev_core_stats_tx_dropped_inc(dev); + return NETDEV_TX_OK; + } + + txq =3D netdev_get_tx_queue(dev, i); + txr =3D &bn->tx_ring[bn->tx_ring_map[i]]; + prod =3D txr->tx_prod; + +#if (MAX_SKB_FRAGS > TX_MAX_FRAGS) + if (skb_shinfo(skb)->nr_frags > TX_MAX_FRAGS) { + netdev_warn_once(dev, "SKB has too many (%d) fragments, max supported is= %d. SKB will be linearized.\n", + skb_shinfo(skb)->nr_frags, TX_MAX_FRAGS); + if (skb_linearize(skb)) { + dev_kfree_skb_any(skb); + dev_core_stats_tx_dropped_inc(dev); + return NETDEV_TX_OK; + } + } +#endif + free_size =3D bnge_tx_avail(bn, txr); + if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) { + /* We must have raced with NAPI cleanup */ + if (net_ratelimit() && txr->kick_pending) + netif_warn(bn, tx_err, dev, + "bnxt: ring busy w/ flush pending!\n"); + if (!netif_txq_try_stop(txq, bnge_tx_avail(bn, txr), + bn->tx_wake_thresh)) + return NETDEV_TX_BUSY; + } + + if (unlikely(ipv6_hopopt_jumbo_remove(skb))) + goto tx_free; + + length =3D skb->len; + len =3D skb_headlen(skb); + last_frag =3D skb_shinfo(skb)->nr_frags; + + txbd =3D &txr->tx_desc_ring[TX_RING(bn, prod)][TX_IDX(prod)]; + + tx_buf =3D &txr->tx_buf_ring[RING_TX(bn, prod)]; + tx_buf->skb =3D skb; + tx_buf->nr_frags =3D last_frag; + + vlan_tag_flags =3D 0; + cfa_action =3D bnge_xmit_get_cfa_action(skb); + if (skb_vlan_tag_present(skb)) { + vlan_tag_flags =3D TX_BD_CFA_META_KEY_VLAN | + skb_vlan_tag_get(skb); + /* Currently supports 8021Q, 8021AD vlan offloads + * QINQ1, QINQ2, QINQ3 vlan headers are deprecated + */ + if (skb->vlan_proto =3D=3D htons(ETH_P_8021Q)) + vlan_tag_flags |=3D 1 << TX_BD_CFA_META_TPID_SHIFT; + } + + if (unlikely(skb->no_fcs)) + lflags |=3D cpu_to_le32(TX_BD_FLAGS_NO_CRC); + + if (length < BNGE_MIN_PKT_SIZE) { + pad =3D BNGE_MIN_PKT_SIZE - length; + if (skb_pad(skb, pad)) + /* SKB already freed. */ + goto tx_kick_pending; + length =3D BNGE_MIN_PKT_SIZE; + } + + mapping =3D dma_map_single(bd->dev, skb->data, len, DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(bd->dev, mapping))) + goto tx_free; + + dma_unmap_addr_set(tx_buf, mapping, mapping); + flags =3D (len << TX_BD_LEN_SHIFT) | TX_BD_TYPE_LONG_TX_BD | + TX_BD_CNT(last_frag + 2); + + txbd->tx_bd_haddr =3D cpu_to_le64(mapping); + txbd->tx_bd_opaque =3D SET_TX_OPAQUE(bn, txr, prod, 2 + last_frag); + + prod =3D NEXT_TX(prod); + txbd1 =3D (struct tx_bd_ext *) + &txr->tx_desc_ring[TX_RING(bn, prod)][TX_IDX(prod)]; + + txbd1->tx_bd_hsize_lflags =3D lflags; + if (skb_is_gso(skb)) { + bool udp_gso =3D !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4); + u32 hdr_len; + + if (skb->encapsulation) { + if (udp_gso) + hdr_len =3D skb_inner_transport_offset(skb) + + sizeof(struct udphdr); + else + hdr_len =3D skb_inner_tcp_all_headers(skb); + } else if (udp_gso) { + hdr_len =3D skb_transport_offset(skb) + + sizeof(struct udphdr); + } else { + hdr_len =3D skb_tcp_all_headers(skb); + } + + txbd1->tx_bd_hsize_lflags |=3D cpu_to_le32(TX_BD_FLAGS_LSO | + TX_BD_FLAGS_T_IPID | + (hdr_len << (TX_BD_HSIZE_SHIFT - 1))); + length =3D skb_shinfo(skb)->gso_size; + txbd1->tx_bd_mss =3D cpu_to_le32(length); + length +=3D hdr_len; + } else if (skb->ip_summed =3D=3D CHECKSUM_PARTIAL) { + txbd1->tx_bd_hsize_lflags |=3D + cpu_to_le32(TX_BD_FLAGS_TCP_UDP_CHKSUM); + txbd1->tx_bd_mss =3D 0; + } + + length >>=3D 9; + if (unlikely(length >=3D ARRAY_SIZE(bnge_lhint_arr))) { + dev_warn_ratelimited(bd->dev, "Dropped oversize %d bytes TX packet.\n", + skb->len); + i =3D 0; + goto tx_dma_error; + } + flags |=3D bnge_lhint_arr[length]; + txbd->tx_bd_len_flags_type =3D cpu_to_le32(flags); + + txbd1->tx_bd_cfa_meta =3D cpu_to_le32(vlan_tag_flags); + txbd1->tx_bd_cfa_action =3D + cpu_to_le32(cfa_action << TX_BD_CFA_ACTION_SHIFT); + txbd0 =3D txbd; + for (i =3D 0; i < last_frag; i++) { + frag =3D &skb_shinfo(skb)->frags[i]; + + prod =3D NEXT_TX(prod); + txbd =3D &txr->tx_desc_ring[TX_RING(bn, prod)][TX_IDX(prod)]; + + len =3D skb_frag_size(frag); + mapping =3D skb_frag_dma_map(bd->dev, frag, 0, len, + DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(bd->dev, mapping))) + goto tx_dma_error; + + tx_buf =3D &txr->tx_buf_ring[RING_TX(bn, prod)]; + netmem_dma_unmap_addr_set(skb_frag_netmem(frag), tx_buf, + mapping, mapping); + + txbd->tx_bd_haddr =3D cpu_to_le64(mapping); + + flags =3D len << TX_BD_LEN_SHIFT; + txbd->tx_bd_len_flags_type =3D cpu_to_le32(flags); + } + + flags &=3D ~TX_BD_LEN; + txbd->tx_bd_len_flags_type =3D + cpu_to_le32(((len + pad) << TX_BD_LEN_SHIFT) | flags | + TX_BD_FLAGS_PACKET_END); + + netdev_tx_sent_queue(txq, skb->len); + + prod =3D NEXT_TX(prod); + WRITE_ONCE(txr->tx_prod, prod); + + if (!netdev_xmit_more() || netif_xmit_stopped(txq)) { + bnge_txr_db_kick(bn, txr, prod); + } else { + if (free_size >=3D bn->tx_wake_thresh) + txbd0->tx_bd_len_flags_type |=3D + cpu_to_le32(TX_BD_FLAGS_NO_CMPL); + txr->kick_pending =3D 1; + } + + if (unlikely(bnge_tx_avail(bn, txr) <=3D MAX_SKB_FRAGS + 1)) { + if (netdev_xmit_more()) { + txbd0->tx_bd_len_flags_type &=3D + cpu_to_le32(~TX_BD_FLAGS_NO_CMPL); + bnge_txr_db_kick(bn, txr, prod); + } + + netif_txq_try_stop(txq, bnge_tx_avail(bn, txr), + bn->tx_wake_thresh); + } + return NETDEV_TX_OK; + +tx_dma_error: + last_frag =3D i; + + /* start back at beginning and unmap skb */ + prod =3D txr->tx_prod; + tx_buf =3D &txr->tx_buf_ring[RING_TX(bn, prod)]; + dma_unmap_single(bd->dev, dma_unmap_addr(tx_buf, mapping), + skb_headlen(skb), DMA_TO_DEVICE); + prod =3D NEXT_TX(prod); + + /* unmap remaining mapped pages */ + for (i =3D 0; i < last_frag; i++) { + prod =3D NEXT_TX(prod); + tx_buf =3D &txr->tx_buf_ring[RING_TX(bn, prod)]; + frag =3D &skb_shinfo(skb)->frags[i]; + netmem_dma_unmap_page_attrs(bd->dev, + dma_unmap_addr(tx_buf, mapping), + skb_frag_size(frag), + DMA_TO_DEVICE, 0); + } + +tx_free: + dev_kfree_skb_any(skb); + +tx_kick_pending: + if (txr->kick_pending) + bnge_txr_db_kick(bn, txr, txr->tx_prod); + txr->tx_buf_ring[RING_TX(bn, txr->tx_prod)].skb =3D NULL; + dev_core_stats_tx_dropped_inc(dev); + return NETDEV_TX_OK; +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.h index 9cd6c7ae65e..38d82cfda46 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h @@ -7,6 +7,34 @@ #include #include "bnge_netdev.h" =20 +static inline u32 bnge_tx_avail(struct bnge_net *bn, + const struct bnge_tx_ring_info *txr) +{ + u32 used =3D READ_ONCE(txr->tx_prod) - READ_ONCE(txr->tx_cons); + + return bn->tx_ring_size - (used & bn->tx_ring_mask); +} + +static inline void bnge_writeq_relaxed(struct bnge_dev *bd, u64 val, + volatile void __iomem *addr) +{ +#if BITS_PER_LONG =3D=3D 32 + spin_lock(&bd->db_lock); + lo_hi_writeq_relaxed(val, addr); + spin_unlock(&bd->db_lock); +#else + writeq_relaxed(val, addr); +#endif +} + +/* For TX and RX ring doorbells with no ordering guarantee*/ +static inline void bnge_db_write_relaxed(struct bnge_net *bn, + struct bnge_db_info *db, u32 idx) +{ + bnge_writeq_relaxed(bn->bd, db->db_key64 | DB_RING_IDX(db, idx), + db->doorbell); +} + #define BNGE_MIN_PKT_SIZE 52 =20 #define TX_OPAQUE_IDX_MASK 0x0000ffff @@ -26,6 +54,11 @@ TX_OPAQUE_BDS_SHIFT) #define TX_OPAQUE_PROD(bn, opq) ((TX_OPAQUE_IDX(opq) + TX_OPAQUE_BDS(opq))= &\ (bn)->tx_ring_mask) +#define TX_BD_CNT(n) (((n) << TX_BD_FLAGS_BD_CNT_SHIFT) & TX_BD_FLAGS_BD_C= NT) + +#define TX_MAX_BD_CNT 32 + +#define TX_MAX_FRAGS (TX_MAX_BD_CNT - 2) =20 /* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1. We need one ext= ra * BD because the first TX BD is always a long BD. @@ -78,6 +111,7 @@ #define RING_CMP(bn, idx) ((idx) & (bn)->cp_ring_mask) =20 irqreturn_t bnge_msix(int irq, void *dev_instance); +netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struct net_device *dev); void bnge_reuse_rx_data(struct bnge_rx_ring_info *rxr, u16 cons, void *dat= a); int bnge_napi_poll(struct napi_struct *napi, int budget); #endif /* _BNGE_TXRX_H_ */ --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-pf1-f228.google.com (mail-pf1-f228.google.com [209.85.210.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 81A48343D9D for ; Wed, 26 Nov 2025 19:50:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186633; cv=none; b=n2qcZ7tz8RcMb9dZppm2GtPMlkHx/ad6PRh7hbQjgncvp/yq+adkDx1UiLE4bLeh1ci+Vg4DHrO/5oAITx/dGZLt8uTJQWVyoCk5q/qQte14eWU/WUR/mw3xJkCW75vQnLk5Qc1kp8sZTVqP8yzljiDm1MlINIVzSm9lpetnNRk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186633; c=relaxed/simple; bh=4oLfJbxce47x6fRyv5tOBHn1pBqwSlMXD6VuQBoOOqg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iDwtjhzJS5BloXfzdYRzG6mvZ4XuzCeW9HgvA9WvQYgBPszfkqsZrJQy7ScbQi2zieYlYUDkbzjsImij4B8evWCZon7YlZSXt6LgFQk5U7yOYerjj5QfUx/wHuu36omrWtANIbbK1SaHFXyF5hTvsRJQUglC1aKWj/VmhTF0k6o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=C6zrsS+G; arc=none smtp.client-ip=209.85.210.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="C6zrsS+G" Received: by mail-pf1-f228.google.com with SMTP id d2e1a72fcca58-7b80fed1505so93193b3a.3 for ; Wed, 26 Nov 2025 11:50:31 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186631; x=1764791431; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=VGo736hYE2HqPRLBs6ZTdR8Gvro/N2dMrm8aw+YlO9Q=; b=vD7u8QKPIb1uJq5f6vcrKl4YfJR1X3ZZg8VzJXvlegNxLRyWhTze+jgs8gXeUTivt0 NJ02caC/vSY57J8O49sdCpm4Q1WlH7jlL5NpRrd9spmBDHG6iTAeuQ2fkuInPmUJH2B0 8CG475ZOlxrPf2zsaUdBteV7QXhu7wzHPzOXM/2nY7X0VYD8hiaViphpp4FwGuS1l+zz UsZspsIhXftH/Em7Hz3WEuXqOlKnCt9f80WIDieN5aP2onwAYhGt8oqor9ER9iX3htfL geXBfsvhkIpiHdrWeTQHGXiwnm4zWEHCmeqm+/0OlJSCwVpL4e6U2ZQaCRzOL/wKwG1r nmpQ== X-Forwarded-Encrypted: i=1; AJvYcCU8Q1Wyt6ku2a47LIeheTXdmvuSNj4VWNqmO5Wm2/wEY9Mm38ntaMSfqfQEIeAu5ogHc2JjmFM5JwGlTBI=@vger.kernel.org X-Gm-Message-State: AOJu0YyS9i91hbuhsFsLoBVplX+ybdaiFouTvrfZLaDMWzNAGLiJQVEC IKHFLjBZVG+QazOdTrHBfAhWDiFv3Bg4e0gdvD30meqFfJBMoiQVe+NgKbUmDgG8Xqy4FslWD/y 1jy9XEZm7/dthYH1c1A660mdzszxXSQKLZVZcPZVijl6MK83FJwUfx3RHC0iv55UVcH7DZmdTna muEvotlwbejd1d8/Xe9lN6aBEp9+rFOQK0rdAzX5fJ5tEscwqSmv2PI8hs3dZTu9ry+HY5NXILb kGH4db5UHECFZCGIpadu3Gw5ZQH X-Gm-Gg: ASbGncu/d+7ZoMIH1x0GW7OpnGeYdyjOFISIX/SFuaPB0LpenKIJ9icCEq0OgrVKTWM 01DXKeCzqLausYjY+np/lRqJu7aIzJ2vCZNfTpZP0D7huuXKeyi3Nwot/0T2qFaytxy8ZDf0e8v A/VKdOwQByFY/9cZkQTN98pJibCh+OeEGyOa3T9P/CLrzSzanvyby6UUkzUNK3u95EGA4hxza3W tZAW8ww34oXpOyaMPgHcYxgsl6x1evsG/u/TqzTKveZWRrZ39bgQgvbt0pZ8JqDUwHkmgsgpd1z /gaRNvjsbb1LqZnu8rVlMJaw1rwd2YFaOTQNJhuseizratCloyw8IvTy1cqjRDKDRW+T3WwYGPs 2FBkVvOTW3IcSFrDzLr9IMNcnnwbAWlfdR48dCJ+ZkgRmwGRxnql7ZBS89nvWxCkJD+94u+7DFh +lMGw6MlzaGvB3mQLUh5MhPuHmdfSdCevSaNKmOfWDgD1EgOLOzZw= X-Google-Smtp-Source: AGHT+IElDBJBumvfogZRabOTrR5uY5Y1Ze2q+SApTA95iuYbY2kbpA1FpEuOQnSJ9/3dboovDboF/s0ImvU3 X-Received: by 2002:a05:6a00:1896:b0:7a2:7458:7fc8 with SMTP id d2e1a72fcca58-7c58c999f3amr19242137b3a.13.1764186630824; Wed, 26 Nov 2025 11:50:30 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-77.dlp.protect.broadcom.com. [144.49.247.77]) by smtp-relay.gmail.com with ESMTPS id d2e1a72fcca58-7c3eea87c9bsm1974757b3a.6.2025.11.26.11.50.30 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:30 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f199.google.com with SMTP id d9443c01a7336-29809acd049so1615065ad.3 for ; Wed, 26 Nov 2025 11:50:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186629; x=1764791429; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VGo736hYE2HqPRLBs6ZTdR8Gvro/N2dMrm8aw+YlO9Q=; b=C6zrsS+GRntlk2Py3l/QYjN2j2sUfN2Ri6zLSVQGWsIfEnnE7I7UAvhtQBAU33H9XC 7rD2em3wdP3rg4zhihQY7oM9GDgzmYcH4N8lpYrxQ6zuXo4zO6e0Wn1H5UlZmlMvXNFl +X//P/CMdv5lsJgNkwfv82sWJATjbu9/l9HsQ= X-Forwarded-Encrypted: i=1; AJvYcCVLxWeYffgK4UDhhRWQ6qHh4+4J4yOHv8hKbBg5WN165Eq5JgR90SpCBNEsAMyQ3eSbP6gQwYaAy0/BlcA=@vger.kernel.org X-Received: by 2002:a17:903:1b50:b0:295:8da5:c631 with SMTP id d9443c01a7336-29b6bf65833mr244955245ad.42.1764186628941; Wed, 26 Nov 2025 11:50:28 -0800 (PST) X-Received: by 2002:a17:903:1b50:b0:295:8da5:c631 with SMTP id d9443c01a7336-29b6bf65833mr244955075ad.42.1764186628504; Wed, 26 Nov 2025 11:50:28 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:28 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 06/12] bng_en: Add support to handle AGG events Date: Thu, 27 Nov 2025 01:19:25 +0530 Message-ID: <20251126194931.455830-7-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Add AGG event handling in the RX path to receive packet data on AGG rings. This enables Jumbo and HDS functionality. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_hw_def.h | 13 ++ .../net/ethernet/broadcom/bnge/bnge_netdev.c | 17 +- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 5 + .../net/ethernet/broadcom/bnge/bnge_txrx.c | 219 +++++++++++++++++- .../net/ethernet/broadcom/bnge/bnge_txrx.h | 1 + 5 files changed, 247 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h b/drivers/net= /ethernet/broadcom/bnge/bnge_hw_def.h index 4da4259095f..cfc888a7f9e 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h @@ -4,6 +4,19 @@ #ifndef _BNGE_HW_DEF_H_ #define _BNGE_HW_DEF_H_ =20 +struct rx_agg_cmp { + __le32 rx_agg_cmp_len_flags_type; + #define RX_AGG_CMP_TYPE (0x3f << 0) + #define RX_AGG_CMP_LEN (0xffff << 16) + #define RX_AGG_CMP_LEN_SHIFT 16 + u32 rx_agg_cmp_opaque; + __le32 rx_agg_cmp_v; + #define RX_AGG_CMP_V (1 << 0) + #define RX_AGG_CMP_AGG_ID (0xffff << 16) + #define RX_AGG_CMP_AGG_ID_SHIFT 16 + __le32 rx_agg_cmp_unused; +}; + struct tx_bd_ext { __le32 tx_bd_hsize_lflags; #define TX_BD_FLAGS_TCP_UDP_CHKSUM (1 << 0) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 1af2c4e29c6..9c827afb131 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -980,9 +983,9 @@ static netmem_ref __bnge_alloc_rx_netmem(struct bnge_ne= t *bn, return netmem; } =20 -static u8 *__bnge_alloc_rx_frag(struct bnge_net *bn, dma_addr_t *mapping, - struct bnge_rx_ring_info *rxr, - gfp_t gfp) +u8 *__bnge_alloc_rx_frag(struct bnge_net *bn, dma_addr_t *mapping, + struct bnge_rx_ring_info *rxr, + gfp_t gfp) { unsigned int offset; struct page *page; @@ -1049,7 +1052,7 @@ static int bnge_alloc_one_rx_ring_bufs(struct bnge_ne= t *bn, return 0; } =20 -static u16 bnge_find_next_agg_idx(struct bnge_rx_ring_info *rxr, u16 idx) +u16 bnge_find_next_agg_idx(struct bnge_rx_ring_info *rxr, u16 idx) { u16 next, max =3D rxr->rx_agg_bmap_size; =20 @@ -1059,9 +1062,9 @@ static u16 bnge_find_next_agg_idx(struct bnge_rx_ring= _info *rxr, u16 idx) return next; } =20 -static int bnge_alloc_rx_netmem(struct bnge_net *bn, - struct bnge_rx_ring_info *rxr, - u16 prod, gfp_t gfp) +int bnge_alloc_rx_netmem(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr, + u16 prod, gfp_t gfp) { struct bnge_sw_rx_agg_bd *rx_agg_buf; u16 sw_prod =3D rxr->rx_sw_agg_prod; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 94d03d1e76b..9d49241d732 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -516,4 +516,9 @@ u16 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr); void bnge_fill_hw_rss_tbl(struct bnge_net *bn, struct bnge_vnic_info *vnic= ); int bnge_alloc_rx_data(struct bnge_net *bn, struct bnge_rx_ring_info *rxr, u16 prod, gfp_t gfp); +u16 bnge_find_next_agg_idx(struct bnge_rx_ring_info *rxr, u16 idx); +u8 *__bnge_alloc_rx_frag(struct bnge_net *bn, dma_addr_t *mapping, + struct bnge_rx_ring_info *rxr, gfp_t gfp); +int bnge_alloc_rx_netmem(struct bnge_net *bn, struct bnge_rx_ring_info *rx= r, + u16 prod, gfp_t gfp); #endif /* _BNGE_NETDEV_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index 7470a705aae..0f897876bdc 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,189 @@ irqreturn_t bnge_msix(int irq, void *dev_instance) return IRQ_HANDLED; } =20 +static struct rx_agg_cmp *bnge_get_agg(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + u16 cp_cons, u16 curr) +{ + struct rx_agg_cmp *agg; + + cp_cons =3D RING_CMP(bn, ADV_RAW_CMP(cp_cons, curr)); + agg =3D (struct rx_agg_cmp *) + &cpr->desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + return agg; +} + +static void bnge_reuse_rx_agg_bufs(struct bnge_cp_ring_info *cpr, u16 idx, + u16 start, u32 agg_bufs) +{ + struct bnge_napi *bnapi =3D cpr->bnapi; + struct bnge_net *bn =3D bnapi->bn; + struct bnge_rx_ring_info *rxr; + u16 prod, sw_prod; + u32 i; + + rxr =3D bnapi->rx_ring; + sw_prod =3D rxr->rx_sw_agg_prod; + prod =3D rxr->rx_agg_prod; + + for (i =3D 0; i < agg_bufs; i++) { + struct bnge_sw_rx_agg_bd *cons_rx_buf, *prod_rx_buf; + struct rx_agg_cmp *agg; + struct rx_bd *prod_bd; + netmem_ref netmem; + u16 cons; + + agg =3D bnge_get_agg(bn, cpr, idx, start + i); + cons =3D agg->rx_agg_cmp_opaque; + __clear_bit(cons, rxr->rx_agg_bmap); + + if (unlikely(test_bit(sw_prod, rxr->rx_agg_bmap))) + sw_prod =3D bnge_find_next_agg_idx(rxr, sw_prod); + + __set_bit(sw_prod, rxr->rx_agg_bmap); + prod_rx_buf =3D &rxr->rx_agg_buf_ring[sw_prod]; + cons_rx_buf =3D &rxr->rx_agg_buf_ring[cons]; + + /* It is possible for sw_prod to be equal to cons, so + * set cons_rx_buf->netmem to 0 first. + */ + netmem =3D cons_rx_buf->netmem; + cons_rx_buf->netmem =3D 0; + prod_rx_buf->netmem =3D netmem; + + prod_rx_buf->mapping =3D cons_rx_buf->mapping; + + prod_bd =3D &rxr->rx_agg_desc_ring[RX_AGG_RING(bn, prod)] + [RX_IDX(prod)]; + + prod_bd->rx_bd_haddr =3D cpu_to_le64(cons_rx_buf->mapping); + prod_bd->rx_bd_opaque =3D sw_prod; + + prod =3D NEXT_RX_AGG(prod); + sw_prod =3D RING_RX_AGG(bn, NEXT_RX_AGG(sw_prod)); + } + rxr->rx_agg_prod =3D prod; + rxr->rx_sw_agg_prod =3D sw_prod; +} + +static int bnge_agg_bufs_valid(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + u8 agg_bufs, u32 *raw_cons) +{ + struct rx_agg_cmp *agg; + u16 last; + + *raw_cons =3D ADV_RAW_CMP(*raw_cons, agg_bufs); + last =3D RING_CMP(bn, *raw_cons); + agg =3D (struct rx_agg_cmp *) + &cpr->desc_ring[CP_RING(last)][CP_IDX(last)]; + return RX_AGG_CMP_VALID(bn, agg, *raw_cons); +} + +static int bnge_discard_rx(struct bnge_net *bn, struct bnge_cp_ring_info *= cpr, + u32 *raw_cons, void *cmp) +{ + u32 tmp_raw_cons =3D *raw_cons; + struct rx_cmp *rxcmp =3D cmp; + u8 cmp_type, agg_bufs =3D 0; + + cmp_type =3D RX_CMP_TYPE(rxcmp); + + if (cmp_type =3D=3D CMP_TYPE_RX_L2_CMP) { + agg_bufs =3D (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & + RX_CMP_AGG_BUFS) >> + RX_CMP_AGG_BUFS_SHIFT; + } + + if (agg_bufs) { + if (!bnge_agg_bufs_valid(bn, cpr, agg_bufs, &tmp_raw_cons)) + return -EBUSY; + } + *raw_cons =3D tmp_raw_cons; + return 0; +} + +static u32 __bnge_rx_agg_netmems(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + u16 idx, u32 agg_bufs, + struct sk_buff *skb) +{ + struct bnge_napi *bnapi =3D cpr->bnapi; + struct skb_shared_info *shinfo; + struct bnge_rx_ring_info *rxr; + u32 i, total_frag_len =3D 0; + u16 prod; + + rxr =3D bnapi->rx_ring; + prod =3D rxr->rx_agg_prod; + shinfo =3D skb_shinfo(skb); + + for (i =3D 0; i < agg_bufs; i++) { + struct bnge_sw_rx_agg_bd *cons_rx_buf; + struct rx_agg_cmp *agg; + u16 cons, frag_len; + netmem_ref netmem; + + agg =3D bnge_get_agg(bn, cpr, idx, i); + cons =3D agg->rx_agg_cmp_opaque; + frag_len =3D (le32_to_cpu(agg->rx_agg_cmp_len_flags_type) & + RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT; + + cons_rx_buf =3D &rxr->rx_agg_buf_ring[cons]; + skb_add_rx_frag_netmem(skb, i, cons_rx_buf->netmem, 0, + frag_len, BNGE_RX_PAGE_SIZE); + __clear_bit(cons, rxr->rx_agg_bmap); + + /* It is possible for bnge_alloc_rx_netmem() to allocate + * a sw_prod index that equals the cons index, so we + * need to clear the cons entry now. + */ + netmem =3D cons_rx_buf->netmem; + cons_rx_buf->netmem =3D 0; + + if (bnge_alloc_rx_netmem(bn, rxr, prod, GFP_ATOMIC) !=3D 0) { + skb->len -=3D frag_len; + skb->data_len -=3D frag_len; + skb->truesize -=3D BNGE_RX_PAGE_SIZE; + + --shinfo->nr_frags; + cons_rx_buf->netmem =3D netmem; + + /* Update prod since possibly some netmems have been + * allocated already. + */ + rxr->rx_agg_prod =3D prod; + bnge_reuse_rx_agg_bufs(cpr, idx, i, agg_bufs - i); + return 0; + } + + page_pool_dma_sync_netmem_for_cpu(rxr->page_pool, netmem, 0, + BNGE_RX_PAGE_SIZE); + + total_frag_len +=3D frag_len; + prod =3D NEXT_RX_AGG(prod); + } + rxr->rx_agg_prod =3D prod; + return total_frag_len; +} + +static struct sk_buff *bnge_rx_agg_netmems_skb(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + struct sk_buff *skb, u16 idx, + u32 agg_bufs) +{ + u32 total_frag_len =3D 0; + + total_frag_len =3D __bnge_rx_agg_netmems(bn, cpr, idx, agg_bufs, skb); + if (!total_frag_len) { + skb_mark_for_recycle(skb); + dev_kfree_skb(skb); + return NULL; + } + + return skb; +} + static void bnge_sched_reset_rxr(struct bnge_net *bn, struct bnge_rx_ring_info *rxr) { @@ -215,6 +399,7 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bnge= _cp_ring_info *cpr, dma_addr_t dma_addr; struct sk_buff *skb; unsigned int len; + u8 agg_bufs; void *data; int rc =3D 0; =20 @@ -244,11 +429,15 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bn= ge_cp_ring_info *cpr, =20 cons =3D rxcmp->rx_cmp_opaque; if (unlikely(cons !=3D rxr->rx_next_cons)) { + int rc1 =3D bnge_discard_rx(bn, cpr, &tmp_raw_cons, rxcmp); + /* 0xffff is forced error, don't print it */ if (rxr->rx_next_cons !=3D 0xffff) netdev_warn(bn->netdev, "RX cons %x !=3D expected cons %x\n", cons, rxr->rx_next_cons); bnge_sched_reset_rxr(bn, rxr); + if (rc1) + return rc1; goto next_rx_no_prod_no_len; } rx_buf =3D &rxr->rx_buf_ring[cons]; @@ -257,11 +446,22 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bn= ge_cp_ring_info *cpr, prefetch(data_ptr); =20 misc =3D le32_to_cpu(rxcmp->rx_cmp_misc_v1); + agg_bufs =3D (misc & RX_CMP_AGG_BUFS) >> RX_CMP_AGG_BUFS_SHIFT; + + if (agg_bufs) { + if (!bnge_agg_bufs_valid(bn, cpr, agg_bufs, &tmp_raw_cons)) + return -EBUSY; + + cp_cons =3D NEXT_CMP(bn, cp_cons); + *event |=3D BNGE_AGG_EVENT; + } *event |=3D BNGE_RX_EVENT; =20 rx_buf->data =3D NULL; if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L2_ERRORS) { bnge_reuse_rx_data(rxr, cons, data); + if (agg_bufs) + bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, agg_bufs); rc =3D -EIO; goto next_rx_no_len; } @@ -273,8 +473,12 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bng= e_cp_ring_info *cpr, if (len <=3D bn->rx_copybreak) { skb =3D bnge_copy_skb(bnapi, data_ptr, len, dma_addr); bnge_reuse_rx_data(rxr, cons, data); - if (!skb) + if (!skb) { + if (agg_bufs) + bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, + agg_bufs); goto oom_next_rx; + } } else { u32 payload; =20 @@ -288,6 +492,13 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bng= e_cp_ring_info *cpr, goto oom_next_rx; } =20 + if (agg_bufs) { + skb =3D bnge_rx_agg_netmems_skb(bn, cpr, skb, cp_cons, + agg_bufs); + if (!skb) + goto oom_next_rx; + } + if (RX_CMP_HASH_VALID(rxcmp)) { enum pkt_hash_types type; =20 @@ -469,6 +680,12 @@ static void __bnge_poll_work_done(struct bnge_net *bn,= struct bnge_napi *bnapi, bnge_db_write(bn->bd, &rxr->rx_db, rxr->rx_prod); bnapi->events &=3D ~BNGE_RX_EVENT; } + if (bnapi->events & BNGE_AGG_EVENT) { + struct bnge_rx_ring_info *rxr =3D bnapi->rx_ring; + + bnge_db_write(bn->bd, &rxr->rx_agg_db, rxr->rx_agg_prod); + bnapi->events &=3D ~BNGE_AGG_EVENT; + } } =20 static void diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.h index 38d82cfda46..d3f89634725 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.h @@ -109,6 +109,7 @@ static inline void bnge_db_write_relaxed(struct bnge_ne= t *bn, #define ADV_RAW_CMP(idx, n) ((idx) + (n)) #define NEXT_RAW_CMP(idx) ADV_RAW_CMP(idx, 1) #define RING_CMP(bn, idx) ((idx) & (bn)->cp_ring_mask) +#define NEXT_CMP(bn, idx) RING_CMP(bn, ADV_RAW_CMP(idx, 1)) =20 irqreturn_t bnge_msix(int irq, void *dev_instance); netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struct net_device *dev); --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-il1-f228.google.com (mail-il1-f228.google.com [209.85.166.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2CFB23446AA for ; Wed, 26 Nov 2025 19:50:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.228 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186638; cv=none; b=MngapJQRvsusCRp/r4bPt93QPkPtFYqnV734VA1n0w+10DXQF88mFnD8yRd1d9Qk47wg7RC5DRHnQibRr9TFfeJlesnLtaEUCsvzlIuDIrlWD4jtZ/mulYLgBJCpH+m85NG1PxGpkJcnA2Hqwgi+pRTLWMJXWcOzrvoOywgiiIc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186638; c=relaxed/simple; bh=/HZVNW5OxxlVlNIfHE3ChDv8GsF61qcpxO2JLVI3zN0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cnwNRXnjtf372A9P8bhKDaGV2oTNfYdLJaXsL5M2E3hk4KIfz7LUWqurccEXKt4sWbkp0V7AuYXKx1l/6cRfg5BCwRMpttrBNJcmFgwCHMBwt+WWBYQPbuoegd4Bmcs0zID9c8RzNiK3CA0czO25dlRXk9v8jmkMZ1rFyHCWs5A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=T1OmJ+F9; arc=none smtp.client-ip=209.85.166.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="T1OmJ+F9" Received: by mail-il1-f228.google.com with SMTP id e9e14a558f8ab-43326c74911so898015ab.2 for ; Wed, 26 Nov 2025 11:50:35 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186635; x=1764791435; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=AqSX51l+/a982PibrmJNbpoAtL6ZxZDmwPfrfWLGeh4=; b=abVwfOeHeaecb6uM+mzFHK41pQ7jMOXoi4669jl/EYOqSIfTNVUIDyKbBHLvl6P0qW LGvKFiZB06R9V3dKeP8aBMVmboYgDzulRukP6qtfSMvx7GSz5aPfrxNLqd7sAOZXuiCa CnC3qek9bdUHiRzwSy5g+FeQXtQY4VYqz44R84U5y29h/G6qdVT29sFkq0TLJzij7iyO hOeTdTf1QGGwBoB6T716owAtwiEISojXj6zuyTTrqTCYWvSR8iGuhQRlUEkwip6lqps3 uTpbBkbSuIDgcdeR5b7R1eJMo3bC+rCtiNH4ZAIITrPxXcFiN/V/Fzls7Ls2et6MXbOx UvBg== X-Forwarded-Encrypted: i=1; AJvYcCWO/ZNUfAzvoJyB+Df1AcDvLfuwMrexcSRBuB3qW5K4MW1J+H0/W02VCU0xph4XEJpQ5Qa+1qRRRJN1358=@vger.kernel.org X-Gm-Message-State: AOJu0YzNDwN1Ri8GjseurlP2BmIiJcqmQtI+ff0Ro3uYPgWvZJqHaw2J atP1aa3GogWMfU8NJxmWhhyZfZb+GOOO7KP9S+sqAV7qVQR7V8vEiig4nNrcjIBhmaaPTa/99fx oeFx7EJ3HX9CKt+uFxLC9BjsFWYdZapxyGW8okQpJRlcEjX+yY0D9ZUliOLcGV34BMxZa2MC7uc Krsn1isx6xT5d9UBpL99vwo1TlYVqwwTnYUYD6MgdOvYEQR91KV6EuDPKyK5BWwNlOsCrLdXQt5 1kmB598F75c8LAIDbEFKNEagRff X-Gm-Gg: ASbGnctHmqR+/bvxN0fjMWFeYJynaEQOXq7H1GVaqDx0MVDqPzcuzm2AtQ+NBNSGZyA vj8Jd2dhSPnpZ1AXVtPz7gWY9NwgRbFtRcYYRTWcE+lQtxVaogsMtiHe0RsfeKVQrRb+tN0L0XV OwJVY6cIcDGdLOtPHTFYZx/+lSAfK7WedASnwPRx+P+w67K/gqVJrYYXs1PPZ3uEoQ3nyf8UtlO /QmVDi995E+scBdoVzzG3B3RLQnN4GzVTAvCmb0PvEAJJ3vlymXJ2mdOV5mBHab8MCILis9NmGr CBQyJU6RxUmthMZqHJaWctFgljC8/API1m4ihbWEp8FoJrRDg/oYjRDFvpy0v9B1lomthewnagn HcJW40wAtRT0FtIypMMVdK5qYC2XHQqYL/+kmVI0xeehKhdAgSJqs8OmbXsvY+ulWEFPcXd37kT cN0tvoMDS9G/sygTed/eNPFWpf6C50pIDKOGFYwVGRY3zF2LfRUUeODA== X-Google-Smtp-Source: AGHT+IH0bo9f2nkDD4miu/5io/biD6/qspsrIOfktf1/a+tqZxUTGyXxih20QJ8XU7NPzTf/90LIj1Z3yW/A X-Received: by 2002:a05:6638:9823:b0:5b7:b9bb:e71 with SMTP id 8926c6da1cb9f-5b99964437fmr6908362173.15.1764186635134; Wed, 26 Nov 2025 11:50:35 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-116.dlp.protect.broadcom.com. [144.49.247.116]) by smtp-relay.gmail.com with ESMTPS id 8926c6da1cb9f-5b954a09276sm1884846173.6.2025.11.26.11.50.34 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:35 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-2956a694b47so1436215ad.1 for ; Wed, 26 Nov 2025 11:50:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186634; x=1764791434; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=AqSX51l+/a982PibrmJNbpoAtL6ZxZDmwPfrfWLGeh4=; b=T1OmJ+F9zVN6m0kv0AFPYovDzsmIV19mjTFWZL01LBkpnuXv9C/AljSezmWupCtWPN 55Kph2IjxBfBbdhZouAD0KW/zUlE2dK8r3wGq8RofGH0dhRDcOFmitZ5mcLsmu1L3jBE aK/eqTSV7OvF+wsIcVP81hdNIYWarOrfF7qwo= X-Forwarded-Encrypted: i=1; AJvYcCWoMBle506ZIzpH66t2FdIA9bM29QAEeLHz8c4zQwIt8wjTl/Qdu+HM2Ck0qZQUaT+4EFYDofHLc7dNGno=@vger.kernel.org X-Received: by 2002:a17:903:2c0e:b0:297:ef11:b504 with SMTP id d9443c01a7336-29baafcc2e8mr91392405ad.24.1764186633594; Wed, 26 Nov 2025 11:50:33 -0800 (PST) X-Received: by 2002:a17:903:2c0e:b0:297:ef11:b504 with SMTP id d9443c01a7336-29baafcc2e8mr91392125ad.24.1764186633084; Wed, 26 Nov 2025 11:50:33 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:32 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 07/12] bng_en: Add TPA related functions Date: Thu, 27 Nov 2025 01:19:26 +0530 Message-ID: <20251126194931.455830-8-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Add the functions to handle TPA events in RX path. This helps the next patch enable TPA functionality. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_hw_def.h | 248 ++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.c | 123 +++++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.h | 47 ++++ 3 files changed, 418 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h b/drivers/net= /ethernet/broadcom/bnge/bnge_hw_def.h index cfc888a7f9e..a824e0566be 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hw_def.h @@ -208,4 +208,252 @@ struct rx_cmp_ext { #define HWRM_RING_ALLOC_AGG 0x4 #define HWRM_RING_ALLOC_CMPL 0x8 #define HWRM_RING_ALLOC_NQ 0x10 + +#define TPA_AGG_AGG_ID(rx_agg) \ + ((le32_to_cpu((rx_agg)->rx_agg_cmp_v) & \ + RX_AGG_CMP_AGG_ID) >> RX_AGG_CMP_AGG_ID_SHIFT) + +struct rx_tpa_start_cmp { + __le32 rx_tpa_start_cmp_len_flags_type; + #define RX_TPA_START_CMP_TYPE (0x3f << 0) + #define RX_TPA_START_CMP_FLAGS (0x3ff << 6) + #define RX_TPA_START_CMP_FLAGS_SHIFT 6 + #define RX_TPA_START_CMP_FLAGS_ERROR (0x1 << 6) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT (0x7 << 7) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_SHIFT 7 + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_JUMBO (0x1 << 7) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_HDS (0x2 << 7) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_JUMBO (0x5 << 7) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_HDS (0x6 << 7) + #define RX_TPA_START_CMP_FLAGS_RSS_VALID (0x1 << 10) + #define RX_TPA_START_CMP_FLAGS_TIMESTAMP (0x1 << 11) + #define RX_TPA_START_CMP_FLAGS_ITYPES (0xf << 12) + #define RX_TPA_START_CMP_FLAGS_ITYPES_SHIFT 12 + #define RX_TPA_START_CMP_FLAGS_ITYPE_TCP (0x2 << 12) + #define RX_TPA_START_CMP_LEN (0xffff << 16) + #define RX_TPA_START_CMP_LEN_SHIFT 16 + + u32 rx_tpa_start_cmp_opaque; + __le32 rx_tpa_start_cmp_misc_v1; + #define RX_TPA_START_CMP_V1 (0x1 << 0) + #define RX_TPA_START_CMP_RSS_HASH_TYPE (0x7f << 9) + #define RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT 9 + #define RX_TPA_START_CMP_V3_RSS_HASH_TYPE (0x1ff << 7) + #define RX_TPA_START_CMP_V3_RSS_HASH_TYPE_SHIFT 7 + #define RX_TPA_START_CMP_AGG_ID (0x7f << 25) + #define RX_TPA_START_CMP_AGG_ID_SHIFT 25 + #define RX_TPA_START_CMP_AGG_ID_P5 (0xffff << 16) + #define RX_TPA_START_CMP_AGG_ID_SHIFT_P5 16 + #define RX_TPA_START_CMP_METADATA1 (0xf << 28) + #define RX_TPA_START_CMP_METADATA1_SHIFT 28 + #define RX_TPA_START_METADATA1_TPID_SEL (0x7 << 28) + #define RX_TPA_START_METADATA1_TPID_8021Q (0x1 << 28) + #define RX_TPA_START_METADATA1_TPID_8021AD (0x0 << 28) + #define RX_TPA_START_METADATA1_VALID (0x8 << 28) + + __le32 rx_tpa_start_cmp_rss_hash; +}; + +#define TPA_START_HASH_VALID(rx_tpa_start) \ + ((rx_tpa_start)->rx_tpa_start_cmp_len_flags_type & \ + cpu_to_le32(RX_TPA_START_CMP_FLAGS_RSS_VALID)) + +#define TPA_START_HASH_TYPE(rx_tpa_start) \ + (((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_RSS_HASH_TYPE) >> \ + RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK) + +#define TPA_START_V3_HASH_TYPE(rx_tpa_start) \ + (((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_V3_RSS_HASH_TYPE) >> \ + RX_TPA_START_CMP_V3_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK) + +#define TPA_START_AGG_ID(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_AGG_ID_P5) >> RX_TPA_START_CMP_AGG_ID_SHIFT_P5) + +#define TPA_START_ERROR(rx_tpa_start) \ + ((rx_tpa_start)->rx_tpa_start_cmp_len_flags_type & \ + cpu_to_le32(RX_TPA_START_CMP_FLAGS_ERROR)) + +#define TPA_START_VLAN_VALID(rx_tpa_start) \ + ((rx_tpa_start)->rx_tpa_start_cmp_misc_v1 & \ + cpu_to_le32(RX_TPA_START_METADATA1_VALID)) + +#define TPA_START_VLAN_TPID_SEL(rx_tpa_start) \ + (le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_METADATA1_TPID_SEL) + +struct rx_tpa_start_cmp_ext { + __le32 rx_tpa_start_cmp_flags2; + #define RX_TPA_START_CMP_FLAGS2_IP_CS_CALC (0x1 << 0) + #define RX_TPA_START_CMP_FLAGS2_L4_CS_CALC (0x1 << 1) + #define RX_TPA_START_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2) + #define RX_TPA_START_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3) + #define RX_TPA_START_CMP_FLAGS2_IP_TYPE (0x1 << 8) + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_VALID (0x1 << 9) + #define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT (0x3 << 10) + #define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT_SHIFT 10 + #define RX_TPA_START_CMP_V3_FLAGS2_T_IP_TYPE (0x1 << 10) + #define RX_TPA_START_CMP_V3_FLAGS2_AGG_GRO (0x1 << 11) + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL (0xffff << 16) + #define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_SHIFT 16 + + __le32 rx_tpa_start_cmp_metadata; + __le32 rx_tpa_start_cmp_cfa_code_v2; + #define RX_TPA_START_CMP_V2 (0x1 << 0) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_MASK (0x7 << 1) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_SHIFT 1 + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) + #define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_FLUSH (0x5 << 1) + #define RX_TPA_START_CMP_CFA_CODE (0xffff << 16) + #define RX_TPA_START_CMPL_CFA_CODE_SHIFT 16 + #define RX_TPA_START_CMP_METADATA0_TCI_MASK (0xffff << 16) + #define RX_TPA_START_CMP_METADATA0_VID_MASK (0x0fff << 16) + #define RX_TPA_START_CMP_METADATA0_SFT 16 + __le32 rx_tpa_start_cmp_hdr_info; +}; + +#define TPA_START_CFA_CODE(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_cfa_code_v2) & \ + RX_TPA_START_CMP_CFA_CODE) >> RX_TPA_START_CMPL_CFA_CODE_SHIFT) + +#define TPA_START_IS_IPV6(rx_tpa_start) \ + (!!((rx_tpa_start)->rx_tpa_start_cmp_flags2 & \ + cpu_to_le32(RX_TPA_START_CMP_FLAGS2_IP_TYPE))) + +#define TPA_START_ERROR_CODE(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_cfa_code_v2) & \ + RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_MASK) >> \ + RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_SHIFT) + +#define TPA_START_METADATA0_TCI(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_cfa_code_v2) & \ + RX_TPA_START_CMP_METADATA0_TCI_MASK) >> \ + RX_TPA_START_CMP_METADATA0_SFT) + +struct rx_tpa_end_cmp { + __le32 rx_tpa_end_cmp_len_flags_type; + #define RX_TPA_END_CMP_TYPE (0x3f << 0) + #define RX_TPA_END_CMP_FLAGS (0x3ff << 6) + #define RX_TPA_END_CMP_FLAGS_SHIFT 6 + #define RX_TPA_END_CMP_FLAGS_PLACEMENT (0x7 << 7) + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_SHIFT 7 + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_JUMBO (0x1 << 7) + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_HDS (0x2 << 7) + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_JUMBO (0x5 << 7) + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_HDS (0x6 << 7) + #define RX_TPA_END_CMP_FLAGS_RSS_VALID (0x1 << 10) + #define RX_TPA_END_CMP_FLAGS_ITYPES (0xf << 12) + #define RX_TPA_END_CMP_FLAGS_ITYPES_SHIFT 12 + #define RX_TPA_END_CMP_FLAGS_ITYPE_TCP (0x2 << 12) + #define RX_TPA_END_CMP_LEN (0xffff << 16) + #define RX_TPA_END_CMP_LEN_SHIFT 16 + + u32 rx_tpa_end_cmp_opaque; + __le32 rx_tpa_end_cmp_misc_v1; + #define RX_TPA_END_CMP_V1 (0x1 << 0) + #define RX_TPA_END_CMP_AGG_BUFS (0x3f << 1) + #define RX_TPA_END_CMP_AGG_BUFS_SHIFT 1 + #define RX_TPA_END_CMP_TPA_SEGS (0xff << 8) + #define RX_TPA_END_CMP_TPA_SEGS_SHIFT 8 + #define RX_TPA_END_CMP_PAYLOAD_OFFSET (0xff << 16) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT 16 + #define RX_TPA_END_CMP_AGG_ID (0xffff << 16) + #define RX_TPA_END_CMP_AGG_ID_SHIFT 16 + + __le32 rx_tpa_end_cmp_tsdelta; + #define RX_TPA_END_GRO_TS (0x1 << 31) +}; + +#define TPA_END_AGG_ID(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_AGG_ID) >> RX_TPA_END_CMP_AGG_ID_SHIFT) + +#define TPA_END_TPA_SEGS(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_TPA_SEGS) >> RX_TPA_END_CMP_TPA_SEGS_SHIFT) + +#define RX_TPA_END_CMP_FLAGS_PLACEMENT_ANY_GRO \ + cpu_to_le32(RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_JUMBO & \ + RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_HDS) + +#define TPA_END_GRO(rx_tpa_end) \ + ((rx_tpa_end)->rx_tpa_end_cmp_len_flags_type & \ + RX_TPA_END_CMP_FLAGS_PLACEMENT_ANY_GRO) + +#define TPA_END_GRO_TS(rx_tpa_end) \ + (!!((rx_tpa_end)->rx_tpa_end_cmp_tsdelta & \ + cpu_to_le32(RX_TPA_END_GRO_TS))) + +struct rx_tpa_end_cmp_ext { + __le32 rx_tpa_end_cmp_dup_acks; + #define RX_TPA_END_CMP_TPA_DUP_ACKS (0xf << 0) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_P5 (0xff << 16) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT_P5 16 + #define RX_TPA_END_CMP_AGG_BUFS_P5 (0xff << 24) + #define RX_TPA_END_CMP_AGG_BUFS_SHIFT_P5 24 + + __le32 rx_tpa_end_cmp_seg_len; + #define RX_TPA_END_CMP_TPA_SEG_LEN (0xffff << 0) + + __le32 rx_tpa_end_cmp_errors_v2; + #define RX_TPA_END_CMP_V2 (0x1 << 0) + #define RX_TPA_END_CMP_ERRORS (0x3 << 1) + #define RX_TPA_END_CMP_ERRORS_P5 (0x7 << 1) + #define RX_TPA_END_CMPL_ERRORS_SHIFT 1 + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (0x2 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_RSV_ERROR (0x4 << 1) + #define RX_TPA_END_CMP_ERRORS_BUFFER_ERROR_FLUSH (0x5 << 1) + + u32 rx_tpa_end_cmp_start_opaque; +}; + +#define TPA_END_ERRORS(rx_tpa_end_ext) \ + ((rx_tpa_end_ext)->rx_tpa_end_cmp_errors_v2 & \ + cpu_to_le32(RX_TPA_END_CMP_ERRORS)) + +#define TPA_END_PAYLOAD_OFF(rx_tpa_end_ext) \ + ((le32_to_cpu((rx_tpa_end_ext)->rx_tpa_end_cmp_dup_acks) & \ + RX_TPA_END_CMP_PAYLOAD_OFFSET_P5) >> \ + RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT_P5) + +#define TPA_END_AGG_BUFS(rx_tpa_end_ext) \ + ((le32_to_cpu((rx_tpa_end_ext)->rx_tpa_end_cmp_dup_acks) & \ + RX_TPA_END_CMP_AGG_BUFS_P5) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT_P5) + +#define EVENT_DATA1_RESET_NOTIFY_FATAL(data1) \ + (((data1) & \ + ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_MASK) =3D=3D\ + ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_EXCEPTION_FATAL) + +#define EVENT_DATA1_RESET_NOTIFY_FW_ACTIVATION(data1) \ + (((data1) & \ + ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_MASK) =3D=3D\ + ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_ACTIVATION) + +#define EVENT_DATA2_RESET_NOTIFY_FW_STATUS_CODE(data2) \ + ((data2) & \ + ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA2_FW_STATUS_CODE_MASK) + +#define EVENT_DATA1_RECOVERY_MASTER_FUNC(data1) \ + (!!((data1) & \ + ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_MASTER_FUNC)) + +#define EVENT_DATA1_RECOVERY_ENABLED(data1) \ + (!!((data1) & \ + ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_RECOVERY_ENABLED)) + +#define BNGE_EVENT_ERROR_REPORT_TYPE(data1) \ + (((data1) & \ + ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_MASK) >>\ + ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_SFT) + +#define BNGE_EVENT_INVALID_SIGNAL_DATA(data2) \ + (((data2) & \ + ASYNC_EVENT_CMPL_ERROR_REPORT_INVALID_SIGNAL_EVENT_DATA2_PIN_ID_MASK) >= >\ + ASYNC_EVENT_CMPL_ERROR_REPORT_INVALID_SIGNAL_EVENT_DATA2_PIN_ID_SFT) #endif /* _BNGE_HW_DEF_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 9c827afb131..f1c79906110 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -378,11 +378,37 @@ static void bnge_free_one_agg_ring_bufs(struct bnge_n= et *bn, } } =20 +static void bnge_free_one_tpa_info_data(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr) +{ + int i; + + for (i =3D 0; i < bn->max_tpa; i++) { + struct bnge_tpa_info *tpa_info =3D &rxr->rx_tpa[i]; + u8 *data =3D tpa_info->data; + + if (!data) + continue; + + tpa_info->data =3D NULL; + page_pool_free_va(rxr->head_pool, data, false); + } +} + static void bnge_free_one_rx_ring_pair_bufs(struct bnge_net *bn, struct bnge_rx_ring_info *rxr) { + struct bnge_tpa_idx_map *map; + + if (rxr->rx_tpa) + bnge_free_one_tpa_info_data(bn, rxr); + bnge_free_one_rx_ring_bufs(bn, rxr); bnge_free_one_agg_ring_bufs(bn, rxr); + + map =3D rxr->rx_tpa_idx_map; + if (map) + memset(map->agg_idx_bmap, 0, sizeof(map->agg_idx_bmap)); } =20 static void bnge_free_rx_ring_pair_bufs(struct bnge_net *bn) @@ -453,11 +479,70 @@ static void bnge_free_all_rings_bufs(struct bnge_net = *bn) bnge_free_tx_skbs(bn); } =20 +static void bnge_free_tpa_info(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i, j; + + for (i =3D 0; i < bd->rx_nr_rings; i++) { + struct bnge_rx_ring_info *rxr =3D &bn->rx_ring[i]; + + kfree(rxr->rx_tpa_idx_map); + rxr->rx_tpa_idx_map =3D NULL; + if (rxr->rx_tpa) { + for (j =3D 0; j < bn->max_tpa; j++) { + kfree(rxr->rx_tpa[j].agg_arr); + rxr->rx_tpa[j].agg_arr =3D NULL; + } + } + kfree(rxr->rx_tpa); + rxr->rx_tpa =3D NULL; + } +} + +static int bnge_alloc_tpa_info(struct bnge_net *bn) +{ + struct bnge_dev *bd =3D bn->bd; + int i, j; + + if (!bd->max_tpa_v2) + return 0; + + bn->max_tpa =3D max_t(u16, bd->max_tpa_v2, MAX_TPA); + for (i =3D 0; i < bd->rx_nr_rings; i++) { + struct bnge_rx_ring_info *rxr =3D &bn->rx_ring[i]; + + rxr->rx_tpa =3D kcalloc(bn->max_tpa, sizeof(struct bnge_tpa_info), + GFP_KERNEL); + if (!rxr->rx_tpa) + goto err_free_tpa_info; + + for (j =3D 0; j < bn->max_tpa; j++) { + struct rx_agg_cmp *agg; + + agg =3D kcalloc(MAX_SKB_FRAGS, sizeof(*agg), GFP_KERNEL); + if (!agg) + goto err_free_tpa_info; + rxr->rx_tpa[j].agg_arr =3D agg; + } + rxr->rx_tpa_idx_map =3D kzalloc(sizeof(*rxr->rx_tpa_idx_map), + GFP_KERNEL); + if (!rxr->rx_tpa_idx_map) + goto err_free_tpa_info; + } + return 0; + +err_free_tpa_info: + bnge_free_tpa_info(bn); + return -ENOMEM; +} + static void bnge_free_rx_rings(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; int i; =20 + bnge_free_tpa_info(bn); for (i =3D 0; i < bd->rx_nr_rings; i++) { struct bnge_rx_ring_info *rxr =3D &bn->rx_ring[i]; struct bnge_ring_struct *ring; @@ -582,6 +667,12 @@ static int bnge_alloc_rx_rings(struct bnge_net *bn) goto err_free_rx_rings; } } + + if (bn->priv_flags & BNGE_NET_EN_TPA) { + rc =3D bnge_alloc_tpa_info(bn); + if (rc) + goto err_free_rx_rings; + } return rc; =20 err_free_rx_rings: @@ -1127,6 +1218,29 @@ static int bnge_alloc_one_agg_ring_bufs(struct bnge_= net *bn, return -ENOMEM; } =20 +static int bnge_alloc_one_tpa_info_data(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr) +{ + dma_addr_t mapping; + u8 *data; + int i; + + for (i =3D 0; i < bn->max_tpa; i++) { + data =3D __bnge_alloc_rx_frag(bn, &mapping, rxr, + GFP_KERNEL); + if (!data) + goto err_free_tpa_info_data; + + rxr->rx_tpa[i].data =3D data; + rxr->rx_tpa[i].data_ptr =3D data + bn->rx_offset; + rxr->rx_tpa[i].mapping =3D mapping; + } + return 0; +err_free_tpa_info_data: + bnge_free_one_tpa_info_data(bn, rxr); + return -ENOMEM; +} + static int bnge_alloc_one_rx_ring_pair_bufs(struct bnge_net *bn, int ring_= nr) { struct bnge_rx_ring_info *rxr =3D &bn->rx_ring[ring_nr]; @@ -1141,8 +1255,17 @@ static int bnge_alloc_one_rx_ring_pair_bufs(struct b= nge_net *bn, int ring_nr) if (rc) goto err_free_one_rx_ring_bufs; } + + if (rxr->rx_tpa) { + rc =3D bnge_alloc_one_tpa_info_data(bn, rxr); + if (rc) + goto err_free_one_agg_ring_bufs; + } + return 0; =20 +err_free_one_agg_ring_bufs: + bnge_free_one_agg_ring_bufs(bn, rxr); err_free_one_rx_ring_bufs: bnge_free_one_rx_ring_bufs(bn, rxr); return rc; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 9d49241d732..41e3ca671a7 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -154,6 +154,46 @@ enum { =20 #define BNGE_NET_EN_TPA (BNGE_NET_EN_GRO | BNGE_NET_EN_LRO) =20 +#define BNGE_NO_FW_ACCESS(bd) (pci_channel_offline((bd)->pdev)) + +#define MAX_TPA 256 +#define MAX_TPA_MASK (MAX_TPA - 1) +#define MAX_TPA_SEGS 0x3f + +#define BNGE_AGG_IDX_BMAP_SIZE (MAX_TPA / BITS_PER_LONG) +struct bnge_tpa_idx_map { + u16 agg_id_tbl[1024]; + unsigned long agg_idx_bmap[BNGE_AGG_IDX_BMAP_SIZE]; +}; + +struct bnge_tpa_info { + void *data; + u8 *data_ptr; + dma_addr_t mapping; + u16 len; + unsigned short gso_type; + u32 flags2; + u32 metadata; + enum pkt_hash_types hash_type; + u32 rss_hash; + u32 hdr_info; + +#define BNGE_TPA_INNER_L3_OFF(hdr_info) \ + (((hdr_info) >> 18) & 0x1ff) + +#define BNGE_TPA_INNER_L2_OFF(hdr_info) \ + (((hdr_info) >> 9) & 0x1ff) + +#define BNGE_TPA_OUTER_L3_OFF(hdr_info) \ + ((hdr_info) & 0x1ff) + + u16 cfa_code; /* cfa_code in TPA start compl */ + u8 agg_count; + u8 vlan_valid:1; + u8 cfa_code_valid:1; + struct rx_agg_cmp *agg_arr; +}; + /* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1. We need one extra * BD because the first TX BD is always a long BD. */ @@ -248,6 +288,10 @@ struct bnge_net { #define BNGE_STATE_NAPI_DISABLED 0 =20 u32 msg_enable; + u16 max_tpa; + __be16 vxlan_port; + __be16 nge_port; + __be16 vxlan_gpe_port; }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 @@ -393,6 +437,9 @@ struct bnge_rx_ring_info { dma_addr_t rx_desc_mapping[MAX_RX_PAGES]; dma_addr_t rx_agg_desc_mapping[MAX_RX_AGG_PAGES]; =20 + struct bnge_tpa_info *rx_tpa; + struct bnge_tpa_idx_map *rx_tpa_idx_map; + struct bnge_ring_struct rx_ring_struct; struct bnge_ring_struct rx_agg_ring_struct; struct page_pool *page_pool; --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-pj1-f97.google.com (mail-pj1-f97.google.com [209.85.216.97]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DEC863451BA for ; Wed, 26 Nov 2025 19:50:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.97 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186643; cv=none; b=doOEOSkUuaBpTa1JfHTDkWlsCcLF2EtHyDS/VTVmKzIUdzBAc5VFOkmI8B2WH2RqW/LIWuZnqklW5DUCZYgp5XqV7QrUg+Z8nqYu1DeyKksPso+1rfh4n7vIGCLIs39zKJecNZ9IXa/zsf5r7Ey/mis3Ppxm8DFiPd7oMGcsoTg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186643; c=relaxed/simple; bh=cMokbu6UdxnW0QLjKK6xPxBiReQ2PwDBBMuSiOtPHFY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pEaYcsuaBJS7HRt76IDSZWeaB5eMS6mOvMuf1PP6rsEDocpMxYUSzgWxdYbFD4o+XYvGvAVr8pChoQll4H3k4N3GK033Mf/TLHmaE4PPjBvQGmrIZqpxV1gJMY0+G94SNa4ii2/BgNirklL4MBD8WOeW44xVnGmmb1P32vIEE9Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=Pq/8Xv+g; arc=none smtp.client-ip=209.85.216.97 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="Pq/8Xv+g" Received: by mail-pj1-f97.google.com with SMTP id 98e67ed59e1d1-343dd5aa6e7so129877a91.0 for ; Wed, 26 Nov 2025 11:50:40 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186640; x=1764791440; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=YkPcAYv3OqJaPH21G4AEKp4As/P3aS2Z6SmIMQeexDk=; b=HvzbSQsPfK3frp1cokhKMpBU3r0lAYVBlu4kdKNfOl4RAYWhmy7XV3arqeUZi/CIWX QuG70lIfLRjTjFOTPoOHFzO04MQfN/zQ+8GHJVv+VPmP3LuSu4HLcrR9RWa0fUP1jNA/ x23i1ttFt2XKbESEuR/ICnySODxxdYsnM5sU5XJkNlqzLVaox/fPpvOqG8q8IulNcSNV sGntsFgVwdvIfGfh0+T4UaT12ejuX4d+d8E9+XJep4OVwhcbuQVceQjkj1znCSCbrCGu LgzjqJTOZQ7+rKRDDsM9NUS0BVRoxoDG24glfTnZsYgR8yj/tq4JPj2bOXQpkLgE/70h ShkA== X-Forwarded-Encrypted: i=1; AJvYcCWUAr47QmxIFPVdGxHyiCxYbv0jsNOWg5vKpM7j8ZGpRhRplGJtbYCVBrsSmxCUlo2soK67J86brSmTzp0=@vger.kernel.org X-Gm-Message-State: AOJu0Yy5PzulU6S2jdNl6smwQYNJFSk4Kjt5YceW6GI5+7k5ie2ms16s hvgngzZF7qrx9HKa5dPLPRnvuwGzmNYaa9td7l6Vluo9thWnbWeaCLpk7N/u1aYZs5FuMh7OkPF WlMzD6vcDATq/ol7irASVIffc6hOWGuIiWYtWbIZeD9MlpkhdjQi9KypvbWiEAkFlu9h0KezpVG nQ9xU2R9PxkDsL+vl/j1jyRUDjZAg4f6PZmDT6eBLrajiUALolA1sQVjsUDy2zHXvRQFWsimxSy 5klqurV9EwaiQAxDuwDg4tzdQPh X-Gm-Gg: ASbGncv8ozR6MIUBirZrFa1qtf1J6bZr5Bq8EJaH6V48x9w4eNS76NkSfIstIqQ4m86 2vq33XvBUboKbtlm3+YB9xJVZX9iOcgbGaWxDZ+Qj0lhkSvEkMeTYcqu38LtjPS48oEaVmUbXHC UzauQUrCGZa1/Lc9vyvaCs3jeFrn/bZ7av//JmWvsBL0hY9HnMt06Ua9rm4Vt5O2srb5I9vWxhv Nb7vCNoGaZNaZ9wdiB4rNN3n4w+AlQHBEUgdXss2lKwLZ5y9ET7h9muUd68aGnik5iGv31e2f9n N1m/ew9VMVHYzNbh0ByS1aRei3fwnAbg1Vzpi59pCBkICzEKJElwceTaUzOeVUTUeB9gD5fNVB3 IR8IOBy3aQ3lLG9YZ2VnQwDII5++jni78XqJRPJprdi87vd2aDstnoQyPenVw0hi6fH4KzkJxoo C0j7C/BAofcWqn473GThADpLBPR2MSmYcQHTLONjUBNUy+0nsEiFeeyw== X-Google-Smtp-Source: AGHT+IFzVY6x5VUdzO8i2zkeZEP55i1wyRFy7dEgCDp4dhBdctRnFOh7QZUXRn7z1iQTFZpoQRhCN2ru/fGl X-Received: by 2002:a17:90b:5450:b0:330:82b1:ef76 with SMTP id 98e67ed59e1d1-34733f350cdmr21273667a91.28.1764186640014; Wed, 26 Nov 2025 11:50:40 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-116.dlp.protect.broadcom.com. [144.49.247.116]) by smtp-relay.gmail.com with ESMTPS id 98e67ed59e1d1-3476a5c71e3sm260842a91.1.2025.11.26.11.50.39 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:40 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f199.google.com with SMTP id d9443c01a7336-29848363458so1737875ad.2 for ; Wed, 26 Nov 2025 11:50:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186638; x=1764791438; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YkPcAYv3OqJaPH21G4AEKp4As/P3aS2Z6SmIMQeexDk=; b=Pq/8Xv+gsRKiASrfVVaMbMHEvJc46dGeq0WLbtMk3Yz1RsvwWDOGG8G6FhAHMp45De acSVDc1gJ3idTYv+d0V2rbuwDKJbMtv9hPlJ1P6g5xMh6h2Xvxg40rN8NS0rMeLICv2n V9m6mlIUOcD7hcOk1cbRC72A/BnRNA8xDUyFc= X-Forwarded-Encrypted: i=1; AJvYcCX/nEowBgIG5udmsHoFwx5O2ZbEEvdzLWFmCDmT4isQiSYl+PkRSwPriqZvuy50mvQonarU7pUAB5n+VcY=@vger.kernel.org X-Received: by 2002:a17:902:cf10:b0:295:4d50:aab6 with SMTP id d9443c01a7336-29b6bec46afmr244676835ad.18.1764186638104; Wed, 26 Nov 2025 11:50:38 -0800 (PST) X-Received: by 2002:a17:902:cf10:b0:295:4d50:aab6 with SMTP id d9443c01a7336-29b6bec46afmr244676455ad.18.1764186637636; Wed, 26 Nov 2025 11:50:37 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:37 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 08/12] bng_en: Add support for TPA events Date: Thu, 27 Nov 2025 01:19:27 +0530 Message-ID: <20251126194931.455830-9-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Enable TPA functionality in the VNIC and add functions to handle TPA events, which help in processing LRO/GRO. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../ethernet/broadcom/bnge/bnge_hwrm_lib.c | 65 +++ .../ethernet/broadcom/bnge/bnge_hwrm_lib.h | 2 + .../net/ethernet/broadcom/bnge/bnge_netdev.c | 27 ++ .../net/ethernet/broadcom/bnge/bnge_txrx.c | 430 +++++++++++++++++- 4 files changed, 514 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.c index 9b31069fc7b..d7eb9c7ed6d 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c @@ -1373,3 +1373,68 @@ int bnge_hwrm_set_async_event_cr(struct bnge_dev *bd= , int idx) req->async_event_cr =3D cpu_to_le16(idx); return bnge_hwrm_req_send(bd, req); } + +#define BNGE_DFLT_TUNL_TPA_BMAP \ + (VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_GRE | \ + VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_IPV4 | \ + VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_IPV6) + +static void bnge_hwrm_vnic_update_tunl_tpa(struct bnge_dev *bd, + struct hwrm_vnic_tpa_cfg_input *req) +{ + struct bnge_net *bn =3D netdev_priv(bd->netdev); + u32 tunl_tpa_bmap =3D BNGE_DFLT_TUNL_TPA_BMAP; + + if (!(bd->fw_cap & BNGE_FW_CAP_VNIC_TUNNEL_TPA)) + return; + + if (bn->vxlan_port) + tunl_tpa_bmap |=3D VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_VXLAN; + if (bn->vxlan_gpe_port) + tunl_tpa_bmap |=3D VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_VXLAN_GPE; + if (bn->nge_port) + tunl_tpa_bmap |=3D VNIC_TPA_CFG_REQ_TNL_TPA_EN_BITMAP_GENEVE; + + req->enables |=3D cpu_to_le32(VNIC_TPA_CFG_REQ_ENABLES_TNL_TPA_EN); + req->tnl_tpa_en_bitmap =3D cpu_to_le32(tunl_tpa_bmap); +} + +int bnge_hwrm_vnic_set_tpa(struct bnge_dev *bd, struct bnge_vnic_info *vni= c, + u32 tpa_flags) +{ + struct bnge_net *bn =3D netdev_priv(bd->netdev); + struct hwrm_vnic_tpa_cfg_input *req; + int rc; + + if (vnic->fw_vnic_id =3D=3D INVALID_HW_RING_ID) + return 0; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_VNIC_TPA_CFG); + if (rc) + return rc; + + if (tpa_flags) { + u32 flags; + + flags =3D VNIC_TPA_CFG_REQ_FLAGS_TPA | + VNIC_TPA_CFG_REQ_FLAGS_ENCAP_TPA | + VNIC_TPA_CFG_REQ_FLAGS_RSC_WND_UPDATE | + VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_ECN | + VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_SAME_GRE_SEQ; + if (tpa_flags & BNGE_NET_EN_GRO) + flags |=3D VNIC_TPA_CFG_REQ_FLAGS_GRO; + + req->flags =3D cpu_to_le32(flags); + req->enables =3D + cpu_to_le32(VNIC_TPA_CFG_REQ_ENABLES_MAX_AGG_SEGS | + VNIC_TPA_CFG_REQ_ENABLES_MAX_AGGS | + VNIC_TPA_CFG_REQ_ENABLES_MIN_AGG_LEN); + req->max_agg_segs =3D cpu_to_le16(MAX_TPA_SEGS); + req->max_aggs =3D cpu_to_le16(bn->max_tpa); + req->min_agg_len =3D cpu_to_le32(512); + bnge_hwrm_vnic_update_tunl_tpa(bd, req); + } + req->vnic_id =3D cpu_to_le16(vnic->fw_vnic_id); + + return bnge_hwrm_req_send(bd, req); +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.h index b063f62ae06..f947ca66111 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h @@ -59,4 +59,6 @@ int bnge_update_link(struct bnge_net *bn, bool chng_link_= state); int bnge_hwrm_phy_qcaps(struct bnge_dev *bd); int bnge_hwrm_set_link_setting(struct bnge_net *bn, bool set_pause); int bnge_hwrm_set_pause(struct bnge_net *bn); +int bnge_hwrm_vnic_set_tpa(struct bnge_dev *bd, struct bnge_vnic_info *vni= c, + u32 tpa_flags); #endif /* _BNGE_HWRM_LIB_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index f1c79906110..82bbc370700 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -2273,6 +2273,27 @@ static int bnge_request_irq(struct bnge_net *bn) return rc; } =20 +static int bnge_set_tpa(struct bnge_net *bn, bool set_tpa) +{ + u32 tpa_flags =3D 0; + int rc, i; + + if (set_tpa) + tpa_flags =3D bn->priv_flags & BNGE_NET_EN_TPA; + else if (BNGE_NO_FW_ACCESS(bn->bd)) + return 0; + for (i =3D 0; i < bn->nr_vnics; i++) { + rc =3D bnge_hwrm_vnic_set_tpa(bn->bd, &bn->vnic_info[i], + tpa_flags); + if (rc) { + netdev_err(bn->netdev, "hwrm vnic set tpa failure rc for vnic %d: %x\n", + i, rc); + return rc; + } + } + return 0; +} + static int bnge_init_chip(struct bnge_net *bn) { struct bnge_vnic_info *vnic =3D &bn->vnic_info[BNGE_VNIC_DEFAULT]; @@ -2307,6 +2328,12 @@ static int bnge_init_chip(struct bnge_net *bn) if (bd->rss_cap & BNGE_RSS_CAP_RSS_HASH_TYPE_DELTA) bnge_hwrm_update_rss_hash_cfg(bn); =20 + if (bn->priv_flags & BNGE_NET_EN_TPA) { + rc =3D bnge_set_tpa(bn, true); + if (rc) + goto err_out; + } + /* Filter for default vnic 0 */ rc =3D bnge_hwrm_set_vnic_filter(bn, 0, 0, bn->netdev->dev_addr); if (rc) { diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/e= thernet/broadcom/bnge/bnge_txrx.c index 0f897876bdc..0491cc0d8be 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,15 @@ irqreturn_t bnge_msix(int irq, void *dev_instance) return IRQ_HANDLED; } =20 +static struct rx_agg_cmp *bnge_get_tpa_agg(struct bnge_net *bn, + struct bnge_rx_ring_info *rxr, + u16 agg_id, u16 curr) +{ + struct bnge_tpa_info *tpa_info =3D &rxr->rx_tpa[agg_id]; + + return &tpa_info->agg_arr[curr]; +} + static struct rx_agg_cmp *bnge_get_agg(struct bnge_net *bn, struct bnge_cp_ring_info *cpr, u16 cp_cons, u16 curr) @@ -57,7 +67,7 @@ static struct rx_agg_cmp *bnge_get_agg(struct bnge_net *b= n, } =20 static void bnge_reuse_rx_agg_bufs(struct bnge_cp_ring_info *cpr, u16 idx, - u16 start, u32 agg_bufs) + u16 start, u32 agg_bufs, bool tpa) { struct bnge_napi *bnapi =3D cpr->bnapi; struct bnge_net *bn =3D bnapi->bn; @@ -76,7 +86,10 @@ static void bnge_reuse_rx_agg_bufs(struct bnge_cp_ring_i= nfo *cpr, u16 idx, netmem_ref netmem; u16 cons; =20 - agg =3D bnge_get_agg(bn, cpr, idx, start + i); + if (tpa) + agg =3D bnge_get_tpa_agg(bn, rxr, idx, start + i); + else + agg =3D bnge_get_agg(bn, cpr, idx, start + i); cons =3D agg->rx_agg_cmp_opaque; __clear_bit(cons, rxr->rx_agg_bmap); =20 @@ -136,6 +149,8 @@ static int bnge_discard_rx(struct bnge_net *bn, struct = bnge_cp_ring_info *cpr, agg_bufs =3D (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & RX_CMP_AGG_BUFS) >> RX_CMP_AGG_BUFS_SHIFT; + } else if (cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_END_CMP) { + return 0; } =20 if (agg_bufs) { @@ -148,7 +163,7 @@ static int bnge_discard_rx(struct bnge_net *bn, struct = bnge_cp_ring_info *cpr, =20 static u32 __bnge_rx_agg_netmems(struct bnge_net *bn, struct bnge_cp_ring_info *cpr, - u16 idx, u32 agg_bufs, + u16 idx, u32 agg_bufs, bool tpa, struct sk_buff *skb) { struct bnge_napi *bnapi =3D cpr->bnapi; @@ -167,7 +182,10 @@ static u32 __bnge_rx_agg_netmems(struct bnge_net *bn, u16 cons, frag_len; netmem_ref netmem; =20 - agg =3D bnge_get_agg(bn, cpr, idx, i); + if (tpa) + agg =3D bnge_get_tpa_agg(bn, rxr, idx, i); + else + agg =3D bnge_get_agg(bn, cpr, idx, i); cons =3D agg->rx_agg_cmp_opaque; frag_len =3D (le32_to_cpu(agg->rx_agg_cmp_len_flags_type) & RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT; @@ -196,7 +214,7 @@ static u32 __bnge_rx_agg_netmems(struct bnge_net *bn, * allocated already. */ rxr->rx_agg_prod =3D prod; - bnge_reuse_rx_agg_bufs(cpr, idx, i, agg_bufs - i); + bnge_reuse_rx_agg_bufs(cpr, idx, i, agg_bufs - i, tpa); return 0; } =20 @@ -213,11 +231,12 @@ static u32 __bnge_rx_agg_netmems(struct bnge_net *bn, static struct sk_buff *bnge_rx_agg_netmems_skb(struct bnge_net *bn, struct bnge_cp_ring_info *cpr, struct sk_buff *skb, u16 idx, - u32 agg_bufs) + u32 agg_bufs, bool tpa) { u32 total_frag_len =3D 0; =20 - total_frag_len =3D __bnge_rx_agg_netmems(bn, cpr, idx, agg_bufs, skb); + total_frag_len =3D __bnge_rx_agg_netmems(bn, cpr, idx, agg_bufs, + tpa, skb); if (!total_frag_len) { skb_mark_for_recycle(skb); dev_kfree_skb(skb); @@ -233,6 +252,156 @@ static void bnge_sched_reset_rxr(struct bnge_net *bn, rxr->rx_next_cons =3D 0xffff; } =20 +static u16 bnge_tpa_alloc_agg_idx(struct bnge_rx_ring_info *rxr, u16 agg_i= d) +{ + struct bnge_tpa_idx_map *map =3D rxr->rx_tpa_idx_map; + u16 idx =3D agg_id & MAX_TPA_MASK; + + if (test_bit(idx, map->agg_idx_bmap)) + idx =3D find_first_zero_bit(map->agg_idx_bmap, + BNGE_AGG_IDX_BMAP_SIZE); + __set_bit(idx, map->agg_idx_bmap); + map->agg_id_tbl[agg_id] =3D idx; + return idx; +} + +static void bnge_free_agg_idx(struct bnge_rx_ring_info *rxr, u16 idx) +{ + struct bnge_tpa_idx_map *map =3D rxr->rx_tpa_idx_map; + + __clear_bit(idx, map->agg_idx_bmap); +} + +static u16 bnge_lookup_agg_idx(struct bnge_rx_ring_info *rxr, u16 agg_id) +{ + struct bnge_tpa_idx_map *map =3D rxr->rx_tpa_idx_map; + + return map->agg_id_tbl[agg_id]; +} + +static void bnge_tpa_metadata(struct bnge_tpa_info *tpa_info, + struct rx_tpa_start_cmp *tpa_start, + struct rx_tpa_start_cmp_ext *tpa_start1) +{ + tpa_info->cfa_code_valid =3D 1; + tpa_info->cfa_code =3D TPA_START_CFA_CODE(tpa_start1); + tpa_info->vlan_valid =3D 0; + if (tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) { + tpa_info->vlan_valid =3D 1; + tpa_info->metadata =3D + le32_to_cpu(tpa_start1->rx_tpa_start_cmp_metadata); + } +} + +static void bnge_tpa_metadata_v2(struct bnge_tpa_info *tpa_info, + struct rx_tpa_start_cmp *tpa_start, + struct rx_tpa_start_cmp_ext *tpa_start1) +{ + tpa_info->vlan_valid =3D 0; + if (TPA_START_VLAN_VALID(tpa_start)) { + u32 tpid_sel =3D TPA_START_VLAN_TPID_SEL(tpa_start); + u32 vlan_proto =3D ETH_P_8021Q; + + tpa_info->vlan_valid =3D 1; + if (tpid_sel =3D=3D RX_TPA_START_METADATA1_TPID_8021AD) + vlan_proto =3D ETH_P_8021AD; + tpa_info->metadata =3D vlan_proto << 16 | + TPA_START_METADATA0_TCI(tpa_start1); + } +} + +static void bnge_tpa_start(struct bnge_net *bn, struct bnge_rx_ring_info *= rxr, + u8 cmp_type, struct rx_tpa_start_cmp *tpa_start, + struct rx_tpa_start_cmp_ext *tpa_start1) +{ + struct bnge_sw_rx_bd *cons_rx_buf, *prod_rx_buf; + struct bnge_tpa_info *tpa_info; + u16 cons, prod, agg_id; + struct rx_bd *prod_bd; + dma_addr_t mapping; + + agg_id =3D TPA_START_AGG_ID(tpa_start); + agg_id =3D bnge_tpa_alloc_agg_idx(rxr, agg_id); + cons =3D tpa_start->rx_tpa_start_cmp_opaque; + prod =3D rxr->rx_prod; + cons_rx_buf =3D &rxr->rx_buf_ring[cons]; + prod_rx_buf =3D &rxr->rx_buf_ring[RING_RX(bn, prod)]; + tpa_info =3D &rxr->rx_tpa[agg_id]; + + if (unlikely(cons !=3D rxr->rx_next_cons || + TPA_START_ERROR(tpa_start))) { + netdev_warn(bn->netdev, "TPA cons %x, expected cons %x, error code %x\n", + cons, rxr->rx_next_cons, + TPA_START_ERROR_CODE(tpa_start1)); + bnge_sched_reset_rxr(bn, rxr); + return; + } + prod_rx_buf->data =3D tpa_info->data; + prod_rx_buf->data_ptr =3D tpa_info->data_ptr; + + mapping =3D tpa_info->mapping; + prod_rx_buf->mapping =3D mapping; + + prod_bd =3D &rxr->rx_desc_ring[RX_RING(bn, prod)][RX_IDX(prod)]; + + prod_bd->rx_bd_haddr =3D cpu_to_le64(mapping); + + tpa_info->data =3D cons_rx_buf->data; + tpa_info->data_ptr =3D cons_rx_buf->data_ptr; + cons_rx_buf->data =3D NULL; + tpa_info->mapping =3D cons_rx_buf->mapping; + + tpa_info->len =3D + le32_to_cpu(tpa_start->rx_tpa_start_cmp_len_flags_type) >> + RX_TPA_START_CMP_LEN_SHIFT; + if (likely(TPA_START_HASH_VALID(tpa_start))) { + tpa_info->hash_type =3D PKT_HASH_TYPE_L4; + tpa_info->gso_type =3D SKB_GSO_TCPV4; + if (TPA_START_IS_IPV6(tpa_start1)) + tpa_info->gso_type =3D SKB_GSO_TCPV6; + tpa_info->rss_hash =3D + le32_to_cpu(tpa_start->rx_tpa_start_cmp_rss_hash); + } else { + tpa_info->hash_type =3D PKT_HASH_TYPE_NONE; + tpa_info->gso_type =3D 0; + netif_warn(bn, rx_err, bn->netdev, "TPA packet without valid hash\n"); + } + tpa_info->flags2 =3D le32_to_cpu(tpa_start1->rx_tpa_start_cmp_flags2); + tpa_info->hdr_info =3D le32_to_cpu(tpa_start1->rx_tpa_start_cmp_hdr_info); + if (cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_START_CMP) + bnge_tpa_metadata(tpa_info, tpa_start, tpa_start1); + else + bnge_tpa_metadata_v2(tpa_info, tpa_start, tpa_start1); + tpa_info->agg_count =3D 0; + + rxr->rx_prod =3D NEXT_RX(prod); + cons =3D RING_RX(bn, NEXT_RX(cons)); + rxr->rx_next_cons =3D RING_RX(bn, NEXT_RX(cons)); + cons_rx_buf =3D &rxr->rx_buf_ring[cons]; + + bnge_reuse_rx_data(rxr, cons, cons_rx_buf->data); + rxr->rx_prod =3D NEXT_RX(rxr->rx_prod); + cons_rx_buf->data =3D NULL; +} + +static void bnge_abort_tpa(struct bnge_cp_ring_info *cpr, u16 idx, u32 agg= _bufs) +{ + if (agg_bufs) + bnge_reuse_rx_agg_bufs(cpr, idx, 0, agg_bufs, true); +} + +static void bnge_tpa_agg(struct bnge_net *bn, struct bnge_rx_ring_info *rx= r, + struct rx_agg_cmp *rx_agg) +{ + u16 agg_id =3D TPA_AGG_AGG_ID(rx_agg); + struct bnge_tpa_info *tpa_info; + + agg_id =3D bnge_lookup_agg_idx(rxr, agg_id); + tpa_info =3D &rxr->rx_tpa[agg_id]; + BUG_ON(tpa_info->agg_count >=3D MAX_SKB_FRAGS); + tpa_info->agg_arr[tpa_info->agg_count++] =3D *rx_agg; +} + void bnge_reuse_rx_data(struct bnge_rx_ring_info *rxr, u16 cons, void *dat= a) { struct bnge_sw_rx_bd *cons_rx_buf, *prod_rx_buf; @@ -287,6 +456,208 @@ static struct sk_buff *bnge_copy_skb(struct bnge_napi= *bnapi, u8 *data, return skb; } =20 +#ifdef CONFIG_INET +static void bnge_gro_tunnel(struct sk_buff *skb, __be16 ip_proto) +{ + struct udphdr *uh =3D NULL; + + if (ip_proto =3D=3D htons(ETH_P_IP)) { + struct iphdr *iph =3D (struct iphdr *)skb->data; + + if (iph->protocol =3D=3D IPPROTO_UDP) + uh =3D (struct udphdr *)(iph + 1); + } else { + struct ipv6hdr *iph =3D (struct ipv6hdr *)skb->data; + + if (iph->nexthdr =3D=3D IPPROTO_UDP) + uh =3D (struct udphdr *)(iph + 1); + } + if (uh) { + if (uh->check) + skb_shinfo(skb)->gso_type |=3D SKB_GSO_UDP_TUNNEL_CSUM; + else + skb_shinfo(skb)->gso_type |=3D SKB_GSO_UDP_TUNNEL; + } +} + +static struct sk_buff *bnge_gro_func(struct bnge_tpa_info *tpa_info, + int payload_off, int tcp_ts, + struct sk_buff *skb) +{ + u16 outer_ip_off, inner_ip_off, inner_mac_off; + u32 hdr_info =3D tpa_info->hdr_info; + int iphdr_len, nw_off; + + inner_ip_off =3D BNGE_TPA_INNER_L3_OFF(hdr_info); + inner_mac_off =3D BNGE_TPA_INNER_L2_OFF(hdr_info); + outer_ip_off =3D BNGE_TPA_OUTER_L3_OFF(hdr_info); + + nw_off =3D inner_ip_off - ETH_HLEN; + skb_set_network_header(skb, nw_off); + iphdr_len =3D (tpa_info->flags2 & RX_TPA_START_CMP_FLAGS2_IP_TYPE) ? + sizeof(struct ipv6hdr) : sizeof(struct iphdr); + skb_set_transport_header(skb, nw_off + iphdr_len); + + if (inner_mac_off) { /* tunnel */ + __be16 proto =3D *((__be16 *)(skb->data + outer_ip_off - + ETH_HLEN - 2)); + + bnge_gro_tunnel(skb, proto); + } + + return skb; +} + +static inline struct sk_buff *bnge_gro_skb(struct bnge_net *bn, + struct bnge_tpa_info *tpa_info, + struct rx_tpa_end_cmp *tpa_end, + struct rx_tpa_end_cmp_ext *tpa_end1, + struct sk_buff *skb) +{ + int payload_off; + u16 segs; + + segs =3D TPA_END_TPA_SEGS(tpa_end); + if (segs =3D=3D 1) + return skb; + + NAPI_GRO_CB(skb)->count =3D segs; + skb_shinfo(skb)->gso_size =3D + le32_to_cpu(tpa_end1->rx_tpa_end_cmp_seg_len); + skb_shinfo(skb)->gso_type =3D tpa_info->gso_type; + payload_off =3D TPA_END_PAYLOAD_OFF(tpa_end1); + skb =3D bnge_gro_func(tpa_info, payload_off, + TPA_END_GRO_TS(tpa_end), skb); + if (likely(skb)) + tcp_gro_complete(skb); + + return skb; +} +#endif + +static inline struct sk_buff *bnge_tpa_end(struct bnge_net *bn, + struct bnge_cp_ring_info *cpr, + u32 *raw_cons, + struct rx_tpa_end_cmp *tpa_end, + struct rx_tpa_end_cmp_ext *tpa_end1, + u8 *event) +{ + struct bnge_napi *bnapi =3D cpr->bnapi; + struct net_device *dev =3D bn->netdev; + struct bnge_tpa_info *tpa_info; + struct bnge_rx_ring_info *rxr; + u8 *data_ptr, agg_bufs; + struct sk_buff *skb; + u16 idx =3D 0, agg_id; + dma_addr_t mapping; + unsigned int len; + void *data; + + rxr =3D bnapi->rx_ring; + agg_id =3D TPA_END_AGG_ID(tpa_end); + agg_id =3D bnge_lookup_agg_idx(rxr, agg_id); + agg_bufs =3D TPA_END_AGG_BUFS(tpa_end1); + tpa_info =3D &rxr->rx_tpa[agg_id]; + if (unlikely(agg_bufs !=3D tpa_info->agg_count)) { + netdev_warn(bn->netdev, "TPA end agg_buf %d !=3D expected agg_bufs %d\n", + agg_bufs, tpa_info->agg_count); + agg_bufs =3D tpa_info->agg_count; + } + tpa_info->agg_count =3D 0; + *event |=3D BNGE_AGG_EVENT; + bnge_free_agg_idx(rxr, agg_id); + idx =3D agg_id; + data =3D tpa_info->data; + data_ptr =3D tpa_info->data_ptr; + prefetch(data_ptr); + len =3D tpa_info->len; + mapping =3D tpa_info->mapping; + + if (unlikely(agg_bufs > MAX_SKB_FRAGS || TPA_END_ERRORS(tpa_end1))) { + bnge_abort_tpa(cpr, idx, agg_bufs); + if (agg_bufs > MAX_SKB_FRAGS) + netdev_warn(bn->netdev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n", + agg_bufs, (int)MAX_SKB_FRAGS); + return NULL; + } + + if (len <=3D bn->rx_copybreak) { + skb =3D bnge_copy_skb(bnapi, data_ptr, len, mapping); + if (!skb) { + bnge_abort_tpa(cpr, idx, agg_bufs); + return NULL; + } + } else { + u8 *new_data; + dma_addr_t new_mapping; + + new_data =3D __bnge_alloc_rx_frag(bn, &new_mapping, rxr, + GFP_ATOMIC); + if (!new_data) { + bnge_abort_tpa(cpr, idx, agg_bufs); + return NULL; + } + + tpa_info->data =3D new_data; + tpa_info->data_ptr =3D new_data + bn->rx_offset; + tpa_info->mapping =3D new_mapping; + + skb =3D napi_build_skb(data, bn->rx_buf_size); + dma_sync_single_for_cpu(bn->bd->dev, mapping, + bn->rx_buf_use_size, bn->rx_dir); + + if (!skb) { + page_pool_free_va(rxr->head_pool, data, true); + bnge_abort_tpa(cpr, idx, agg_bufs); + return NULL; + } + skb_mark_for_recycle(skb); + skb_reserve(skb, bn->rx_offset); + skb_put(skb, len); + } + + if (agg_bufs) { + skb =3D bnge_rx_agg_netmems_skb(bn, cpr, skb, idx, agg_bufs, + true); + /* Page reuse already handled by bnge_rx_agg_netmems_skb(). */ + if (!skb) + return NULL; + } + + skb->protocol =3D eth_type_trans(skb, dev); + + if (tpa_info->hash_type !=3D PKT_HASH_TYPE_NONE) + skb_set_hash(skb, tpa_info->rss_hash, tpa_info->hash_type); + + if (tpa_info->vlan_valid && + (dev->features & BNGE_HW_FEATURE_VLAN_ALL_RX)) { + __be16 vlan_proto =3D htons(tpa_info->metadata >> + RX_CMP_FLAGS2_METADATA_TPID_SFT); + u16 vtag =3D tpa_info->metadata & RX_CMP_FLAGS2_METADATA_TCI_MASK; + + if (eth_type_vlan(vlan_proto)) { + __vlan_hwaccel_put_tag(skb, vlan_proto, vtag); + } else { + dev_kfree_skb(skb); + return NULL; + } + } + + skb_checksum_none_assert(skb); + if (likely(tpa_info->flags2 & RX_TPA_START_CMP_FLAGS2_L4_CS_CALC)) { + skb->ip_summed =3D CHECKSUM_UNNECESSARY; + skb->csum_level =3D + (tpa_info->flags2 & RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3; + } + +#ifdef CONFIG_INET + if (bn->priv_flags & BNGE_NET_EN_GRO) + skb =3D bnge_gro_skb(bn, tpa_info, tpa_end, tpa_end1, skb); +#endif + + return skb; +} + static enum pkt_hash_types bnge_rss_ext_op(struct bnge_net *bn, struct rx_cmp *rxcmp) { @@ -380,6 +751,7 @@ static struct sk_buff *bnge_rx_skb(struct bnge_net *bn, =20 /* returns the following: * 1 - 1 packet successfully received + * 0 - successful TPA_START, packet not completed yet * -EBUSY - completion ring does not have all the agg buffers yet * -ENOMEM - packet aborted due to out of memory * -EIO - packet aborted due to hw error indicated in BD @@ -413,6 +785,11 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bng= e_cp_ring_info *cpr, =20 cmp_type =3D RX_CMP_TYPE(rxcmp); =20 + if (cmp_type =3D=3D CMP_TYPE_RX_TPA_AGG_CMP) { + bnge_tpa_agg(bn, rxr, (struct rx_agg_cmp *)rxcmp); + goto next_rx_no_prod_no_len; + } + tmp_raw_cons =3D NEXT_RAW_CMP(tmp_raw_cons); cp_cons =3D RING_CMP(bn, tmp_raw_cons); rxcmp1 =3D (struct rx_cmp_ext *) @@ -427,6 +804,32 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bng= e_cp_ring_info *cpr, dma_rmb(); prod =3D rxr->rx_prod; =20 + if (cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_START_CMP || + cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_START_V3_CMP) { + bnge_tpa_start(bn, rxr, cmp_type, + (struct rx_tpa_start_cmp *)rxcmp, + (struct rx_tpa_start_cmp_ext *)rxcmp1); + + *event |=3D BNGE_RX_EVENT; + goto next_rx_no_prod_no_len; + + } else if (cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_END_CMP) { + skb =3D bnge_tpa_end(bn, cpr, &tmp_raw_cons, + (struct rx_tpa_end_cmp *)rxcmp, + (struct rx_tpa_end_cmp_ext *)rxcmp1, event); + + if (IS_ERR(skb)) + return -EBUSY; + + rc =3D -ENOMEM; + if (likely(skb)) { + bnge_deliver_skb(bn, bnapi, skb); + rc =3D 1; + } + *event |=3D BNGE_RX_EVENT; + goto next_rx_no_prod_no_len; + } + cons =3D rxcmp->rx_cmp_opaque; if (unlikely(cons !=3D rxr->rx_next_cons)) { int rc1 =3D bnge_discard_rx(bn, cpr, &tmp_raw_cons, rxcmp); @@ -461,7 +864,8 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bnge= _cp_ring_info *cpr, if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L2_ERRORS) { bnge_reuse_rx_data(rxr, cons, data); if (agg_bufs) - bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, agg_bufs); + bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, agg_bufs, + false); rc =3D -EIO; goto next_rx_no_len; } @@ -476,7 +880,7 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bnge= _cp_ring_info *cpr, if (!skb) { if (agg_bufs) bnge_reuse_rx_agg_bufs(cpr, cp_cons, 0, - agg_bufs); + agg_bufs, false); goto oom_next_rx; } } else { @@ -494,7 +898,7 @@ static int bnge_rx_pkt(struct bnge_net *bn, struct bnge= _cp_ring_info *cpr, =20 if (agg_bufs) { skb =3D bnge_rx_agg_netmems_skb(bn, cpr, skb, cp_cons, - agg_bufs); + agg_bufs, false); if (!skb) goto oom_next_rx; } @@ -592,6 +996,12 @@ static int bnge_force_rx_discard(struct bnge_net *bn, cmp_type =3D=3D CMP_TYPE_RX_L2_V3_CMP) { rxcmp1->rx_cmp_cfa_code_errors_v2 |=3D cpu_to_le32(RX_CMPL_ERRORS_CRC_ERROR); + } else if (cmp_type =3D=3D CMP_TYPE_RX_L2_TPA_END_CMP) { + struct rx_tpa_end_cmp_ext *tpa_end1; + + tpa_end1 =3D (struct rx_tpa_end_cmp_ext *)rxcmp1; + tpa_end1->rx_tpa_end_cmp_errors_v2 |=3D + cpu_to_le32(RX_TPA_END_CMP_ERRORS); } rc =3D bnge_rx_pkt(bn, cpr, raw_cons, event); return rc; --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-io1-f98.google.com (mail-io1-f98.google.com [209.85.166.98]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CE56830E834 for ; Wed, 26 Nov 2025 19:50:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.98 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186648; cv=none; b=lLg2Hwz9m6coT5xVvW7heMlLFrlk12VtnPt/hj+oLu1HkAZgHeGmK7gSwkcD6WtvmZk2BNNd8zpDeGq2aXiGV4s3eLjLIwAHS15eH+x9KfOQ6yqsDG/gI27RoGr+Johz7ZlgDFNjsHur2hsk2Xc9S0G6QJ5wRO3XGIhulFekMO0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186648; c=relaxed/simple; bh=lHX500W4mSSKF2ULG32ABd7aw+ZTvBhjRQtKveb9heE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PLpADy0+BDnf6Y5WvgTTR5lZSLUqEGd1i4CvgUcMqN2drRECmRNd7fJEBeaVL89KlFab4pv5CBmw7MqAOdPaoABGVuEU7yMxLtEM9803qHGNYrXG3A8itdwL+l40VYg0qG6IYM4u8F06sln2c2jenkyZNzOh10/bWBalJgvFhm8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=fwZNF85D; arc=none smtp.client-ip=209.85.166.98 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="fwZNF85D" Received: by mail-io1-f98.google.com with SMTP id ca18e2360f4ac-94905c3e2a4so55498839f.1 for ; Wed, 26 Nov 2025 11:50:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186645; x=1764791445; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=SNTtB9FFKYiyl7JpYMgCteErn1EGaQmPvKyEw6vZfnU=; b=abKLeGxD/z5J20FjllLyKqJnd4HbYGQm/KbrHTaC5bFNKlxqegZfPuIlrsUBmvhAvQ MRtTjm1u6nsjUAWEDK7MH81C12pBj1SpxahRqs7iVr0G+L3TC8WRuMFavEDJPNXUdcH7 PiYGIAa0JVzJ4JXVqM9tRyWiGCXDDYKCP0eBhyX/ub0WaJSlQ3pSvsYdCGZLp1WCoj7s T5BwHC4/lDc7hNNATrKCIXG4WQzmVtbjuspy1f80u2nN0ZRyG/KMPshB4uztbeB7n7Vt tmRMfXZbO4MdVYcsSx9mMme4tMedMSU+qyq8/6X93If0FMYJAihLkH1db2gz5mdfKCZa J+tQ== X-Forwarded-Encrypted: i=1; AJvYcCX4A8X5fJZoN/ukWJkmQfONRla1Qv0bQDI9pxaoNhu/RrZySHKPC1D2orRRulqkT7c2VG03ejG23VM2878=@vger.kernel.org X-Gm-Message-State: AOJu0YxU+t86eNBC0vtlKDUptMkX3pXC1t/fMnQXQ0T5mjrO17ih8i50 /SzEekHRPspZG+PFxjxcQZT5uKe/NclTCh0sst1WZo8r5jWQwm+kqEyTPG+rnOljqAqawtacZdo buYOjOWi0+nZVg5l6tNKupDJrgH+X4vGH8AJeJv7HGc8DB1V35oHLVwQMqsJ0ta97IMXazwOgsG pNt1vUj3XTM0PP9U/0EUelqFJLMQMPvtocvGtCcg9F1Sn3xOzYQ6PID0I5P0xW/EPQVnZ/naBf0 x7zgghLiubHjP7U4zsY7koCf7rV X-Gm-Gg: ASbGnctnHKhyvrVFq5q6bbP9GeD9R/ZmqXb4EHKAgfSceilfslhD3s1HVs0ABuw3DKW aq4OSgPacHWkwPmDLPt55dh+qUnRozE2022wct2lHKyg4w4/WLQMdJWrUgqhFFc1nzxrlEXMCHJ q33Abk7/4HwqHgtRFOEEXwHe+QnkKUh5+qHznXUfz/rS4iUOyB9iKqr7UnJ2uUR1O99hkgHsgQn KqSiVVlyxy5OdoVror3FJ0VU2JEDlvMblX8zCFT/xeYDoA638E1GHoaIs1YMK9EXSP7zFlOZWgA JJMi6HxdZu2MeOriAvzYeWbEby9QZjDAfKy1R+jXBnjCPUwz6O+Wvmzufl1BPnHaIwoaGcxknyz dZsWp0QWe3NNASDzSvJ+E1b+EfCYwF5j+t2dwuyb+b0MS5xHARJoUSpJ1fokjqSLF7y9S9OIxyD RO+pNjqMbSA78CvFXR7/WJ0h0TBm8E07/s7+mhGaL4e09a3EDrNd0= X-Google-Smtp-Source: AGHT+IE7q0hJ3lO2jkuCVs7JWKSy/YFskG9BSs+oqtbLUL4z2c2KtatSENAtVB0PnxKlj4n1wusKuJfgsECN X-Received: by 2002:a02:c8d5:0:b0:5b7:1b3a:b998 with SMTP id 8926c6da1cb9f-5b9567d00dcmr12222856173.5.1764186644712; Wed, 26 Nov 2025 11:50:44 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-11.dlp.protect.broadcom.com. [144.49.247.11]) by smtp-relay.gmail.com with ESMTPS id 8926c6da1cb9f-5b954b16f1bsm1891374173.25.2025.11.26.11.50.44 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:44 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f198.google.com with SMTP id d9443c01a7336-2955f0b8895so11106565ad.0 for ; Wed, 26 Nov 2025 11:50:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186643; x=1764791443; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=SNTtB9FFKYiyl7JpYMgCteErn1EGaQmPvKyEw6vZfnU=; b=fwZNF85DYXKlOoejxeT1qiA3y26vZFw7LDS099G2gQFwOMEd2GSnpARVqp0fkG4cKB lY1J36yqydKLBPk6BomZkJRT8N+rHrSfyev9U7Q0SI7Ic8qd2mFFfOlD6fiBmfbBYNRq ambSEQOwaLom9YTyqnoWnbuwToit9P/l2rixw= X-Forwarded-Encrypted: i=1; AJvYcCXAKB3H9AfAF/OLWUr0eXdRlRGg3ZVPaZzhBO4gQRERLAb0oNLyTAi64iFj9NnyEy20+LxyCah+xIxn9ks=@vger.kernel.org X-Received: by 2002:a17:903:2acd:b0:299:bda7:ae45 with SMTP id d9443c01a7336-29b5e3b884dmr240828535ad.25.1764186642821; Wed, 26 Nov 2025 11:50:42 -0800 (PST) X-Received: by 2002:a17:903:2acd:b0:299:bda7:ae45 with SMTP id d9443c01a7336-29b5e3b884dmr240828255ad.25.1764186642310; Wed, 26 Nov 2025 11:50:42 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:41 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 09/12] bng_en: Add ethtool link settings and capabilities support Date: Thu, 27 Nov 2025 01:19:28 +0530 Message-ID: <20251126194931.455830-10-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Adds ethtool ops to query and configure link speed, duplex, autoneg, report link status, and advertise lane support. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- drivers/net/ethernet/broadcom/bnge/bnge.h | 2 + .../net/ethernet/broadcom/bnge/bnge_ethtool.c | 25 + .../net/ethernet/broadcom/bnge/bnge_link.c | 838 ++++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_link.h | 6 + 4 files changed, 871 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethern= et/broadcom/bnge/bnge.h index 68c13520a95..72d9865ba7b 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h @@ -224,6 +224,8 @@ struct bnge_dev { #define BNGE_PHY_FL_NO_FCS PORT_PHY_QCAPS_RESP_FLAGS_NO_FCS #define BNGE_PHY_FL_SPEEDS2 \ (PORT_PHY_QCAPS_RESP_FLAGS2_SPEEDS2_SUPPORTED << 8) +#define BNGE_PHY_FL_NO_PAUSE \ + (PORT_PHY_QCAPS_RESP_FLAGS2_PAUSE_UNSUPPORTED << 8) =20 u32 msg_enable; }; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c b/drivers/ne= t/ethernet/broadcom/bnge/bnge_ethtool.c index 569371c1b4f..b985799051b 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c @@ -11,6 +11,26 @@ =20 #include "bnge.h" #include "bnge_ethtool.h" +#include "bnge_hwrm_lib.h" + +static int bnge_nway_reset(struct net_device *dev) +{ + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_dev *bd =3D bn->bd; + int rc =3D 0; + + if (!BNGE_PHY_CFG_ABLE(bd)) + return -EOPNOTSUPP; + + if (!(bn->eth_link_info.autoneg & BNGE_AUTONEG_SPEED)) + return -EINVAL; + + if (netif_running(dev)) + rc =3D bnge_hwrm_set_link_setting(bn, true); + + return rc; +} + =20 static void bnge_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) @@ -24,7 +44,12 @@ static void bnge_get_drvinfo(struct net_device *dev, } =20 static const struct ethtool_ops bnge_ethtool_ops =3D { + .cap_link_lanes_supported =3D 1, + .get_link_ksettings =3D bnge_get_link_ksettings, + .set_link_ksettings =3D bnge_set_link_ksettings, .get_drvinfo =3D bnge_get_drvinfo, + .get_link =3D bnge_get_link, + .nway_reset =3D bnge_nway_reset, }; =20 void bnge_set_ethtool_ops(struct net_device *dev) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.c b/drivers/net/e= thernet/broadcom/bnge/bnge_link.c index 02deb38d81d..6dd741d3461 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_link.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.c @@ -7,6 +7,63 @@ #include "bnge_link.h" #include "bnge_hwrm_lib.h" =20 +enum bnge_media_type { + BNGE_MEDIA_UNKNOWN =3D 0, + BNGE_MEDIA_TP, + BNGE_MEDIA_CR, + BNGE_MEDIA_SR, + BNGE_MEDIA_LR_ER_FR, + BNGE_MEDIA_KR, + BNGE_MEDIA_KX, + BNGE_MEDIA_X, + __BNGE_MEDIA_END, +}; + +static const enum bnge_media_type bnge_phy_types[] =3D { + [PORT_PHY_QCFG_RESP_PHY_TYPE_BASECR] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR4] =3D BNGE_MEDIA_KR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_BASELR] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_BASESR] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR2] =3D BNGE_MEDIA_KR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKX] =3D BNGE_MEDIA_KX, + [PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR] =3D BNGE_MEDIA_KR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_BASET] =3D BNGE_MEDIA_TP, + [PORT_PHY_QCFG_RESP_PHY_TYPE_BASETE] =3D BNGE_MEDIA_TP, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR4] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR4] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR4] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER4] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR10] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASECR4] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASESR4] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASELR4] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASEER4] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASECR] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASESR] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASELR] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASEER] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR2] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR2] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR2] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER2] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASECR2] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASESR2] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASELR2] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASEER2] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASECR8] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASESR8] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASELR8] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASEER8] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASECR4] =3D BNGE_MEDIA_CR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASESR4] =3D BNGE_MEDIA_SR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASELR4] =3D BNGE_MEDIA_LR_ER_FR, + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASEER4] =3D BNGE_MEDIA_LR_ER_FR, +}; + u32 bnge_fw_to_ethtool_speed(u16 fw_link_speed) { switch (fw_link_speed) { @@ -485,3 +542,784 @@ void bnge_report_link(struct bnge_dev *bd) netdev_err(bd->netdev, "NIC Link is Down\n"); } } + +static void bnge_get_ethtool_modes(struct bnge_net *bn, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct bnge_ethtool_link_info *elink_info; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + elink_info =3D &bn->eth_link_info; + link_info =3D &bd->link_info; + + if (!(bd->phy_flags & BNGE_PHY_FL_NO_PAUSE)) { + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, + lk_ksettings->link_modes.supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + lk_ksettings->link_modes.supported); + } + + if (link_info->support_auto_speeds || link_info->support_auto_speeds2 || + link_info->support_pam4_auto_speeds) + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + lk_ksettings->link_modes.supported); + + if (~elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) + return; + + if (link_info->auto_pause_setting & BNGE_LINK_PAUSE_RX) + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, + lk_ksettings->link_modes.advertising); + if (hweight8(link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH) =3D=3D= 1) + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + lk_ksettings->link_modes.advertising); + if (link_info->lp_pause & BNGE_LINK_PAUSE_RX) + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, + lk_ksettings->link_modes.lp_advertising); + if (hweight8(link_info->lp_pause & BNGE_LINK_PAUSE_BOTH) =3D=3D 1) + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + lk_ksettings->link_modes.lp_advertising); +} + +u32 bnge_get_link(struct net_device *dev) +{ + struct bnge_net *bn =3D netdev_priv(dev); + + /* TODO: handle MF, VF, driver close case */ + return BNGE_LINK_IS_UP(bn->bd); +} + +static enum bnge_media_type +bnge_get_media(struct bnge_link_info *link_info) +{ + switch (link_info->media_type) { + case PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP: + return BNGE_MEDIA_TP; + case PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC: + return BNGE_MEDIA_CR; + default: + if (link_info->phy_type < ARRAY_SIZE(bnge_phy_types)) + return bnge_phy_types[link_info->phy_type]; + return BNGE_MEDIA_UNKNOWN; + } +} + +enum bnge_link_speed_indices { + BNGE_LINK_SPEED_UNKNOWN =3D 0, + BNGE_LINK_SPEED_50GB_IDX, + BNGE_LINK_SPEED_100GB_IDX, + BNGE_LINK_SPEED_200GB_IDX, + BNGE_LINK_SPEED_400GB_IDX, + BNGE_LINK_SPEED_800GB_IDX, + __BNGE_LINK_SPEED_END +}; + +static enum bnge_link_speed_indices bnge_fw_speed_idx(u16 speed) +{ + switch (speed) { + case BNGE_LINK_SPEED_50GB: + case BNGE_LINK_SPEED_50GB_PAM4: + return BNGE_LINK_SPEED_50GB_IDX; + case BNGE_LINK_SPEED_100GB: + case BNGE_LINK_SPEED_100GB_PAM4: + case BNGE_LINK_SPEED_100GB_PAM4_112: + return BNGE_LINK_SPEED_100GB_IDX; + case BNGE_LINK_SPEED_200GB: + case BNGE_LINK_SPEED_200GB_PAM4: + case BNGE_LINK_SPEED_200GB_PAM4_112: + return BNGE_LINK_SPEED_200GB_IDX; + case BNGE_LINK_SPEED_400GB: + case BNGE_LINK_SPEED_400GB_PAM4: + case BNGE_LINK_SPEED_400GB_PAM4_112: + return BNGE_LINK_SPEED_400GB_IDX; + case BNGE_LINK_SPEED_800GB: + case BNGE_LINK_SPEED_800GB_PAM4_112: + return BNGE_LINK_SPEED_800GB_IDX; + default: return BNGE_LINK_SPEED_UNKNOWN; + } +} + +static const enum ethtool_link_mode_bit_indices +bnge_link_modes[__BNGE_LINK_SPEED_END][BNGE_SIG_MODE_MAX][__BNGE_MEDIA_END= ] =3D { + [BNGE_LINK_SPEED_50GB_IDX] =3D { + [BNGE_SIG_MODE_PAM4] =3D { + [BNGE_MEDIA_CR] =3D ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, + [BNGE_MEDIA_SR] =3D ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, + [BNGE_MEDIA_LR_ER_FR] =3D ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, + [BNGE_MEDIA_KR] =3D ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, + }, + }, + [BNGE_LINK_SPEED_100GB_IDX] =3D { + [BNGE_SIG_MODE_NRZ] =3D { + [BNGE_MEDIA_CR] =3D ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, + [BNGE_MEDIA_SR] =3D ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, + [BNGE_MEDIA_LR_ER_FR] =3D ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, + [BNGE_MEDIA_KR] =3D ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, + }, + [BNGE_SIG_MODE_PAM4] =3D { + [BNGE_MEDIA_CR] =3D ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, + [BNGE_MEDIA_SR] =3D ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, + [BNGE_MEDIA_LR_ER_FR] =3D ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_= BIT, + [BNGE_MEDIA_KR] =3D ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, + }, + [BNGE_SIG_MODE_PAM4_112] =3D { + [BNGE_MEDIA_CR] =3D ETHTOOL_LINK_MODE_100000baseCR_Full_BIT, + [BNGE_MEDIA_SR] =3D ETHTOOL_LINK_MODE_100000baseSR_Full_BIT, + [BNGE_MEDIA_KR] =3D ETHTOOL_LINK_MODE_100000baseKR_Full_BIT, + [BNGE_MEDIA_LR_ER_FR] =3D ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT, + }, + }, + [BNGE_LINK_SPEED_200GB_IDX] =3D { + [BNGE_SIG_MODE_PAM4] =3D { + [BNGE_MEDIA_CR] =3D ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, + [BNGE_MEDIA_SR] =3D ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, + [BNGE_MEDIA_LR_ER_FR] =3D ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_= BIT, + [BNGE_MEDIA_KR] =3D ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, + }, + [BNGE_SIG_MODE_PAM4_112] =3D { + [BNGE_MEDIA_CR] =3D ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT, + [BNGE_MEDIA_KR] =3D ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT, + [BNGE_MEDIA_SR] =3D ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, + [BNGE_MEDIA_LR_ER_FR] =3D ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_= BIT, + }, + }, + [BNGE_LINK_SPEED_400GB_IDX] =3D { + [BNGE_SIG_MODE_PAM4] =3D { + [BNGE_MEDIA_CR] =3D ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT, + [BNGE_MEDIA_KR] =3D ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT, + [BNGE_MEDIA_SR] =3D ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT, + [BNGE_MEDIA_LR_ER_FR] =3D ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_= BIT, + }, + [BNGE_SIG_MODE_PAM4_112] =3D { + [BNGE_MEDIA_CR] =3D ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT, + [BNGE_MEDIA_KR] =3D ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT, + [BNGE_MEDIA_SR] =3D ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT, + [BNGE_MEDIA_LR_ER_FR] =3D ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_= BIT, + }, + }, + [BNGE_LINK_SPEED_800GB_IDX] =3D { + [BNGE_SIG_MODE_PAM4_112] =3D { + [BNGE_MEDIA_CR] =3D ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT, + [BNGE_MEDIA_KR] =3D ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT, + [BNGE_MEDIA_SR] =3D ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT, + }, + }, +}; + +#define BNGE_LINK_MODE_UNKNOWN -1 + +static enum ethtool_link_mode_bit_indices +bnge_get_link_mode(struct bnge_net *bn) +{ + enum ethtool_link_mode_bit_indices link_mode; + struct bnge_ethtool_link_info *elink_info; + enum bnge_link_speed_indices speed; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + enum bnge_media_type media; + u8 sig_mode; + + elink_info =3D &bn->eth_link_info; + link_info =3D &bd->link_info; + + if (link_info->phy_link_status !=3D BNGE_LINK_LINK) + return BNGE_LINK_MODE_UNKNOWN; + + media =3D bnge_get_media(link_info); + if (BNGE_AUTO_MODE(link_info->auto_mode)) { + speed =3D bnge_fw_speed_idx(link_info->link_speed); + sig_mode =3D link_info->active_fec_sig_mode & + PORT_PHY_QCFG_RESP_SIGNAL_MODE_MASK; + } else { + speed =3D bnge_fw_speed_idx(elink_info->req_link_speed); + sig_mode =3D elink_info->req_signal_mode; + } + if (sig_mode >=3D BNGE_SIG_MODE_MAX) + return BNGE_LINK_MODE_UNKNOWN; + + /* Since ETHTOOL_LINK_MODE_10baseT_Half_BIT is defined as 0 and + * not actually supported, the zeroes in this map can be safely + * used to represent unknown link modes. + */ + link_mode =3D bnge_link_modes[speed][sig_mode][media]; + if (!link_mode) + return BNGE_LINK_MODE_UNKNOWN; + + switch (link_mode) { + case ETHTOOL_LINK_MODE_100baseT_Full_BIT: + if (~link_info->duplex & BNGE_LINK_DUPLEX_FULL) + link_mode =3D ETHTOOL_LINK_MODE_100baseT_Half_BIT; + break; + case ETHTOOL_LINK_MODE_1000baseT_Full_BIT: + if (~link_info->duplex & BNGE_LINK_DUPLEX_FULL) + link_mode =3D ETHTOOL_LINK_MODE_1000baseT_Half_BIT; + break; + default: + break; + } + + return link_mode; +} + +static const u16 bnge_nrz_speed_masks[] =3D { + [BNGE_LINK_SPEED_100GB_IDX] =3D BNGE_LINK_SPEED_MSK_100GB, + [__BNGE_LINK_SPEED_END - 1] =3D 0 /* make any legal speed a valid index */ +}; + +static const u16 bnge_pam4_speed_masks[] =3D { + [BNGE_LINK_SPEED_50GB_IDX] =3D BNGE_LINK_PAM4_SPEED_MSK_50GB, + [BNGE_LINK_SPEED_100GB_IDX] =3D BNGE_LINK_PAM4_SPEED_MSK_100GB, + [BNGE_LINK_SPEED_200GB_IDX] =3D BNGE_LINK_PAM4_SPEED_MSK_200GB, + [__BNGE_LINK_SPEED_END - 1] =3D 0 /* make any legal speed a valid index */ +}; + +static const u16 bnge_nrz_speeds2_masks[] =3D { + [BNGE_LINK_SPEED_100GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_100GB, + [__BNGE_LINK_SPEED_END - 1] =3D 0 /* make any legal speed a valid index */ +}; + +static const u16 bnge_pam4_speeds2_masks[] =3D { + [BNGE_LINK_SPEED_50GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_50GB_PAM4, + [BNGE_LINK_SPEED_100GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_100GB_PAM4, + [BNGE_LINK_SPEED_200GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_200GB_PAM4, + [BNGE_LINK_SPEED_400GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_400GB_PAM4, +}; + +static const u16 bnge_pam4_112_speeds2_masks[] =3D { + [BNGE_LINK_SPEED_100GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_100GB_PAM4_112, + [BNGE_LINK_SPEED_200GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_200GB_PAM4_112, + [BNGE_LINK_SPEED_400GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_400GB_PAM4_112, + [BNGE_LINK_SPEED_800GB_IDX] =3D BNGE_LINK_SPEEDS2_MSK_800GB_PAM4_112, +}; + +static enum bnge_link_speed_indices +bnge_encoding_speed_idx(u8 sig_mode, u16 phy_flags, u16 speed_msk) +{ + const u16 *speeds; + int idx, len; + + switch (sig_mode) { + case BNGE_SIG_MODE_NRZ: + if (phy_flags & BNGE_PHY_FL_SPEEDS2) { + speeds =3D bnge_nrz_speeds2_masks; + len =3D ARRAY_SIZE(bnge_nrz_speeds2_masks); + } else { + speeds =3D bnge_nrz_speed_masks; + len =3D ARRAY_SIZE(bnge_nrz_speed_masks); + } + break; + case BNGE_SIG_MODE_PAM4: + if (phy_flags & BNGE_PHY_FL_SPEEDS2) { + speeds =3D bnge_pam4_speeds2_masks; + len =3D ARRAY_SIZE(bnge_pam4_speeds2_masks); + } else { + speeds =3D bnge_pam4_speed_masks; + len =3D ARRAY_SIZE(bnge_pam4_speed_masks); + } + break; + case BNGE_SIG_MODE_PAM4_112: + speeds =3D bnge_pam4_112_speeds2_masks; + len =3D ARRAY_SIZE(bnge_pam4_112_speeds2_masks); + break; + default: + return BNGE_LINK_SPEED_UNKNOWN; + } + + for (idx =3D 0; idx < len; idx++) { + if (speeds[idx] =3D=3D speed_msk) + return idx; + } + + return BNGE_LINK_SPEED_UNKNOWN; +} + +#define BNGE_FW_SPEED_MSK_BITS 16 + +static void +__bnge_get_ethtool_speeds(unsigned long fw_mask, enum bnge_media_type medi= a, + u8 sig_mode, u16 phy_flags, unsigned long *et_mask) +{ + enum ethtool_link_mode_bit_indices link_mode; + enum bnge_link_speed_indices speed; + u8 bit; + + for_each_set_bit(bit, &fw_mask, BNGE_FW_SPEED_MSK_BITS) { + speed =3D bnge_encoding_speed_idx(sig_mode, phy_flags, 1 << bit); + if (!speed) + continue; + + link_mode =3D bnge_link_modes[speed][sig_mode][media]; + if (!link_mode) + continue; + + linkmode_set_bit(link_mode, et_mask); + } +} + +static void +bnge_get_ethtool_speeds(unsigned long fw_mask, enum bnge_media_type media, + u8 sig_mode, u16 phy_flags, unsigned long *et_mask) +{ + if (media) { + __bnge_get_ethtool_speeds(fw_mask, media, sig_mode, phy_flags, + et_mask); + return; + } + + /* list speeds for all media if unknown */ + for (media =3D 1; media < __BNGE_MEDIA_END; media++) + __bnge_get_ethtool_speeds(fw_mask, media, sig_mode, phy_flags, + et_mask); +} + +static void +bnge_get_all_ethtool_support_speeds(struct bnge_dev *bd, + enum bnge_media_type media, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct bnge_link_info *link_info =3D &bd->link_info; + u16 sp_nrz, sp_pam4, sp_pam4_112 =3D 0; + u16 phy_flags =3D bd->phy_flags; + + if (phy_flags & BNGE_PHY_FL_SPEEDS2) { + sp_nrz =3D link_info->support_speeds2; + sp_pam4 =3D link_info->support_speeds2; + sp_pam4_112 =3D link_info->support_speeds2; + } else { + sp_nrz =3D link_info->support_speeds; + sp_pam4 =3D link_info->support_pam4_speeds; + } + bnge_get_ethtool_speeds(sp_nrz, media, BNGE_SIG_MODE_NRZ, phy_flags, + lk_ksettings->link_modes.supported); + bnge_get_ethtool_speeds(sp_pam4, media, BNGE_SIG_MODE_PAM4, phy_flags, + lk_ksettings->link_modes.supported); + bnge_get_ethtool_speeds(sp_pam4_112, media, BNGE_SIG_MODE_PAM4_112, + phy_flags, lk_ksettings->link_modes.supported); +} + +static void +bnge_get_all_ethtool_adv_speeds(struct bnge_net *bn, + enum bnge_media_type media, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + u16 sp_nrz, sp_pam4, sp_pam4_112 =3D 0; + struct bnge_dev *bd =3D bn->bd; + u16 phy_flags; + + phy_flags =3D bd->phy_flags; + sp_nrz =3D elink_info->advertising; + + if (phy_flags & BNGE_PHY_FL_SPEEDS2) { + sp_pam4 =3D elink_info->advertising; + sp_pam4_112 =3D elink_info->advertising; + } else { + sp_pam4 =3D elink_info->advertising_pam4; + } + bnge_get_ethtool_speeds(sp_nrz, media, BNGE_SIG_MODE_NRZ, phy_flags, + lk_ksettings->link_modes.advertising); + bnge_get_ethtool_speeds(sp_pam4, media, BNGE_SIG_MODE_PAM4, phy_flags, + lk_ksettings->link_modes.advertising); + bnge_get_ethtool_speeds(sp_pam4_112, media, BNGE_SIG_MODE_PAM4_112, + phy_flags, lk_ksettings->link_modes.advertising); +} + +static void +bnge_get_all_ethtool_lp_speeds(struct bnge_dev *bd, + enum bnge_media_type media, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct bnge_link_info *link_info =3D &bd->link_info; + u16 phy_flags =3D bd->phy_flags; + + bnge_get_ethtool_speeds(link_info->lp_auto_link_speeds, media, + BNGE_SIG_MODE_NRZ, phy_flags, + lk_ksettings->link_modes.lp_advertising); + bnge_get_ethtool_speeds(link_info->lp_auto_pam4_link_speeds, media, + BNGE_SIG_MODE_PAM4, phy_flags, + lk_ksettings->link_modes.lp_advertising); +} + +static void bnge_update_speed(u32 *delta, bool installed_media, u16 *speed= s, + u16 speed_msk, const unsigned long *et_mask, + enum ethtool_link_mode_bit_indices mode) +{ + bool mode_desired =3D linkmode_test_bit(mode, et_mask); + + if (!mode) + return; + + /* enabled speeds for installed media should override */ + if (installed_media && mode_desired) { + *speeds |=3D speed_msk; + *delta |=3D speed_msk; + return; + } + + /* many to one mapping, only allow one change per fw_speed bit */ + if (!(*delta & speed_msk) && (mode_desired =3D=3D !(*speeds & speed_msk))= ) { + *speeds ^=3D speed_msk; + *delta |=3D speed_msk; + } +} + +static void bnge_set_ethtool_speeds(struct bnge_net *bn, + const unsigned long *et_mask) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + u16 const *sp_msks, *sp_pam4_msks, *sp_pam4_112_msks; + u16 *adv, *adv_pam4, *adv_pam4_112 =3D NULL; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + enum bnge_media_type media; + u32 delta_pam4_112 =3D 0; + u32 delta_pam4 =3D 0; + u32 delta_nrz =3D 0; + int i, m; + + link_info =3D &bd->link_info; + media =3D bnge_get_media(link_info); + adv =3D &elink_info->advertising; + + if (bd->phy_flags & BNGE_PHY_FL_SPEEDS2) { + adv_pam4 =3D &elink_info->advertising; + adv_pam4_112 =3D &elink_info->advertising; + sp_msks =3D bnge_nrz_speeds2_masks; + sp_pam4_msks =3D bnge_pam4_speeds2_masks; + sp_pam4_112_msks =3D bnge_pam4_112_speeds2_masks; + } else { + adv_pam4 =3D &elink_info->advertising_pam4; + sp_msks =3D bnge_nrz_speed_masks; + sp_pam4_msks =3D bnge_pam4_speed_masks; + } + for (i =3D 1; i < __BNGE_LINK_SPEED_END; i++) { + /* accept any legal media from user */ + for (m =3D 1; m < __BNGE_MEDIA_END; m++) { + bnge_update_speed(&delta_nrz, m =3D=3D media, + adv, sp_msks[i], et_mask, + bnge_link_modes[i][BNGE_SIG_MODE_NRZ][m]); + bnge_update_speed(&delta_pam4, m =3D=3D media, + adv_pam4, sp_pam4_msks[i], et_mask, + bnge_link_modes[i][BNGE_SIG_MODE_PAM4][m]); + if (!adv_pam4_112) + continue; + + bnge_update_speed(&delta_pam4_112, m =3D=3D media, + adv_pam4_112, sp_pam4_112_msks[i], et_mask, + bnge_link_modes[i][BNGE_SIG_MODE_PAM4_112][m]); + } + } +} + +static void +bnge_fw_to_ethtool_advertised_fec(struct bnge_link_info *link_info, + struct ethtool_link_ksettings *lk_ksettings) +{ + u16 fec_cfg =3D link_info->fec_cfg; + + if ((fec_cfg & BNGE_FEC_NONE) || !(fec_cfg & BNGE_FEC_AUTONEG)) { + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, + lk_ksettings->link_modes.advertising); + return; + } + if (fec_cfg & BNGE_FEC_ENC_BASE_R) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT, + lk_ksettings->link_modes.advertising); + if (fec_cfg & BNGE_FEC_ENC_RS) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT, + lk_ksettings->link_modes.advertising); + if (fec_cfg & BNGE_FEC_ENC_LLRS) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_LLRS_BIT, + lk_ksettings->link_modes.advertising); +} + +static void +bnge_fw_to_ethtool_support_fec(struct bnge_link_info *link_info, + struct ethtool_link_ksettings *lk_ksettings) +{ + u16 fec_cfg =3D link_info->fec_cfg; + + if (fec_cfg & BNGE_FEC_NONE) { + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, + lk_ksettings->link_modes.supported); + return; + } + if (fec_cfg & BNGE_FEC_ENC_BASE_R_CAP) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT, + lk_ksettings->link_modes.supported); + if (fec_cfg & BNGE_FEC_ENC_RS_CAP) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT, + lk_ksettings->link_modes.supported); + if (fec_cfg & BNGE_FEC_ENC_LLRS_CAP) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_LLRS_BIT, + lk_ksettings->link_modes.supported); +} + +static void bnge_get_default_speeds(struct bnge_net *bn, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct bnge_ethtool_link_info *elink_info =3D &bn->eth_link_info; + struct ethtool_link_settings *base =3D &lk_ksettings->base; + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + + link_info =3D &bd->link_info; + + if (link_info->link_state =3D=3D BNGE_LINK_STATE_UP) { + base->speed =3D bnge_fw_to_ethtool_speed(link_info->link_speed); + base->duplex =3D DUPLEX_HALF; + if (link_info->duplex & BNGE_LINK_DUPLEX_FULL) + base->duplex =3D DUPLEX_FULL; + lk_ksettings->lanes =3D link_info->active_lanes; + } else if (!elink_info->autoneg) { + base->speed =3D bnge_fw_to_ethtool_speed(elink_info->req_link_speed); + base->duplex =3D DUPLEX_HALF; + if (elink_info->req_duplex =3D=3D BNGE_LINK_DUPLEX_FULL) + base->duplex =3D DUPLEX_FULL; + } +} + +int bnge_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *lk_ksettings) +{ + struct ethtool_link_settings *base =3D &lk_ksettings->base; + enum ethtool_link_mode_bit_indices link_mode; + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + enum bnge_media_type media; + + ethtool_link_ksettings_zero_link_mode(lk_ksettings, lp_advertising); + ethtool_link_ksettings_zero_link_mode(lk_ksettings, advertising); + ethtool_link_ksettings_zero_link_mode(lk_ksettings, supported); + base->duplex =3D DUPLEX_UNKNOWN; + base->speed =3D SPEED_UNKNOWN; + link_info =3D &bd->link_info; + + mutex_lock(&bd->link_lock); + bnge_get_ethtool_modes(bn, lk_ksettings); + media =3D bnge_get_media(link_info); + bnge_get_all_ethtool_support_speeds(bd, media, lk_ksettings); + bnge_fw_to_ethtool_support_fec(link_info, lk_ksettings); + link_mode =3D bnge_get_link_mode(bn); + if (link_mode !=3D BNGE_LINK_MODE_UNKNOWN) + ethtool_params_from_link_mode(lk_ksettings, link_mode); + else + bnge_get_default_speeds(bn, lk_ksettings); + + if (bn->eth_link_info.autoneg) { + bnge_fw_to_ethtool_advertised_fec(link_info, lk_ksettings); + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + lk_ksettings->link_modes.advertising); + base->autoneg =3D AUTONEG_ENABLE; + bnge_get_all_ethtool_adv_speeds(bn, media, lk_ksettings); + if (link_info->phy_link_status =3D=3D BNGE_LINK_LINK) + bnge_get_all_ethtool_lp_speeds(bd, media, lk_ksettings); + } else { + base->autoneg =3D AUTONEG_DISABLE; + } + + base->port =3D PORT_NONE; + if (link_info->media_type =3D=3D PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) { + base->port =3D PORT_TP; + linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, + lk_ksettings->link_modes.supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, + lk_ksettings->link_modes.advertising); + } else { + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, + lk_ksettings->link_modes.supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, + lk_ksettings->link_modes.advertising); + + if (link_info->media_type =3D=3D PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC) + base->port =3D PORT_DA; + else + base->port =3D PORT_FIBRE; + } + base->phy_address =3D link_info->phy_addr; + mutex_unlock(&bd->link_lock); + + return 0; +} + +static int +bnge_force_link_speed(struct net_device *dev, u32 ethtool_speed, u32 lanes) +{ + u16 support_pam4_spds, support_spds2, support_spds; + struct bnge_ethtool_link_info *elink_info; + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_link_info *link_info; + u8 sig_mode =3D BNGE_SIG_MODE_NRZ; + struct bnge_dev *bd =3D bn->bd; + u32 lanes_needed =3D 1; + u16 fw_speed =3D 0; + + elink_info =3D &bn->eth_link_info; + link_info =3D &bd->link_info; + support_pam4_spds =3D link_info->support_pam4_speeds; + support_spds2 =3D link_info->support_speeds2; + support_spds =3D link_info->support_speeds; + + switch (ethtool_speed) { + case SPEED_50000: + if (((support_spds & BNGE_LINK_SPEED_MSK_50GB) || + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_50GB)) && + lanes !=3D 1) { + fw_speed =3D PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_50GB; + lanes_needed =3D 2; + } else if (support_pam4_spds & BNGE_LINK_PAM4_SPEED_MSK_50GB) { + fw_speed =3D PORT_PHY_CFG_REQ_FORCE_PAM4_LINK_SPEED_50GB; + sig_mode =3D BNGE_SIG_MODE_PAM4; + } else if (support_spds2 & BNGE_LINK_SPEEDS2_MSK_50GB_PAM4) { + fw_speed =3D BNGE_LINK_SPEED_50GB_PAM4; + sig_mode =3D BNGE_SIG_MODE_PAM4; + } + break; + case SPEED_100000: + if (((support_spds & BNGE_LINK_SPEED_MSK_100GB) || + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_100GB)) && + lanes !=3D 2 && lanes !=3D 1) { + fw_speed =3D PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_100GB; + lanes_needed =3D 4; + } else if (support_pam4_spds & BNGE_LINK_PAM4_SPEED_MSK_100GB) { + fw_speed =3D PORT_PHY_CFG_REQ_FORCE_PAM4_LINK_SPEED_100GB; + sig_mode =3D BNGE_SIG_MODE_PAM4; + lanes_needed =3D 2; + } else if ((support_spds2 & BNGE_LINK_SPEEDS2_MSK_100GB_PAM4) && + lanes !=3D 1) { + fw_speed =3D BNGE_LINK_SPEED_100GB_PAM4; + sig_mode =3D BNGE_SIG_MODE_PAM4; + lanes_needed =3D 2; + } else if (support_spds2 & BNGE_LINK_SPEEDS2_MSK_100GB_PAM4_112) { + fw_speed =3D BNGE_LINK_SPEED_100GB_PAM4_112; + sig_mode =3D BNGE_SIG_MODE_PAM4_112; + } + break; + case SPEED_200000: + if (support_pam4_spds & BNGE_LINK_PAM4_SPEED_MSK_200GB) { + fw_speed =3D PORT_PHY_CFG_REQ_FORCE_PAM4_LINK_SPEED_200GB; + sig_mode =3D BNGE_SIG_MODE_PAM4; + lanes_needed =3D 4; + } else if ((support_spds2 & BNGE_LINK_SPEEDS2_MSK_200GB_PAM4) && + lanes !=3D 2) { + fw_speed =3D BNGE_LINK_SPEED_200GB_PAM4; + sig_mode =3D BNGE_SIG_MODE_PAM4; + lanes_needed =3D 4; + } else if (support_spds2 & BNGE_LINK_SPEEDS2_MSK_200GB_PAM4_112) { + fw_speed =3D BNGE_LINK_SPEED_200GB_PAM4_112; + sig_mode =3D BNGE_SIG_MODE_PAM4_112; + lanes_needed =3D 2; + } + break; + case SPEED_400000: + if ((support_spds2 & BNGE_LINK_SPEEDS2_MSK_400GB_PAM4) && + lanes !=3D 4) { + fw_speed =3D BNGE_LINK_SPEED_400GB_PAM4; + sig_mode =3D BNGE_SIG_MODE_PAM4; + lanes_needed =3D 8; + } else if (support_spds2 & BNGE_LINK_SPEEDS2_MSK_400GB_PAM4_112) { + fw_speed =3D BNGE_LINK_SPEED_400GB_PAM4_112; + sig_mode =3D BNGE_SIG_MODE_PAM4_112; + lanes_needed =3D 4; + } + break; + case SPEED_800000: + if (support_spds2 & BNGE_LINK_SPEEDS2_MSK_800GB_PAM4_112) { + fw_speed =3D BNGE_LINK_SPEED_800GB_PAM4_112; + sig_mode =3D BNGE_SIG_MODE_PAM4_112; + lanes_needed =3D 8; + } + } + + if (!fw_speed) { + netdev_err(dev, "unsupported speed!\n"); + return -EINVAL; + } + + if (lanes && lanes !=3D lanes_needed) { + netdev_err(dev, "unsupported number of lanes for speed\n"); + return -EINVAL; + } + + if (elink_info->req_link_speed =3D=3D fw_speed && + elink_info->req_signal_mode =3D=3D sig_mode && + elink_info->autoneg =3D=3D 0) + return -EALREADY; + + elink_info->req_link_speed =3D fw_speed; + elink_info->req_signal_mode =3D sig_mode; + elink_info->req_duplex =3D BNGE_LINK_DUPLEX_FULL; + elink_info->autoneg =3D 0; + elink_info->advertising =3D 0; + elink_info->advertising_pam4 =3D 0; + + return 0; +} + +int bnge_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *lk_ksettings) +{ + const struct ethtool_link_settings *base =3D &lk_ksettings->base; + struct bnge_ethtool_link_info *elink_info; + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_link_info *link_info; + struct bnge_dev *bd =3D bn->bd; + bool set_pause =3D false; + u32 speed, lanes =3D 0; + int rc =3D 0; + + elink_info =3D &bn->eth_link_info; + link_info =3D &bd->link_info; + + if (!BNGE_PHY_CFG_ABLE(bd)) + return -EOPNOTSUPP; + + mutex_lock(&bd->link_lock); + if (base->autoneg =3D=3D AUTONEG_ENABLE) { + bnge_set_ethtool_speeds(bn, + lk_ksettings->link_modes.advertising); + elink_info->autoneg |=3D BNGE_AUTONEG_SPEED; + if (!elink_info->advertising && !elink_info->advertising_pam4) { + elink_info->advertising =3D link_info->support_auto_speeds; + elink_info->advertising_pam4 =3D + link_info->support_pam4_auto_speeds; + } + /* any change to autoneg will cause link change, therefore the + * driver should put back the original pause setting in autoneg + */ + if (!(bd->phy_flags & BNGE_PHY_FL_NO_PAUSE)) + set_pause =3D true; + } else { + u8 phy_type =3D link_info->phy_type; + + if (phy_type =3D=3D PORT_PHY_QCFG_RESP_PHY_TYPE_BASET || + phy_type =3D=3D PORT_PHY_QCFG_RESP_PHY_TYPE_BASETE || + link_info->media_type =3D=3D PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) { + netdev_err(dev, "10GBase-T devices must autoneg\n"); + rc =3D -EINVAL; + goto set_setting_exit; + } + if (base->duplex =3D=3D DUPLEX_HALF) { + netdev_err(dev, "HALF DUPLEX is not supported!\n"); + rc =3D -EINVAL; + goto set_setting_exit; + } + speed =3D base->speed; + lanes =3D lk_ksettings->lanes; + rc =3D bnge_force_link_speed(dev, speed, lanes); + if (rc) { + if (rc =3D=3D -EALREADY) + rc =3D 0; + goto set_setting_exit; + } + } + + if (netif_running(dev)) + rc =3D bnge_hwrm_set_link_setting(bn, set_pause); + +set_setting_exit: + mutex_unlock(&bd->link_lock); + return rc; +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_link.h b/drivers/net/e= thernet/broadcom/bnge/bnge_link.h index 65da27c510b..995ca731879 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_link.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_link.h @@ -182,4 +182,10 @@ void bnge_init_ethtool_link_settings(struct bnge_net *= bn); u32 bnge_fw_to_ethtool_speed(u16 fw_link_speed); int bnge_probe_phy(struct bnge_net *bd, bool fw_dflt); bool bnge_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *resp); +int bnge_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *lk_ksettings); +int bnge_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *lk_ksettings); +u32 bnge_get_link(struct net_device *dev); +u16 bnge_get_force_speed(struct bnge_link_info *link_info); #endif /* _BNGE_LINK_H_ */ --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-yx1-f99.google.com (mail-yx1-f99.google.com [74.125.224.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5CEFA345CD2 for ; Wed, 26 Nov 2025 19:50:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.99 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186653; cv=none; b=C2AfabeyUPzq7V5zdGTJXIRegMK1eR/R+YDpo46uR1IlnwgCEWXZm62WC/OxZ/5jNWpdF+i1DfjDwc79Diyyut2A/Q3WyWqn/vfWrPmzYelybSTOxyQB0dMK0K96hsogdc13UJhCbJ2lVD073w3Ovw2Fb1+ruJOBS8D39cPIyUE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186653; c=relaxed/simple; bh=ViMa2JXl8dBSFb/J919nGFZxyOT8I+T4Ov0qvqphhOg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=okz8Cx36DqpD48Xlo+YrbfAr1/LVxh8eaZxDPgoLGkw/ihqt1hl3Yu2gAaf1VfZbUY5MPEXZKjwpMe+TWsRAJBGqP7YezJOre4pwW5seh+Ift1miiz/S9AvQiA173ifJsgX908nA+A14p2fywoAaM25lcD6e3Tsx9mrnEtRJnRI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=ap1BGSV6; arc=none smtp.client-ip=74.125.224.99 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="ap1BGSV6" Received: by mail-yx1-f99.google.com with SMTP id 956f58d0204a3-641e942242cso131831d50.1 for ; Wed, 26 Nov 2025 11:50:50 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186649; x=1764791449; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=96B5g/vrBTqWhs3NOZYa0sQuyQICh5qAauRERgmK3aE=; b=oh5HvQ8b6uLKXOZob3/neKZ5OFpPzK7tsTsf/x7WobW/fmdgAZA7SAmW94Cq9rEjbU zgBoRPY0NTM5WpEnXhNbXZLvI5pHKns6bmRleoz5R+SRkWfLnRvmFDdzAwdXcTyF9jnY VnT9vuQEVepMgag2B8ljkSR12RnLGgbimZpDeYESQFqoFR2UsJ0X3mpRhX6EKvThgVXc FgkH9TB6jBUKNUKGBCFGaZVyrLZeebD1QRCmXfqAoJZfJcyWntfoUJIuFdNK5gMhDiQU 2/y4NFqJKdifynqAEtdiTTR5kHnXXD5T2xPgqQTpaN4MI30Uc5Q85FHUyDtH5JNiqunq UgVw== X-Forwarded-Encrypted: i=1; AJvYcCVu5dw4x4aEjcg4Wpt0r+M6bp+D7fOlJnhwbNcf1VUu8g0qNWjmMNosyh9TOD8mAnApYBNMsYjso7EaVzQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/2slXPF898ir2ZgnbXzY8/kFyrPvNBsZ/TTaOZlGxXZwdGaR5 ZdlcdpVuuHLbRTTbDMUumXtLz7u23+roIxz7uF6iP7ikqj21l6var9gdNYOB8SZZhWlWl0d9Qud 93i4NJBwPnsSLiugSqyLBHxj/IX3PO2B09H0GTJK7EleflG4DyMPgHalWfPWZiF+2kW6Bxmm2mN /YMYN0ljAKKhqd6iM26cMLiF8cRfptfdrEW4xjlj9g8ZnnlgKS2zUnsfvphLY6yCaAb7RZlfvhR a88KbuwqqQnkLtvgR3Pjj6Lig3a X-Gm-Gg: ASbGncusRBJGWc3JrrEnZM2KrULG1qbnFJ1VfDvDiSw/u6dMpad7fcIaqbrfnzuZUbb ORlicjgnfzEHvStlrsTB20vhOsHeXG8Z1HGj8bn9ATavcJS1B1lLdT9G33N7iOmpOF5Hxgo/RZR 3bbghLkJayHaqMSaQhqLxvdSH5OjTRMa4cHJONi8NsqooUCIjgrNJ/1bTznSwKznA7MjzyacEr6 0LmJE8VbpCEdt+HwCEK4EWYYe6GX2x4bv6iSzP0IJ9xkKhVatdel0IlTx6nFgetLruMm/skbpl5 i4hZ1zWpF1KyPjmZiX/KNrpQqgU9M9NfdAe0liYhiOcYQZMgRDZnUnh2wcMLeanaa75fAtzoWXX yLxYFfCcqqSvFwKHx3lGNOlNdsE4RLEWeBfr63/N9gePXvPUyUwc/HtV/jQYHHG5yLoz/GFjuQ7 3e6Nf0rIBEfydiCyL2oFAvEQE3keTgbzkEDyuC9eiy8ZXznXXyl+Q= X-Google-Smtp-Source: AGHT+IHi9HdAMCZ4wz5Zl0+JjPpP+LH4uDVAIGRZIchdKfpuncwxrRo/w5RWx/giMSdGcavPdUi9kllFKrOM X-Received: by 2002:a05:690c:630e:b0:789:62c5:db2f with SMTP id 00721157ae682-78a8b545b8fmr170866577b3.62.1764186649259; Wed, 26 Nov 2025 11:50:49 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-11.dlp.protect.broadcom.com. [144.49.247.11]) by smtp-relay.gmail.com with ESMTPS id 00721157ae682-78a79921275sm14371807b3.20.2025.11.26.11.50.48 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:49 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f197.google.com with SMTP id d9443c01a7336-297dabf9fd0so1576045ad.0 for ; Wed, 26 Nov 2025 11:50:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186648; x=1764791448; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=96B5g/vrBTqWhs3NOZYa0sQuyQICh5qAauRERgmK3aE=; b=ap1BGSV6n4G92Axg8eyUeiYTNaHWCQQNqi02sSLM76OwXN+2zpaiE54kqoHuz+FdSL Ml6nVm3El/t0v2OKTIDfkgBu/1RQTTbv693Oosd8ouGXY4sZ4ZhFSFU8riZwJ2asp0pM 1X8vygN57+TmzLH3pcbFrmUwPx9c6DRv0z4k4= X-Forwarded-Encrypted: i=1; AJvYcCXEEUaEAkWJ1Z64myujVxxXUL8jF/1A1shRRX99RcDJRBX1rSSWgmZterjSaH/RAw1a4i53IxDcspPge50=@vger.kernel.org X-Received: by 2002:a17:903:1904:b0:298:616b:b2d with SMTP id d9443c01a7336-29b6c6b1bf9mr173250845ad.51.1764186647550; Wed, 26 Nov 2025 11:50:47 -0800 (PST) X-Received: by 2002:a17:903:1904:b0:298:616b:b2d with SMTP id d9443c01a7336-29b6c6b1bf9mr173250595ad.51.1764186646995; Wed, 26 Nov 2025 11:50:46 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:46 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 10/12] bng_en: Add initial support for ethtool stats display Date: Thu, 27 Nov 2025 01:19:29 +0530 Message-ID: <20251126194931.455830-11-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" This patch adds support for displaying ethtool statistics. Currently, only the display functionality is implemented. All stat counters remain at 0, as support for updating the counters will be added in subsequent patches. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_ethtool.c | 612 ++++++++++++++++++ .../ethernet/broadcom/bnge/bnge_hwrm_lib.c | 143 ++++ .../ethernet/broadcom/bnge/bnge_hwrm_lib.h | 3 + .../net/ethernet/broadcom/bnge/bnge_netdev.c | 186 +++++- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 94 ++- 5 files changed, 1028 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c b/drivers/ne= t/ethernet/broadcom/bnge/bnge_ethtool.c index b985799051b..a82271492d7 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c @@ -32,6 +32,374 @@ static int bnge_nway_reset(struct net_device *dev) } =20 =20 +static const char * const bnge_ring_rx_stats_str[] =3D { + "rx_ucast_packets", + "rx_mcast_packets", + "rx_bcast_packets", + "rx_discards", + "rx_errors", + "rx_ucast_bytes", + "rx_mcast_bytes", + "rx_bcast_bytes", +}; + +static const char * const bnge_ring_tx_stats_str[] =3D { + "tx_ucast_packets", + "tx_mcast_packets", + "tx_bcast_packets", + "tx_errors", + "tx_discards", + "tx_ucast_bytes", + "tx_mcast_bytes", + "tx_bcast_bytes", +}; + +static const char * const bnge_ring_tpa_stats_str[] =3D { + "tpa_packets", + "tpa_bytes", + "tpa_events", + "tpa_aborts", +}; + +static const char * const bnge_ring_tpa2_stats_str[] =3D { + "rx_tpa_eligible_pkt", + "rx_tpa_eligible_bytes", + "rx_tpa_pkt", + "rx_tpa_bytes", + "rx_tpa_errors", + "rx_tpa_events", +}; + +static const char * const bnge_rx_sw_stats_str[] =3D { + "rx_l4_csum_errors", + "rx_resets", + "rx_buf_errors", +}; + +#define BNGE_RX_STATS_ENTRY(counter) \ + { BNGE_RX_STATS_OFFSET(counter), __stringify(counter) } + +#define BNGE_TX_STATS_ENTRY(counter) \ + { BNGE_TX_STATS_OFFSET(counter), __stringify(counter) } + +#define BNGE_RX_STATS_EXT_ENTRY(counter) \ + { BNGE_RX_STATS_EXT_OFFSET(counter), __stringify(counter) } + +#define BNGE_TX_STATS_EXT_ENTRY(counter) \ + { BNGE_TX_STATS_EXT_OFFSET(counter), __stringify(counter) } + +#define BNGE_RX_STATS_EXT_PFC_ENTRY(n) \ + BNGE_RX_STATS_EXT_ENTRY(pfc_pri##n##_rx_duration_us), \ + BNGE_RX_STATS_EXT_ENTRY(pfc_pri##n##_rx_transitions) + +#define BNGE_TX_STATS_EXT_PFC_ENTRY(n) \ + BNGE_TX_STATS_EXT_ENTRY(pfc_pri##n##_tx_duration_us), \ + BNGE_TX_STATS_EXT_ENTRY(pfc_pri##n##_tx_transitions) + +#define BNGE_RX_STATS_EXT_PFC_ENTRIES \ + BNGE_RX_STATS_EXT_PFC_ENTRY(0), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(1), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(2), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(3), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(4), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(5), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(6), \ + BNGE_RX_STATS_EXT_PFC_ENTRY(7) + +#define BNGE_TX_STATS_EXT_PFC_ENTRIES \ + BNGE_TX_STATS_EXT_PFC_ENTRY(0), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(1), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(2), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(3), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(4), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(5), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(6), \ + BNGE_TX_STATS_EXT_PFC_ENTRY(7) + +#define BNGE_RX_STATS_EXT_COS_ENTRY(n) \ + BNGE_RX_STATS_EXT_ENTRY(rx_bytes_cos##n), \ + BNGE_RX_STATS_EXT_ENTRY(rx_packets_cos##n) + +#define BNGE_TX_STATS_EXT_COS_ENTRY(n) \ + BNGE_TX_STATS_EXT_ENTRY(tx_bytes_cos##n), \ + BNGE_TX_STATS_EXT_ENTRY(tx_packets_cos##n) + +#define BNGE_RX_STATS_EXT_COS_ENTRIES \ + BNGE_RX_STATS_EXT_COS_ENTRY(0), \ + BNGE_RX_STATS_EXT_COS_ENTRY(1), \ + BNGE_RX_STATS_EXT_COS_ENTRY(2), \ + BNGE_RX_STATS_EXT_COS_ENTRY(3), \ + BNGE_RX_STATS_EXT_COS_ENTRY(4), \ + BNGE_RX_STATS_EXT_COS_ENTRY(5), \ + BNGE_RX_STATS_EXT_COS_ENTRY(6), \ + BNGE_RX_STATS_EXT_COS_ENTRY(7) \ + +#define BNGE_TX_STATS_EXT_COS_ENTRIES \ + BNGE_TX_STATS_EXT_COS_ENTRY(0), \ + BNGE_TX_STATS_EXT_COS_ENTRY(1), \ + BNGE_TX_STATS_EXT_COS_ENTRY(2), \ + BNGE_TX_STATS_EXT_COS_ENTRY(3), \ + BNGE_TX_STATS_EXT_COS_ENTRY(4), \ + BNGE_TX_STATS_EXT_COS_ENTRY(5), \ + BNGE_TX_STATS_EXT_COS_ENTRY(6), \ + BNGE_TX_STATS_EXT_COS_ENTRY(7) \ + +#define BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(n) \ + BNGE_RX_STATS_EXT_ENTRY(rx_discard_bytes_cos##n), \ + BNGE_RX_STATS_EXT_ENTRY(rx_discard_packets_cos##n) + +#define BNGE_RX_STATS_EXT_DISCARD_COS_ENTRIES \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(0), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(1), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(2), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(3), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(4), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(5), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(6), \ + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(7) + +#define BNGE_RX_STATS_PRI_ENTRY(counter, n) \ + { BNGE_RX_STATS_EXT_OFFSET(counter##_cos0), \ + __stringify(counter##_pri##n) } + +#define BNGE_TX_STATS_PRI_ENTRY(counter, n) \ + { BNGE_TX_STATS_EXT_OFFSET(counter##_cos0), \ + __stringify(counter##_pri##n) } + +#define BNGE_RX_STATS_PRI_ENTRIES(counter) \ + BNGE_RX_STATS_PRI_ENTRY(counter, 0), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 1), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 2), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 3), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 4), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 5), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 6), \ + BNGE_RX_STATS_PRI_ENTRY(counter, 7) + +#define BNGE_TX_STATS_PRI_ENTRIES(counter) \ + BNGE_TX_STATS_PRI_ENTRY(counter, 0), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 1), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 2), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 3), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 4), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 5), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 6), \ + BNGE_TX_STATS_PRI_ENTRY(counter, 7) + +enum { + RX_TOTAL_DISCARDS, + TX_TOTAL_DISCARDS, + RX_NETPOLL_DISCARDS, +}; + +static const char *const bnge_ring_err_stats_arr[] =3D { + "rx_total_l4_csum_errors", + "rx_total_resets", + "rx_total_buf_errors", + "rx_total_oom_discards", + "rx_total_netpoll_discards", + "rx_total_ring_discards", + "tx_total_resets", + "tx_total_ring_discards", +}; + +#define NUM_RING_RX_SW_STATS ARRAY_SIZE(bnge_rx_sw_stats_str) +#define NUM_RING_RX_HW_STATS ARRAY_SIZE(bnge_ring_rx_stats_str) +#define NUM_RING_TX_HW_STATS ARRAY_SIZE(bnge_ring_tx_stats_str) + +static const struct { + long offset; + char string[ETH_GSTRING_LEN]; +} bnge_tx_port_stats_ext_arr[] =3D { + BNGE_TX_STATS_EXT_COS_ENTRIES, + BNGE_TX_STATS_EXT_PFC_ENTRIES, +}; + +static const struct { + long base_off; + char string[ETH_GSTRING_LEN]; +} bnge_rx_bytes_pri_arr[] =3D { + BNGE_RX_STATS_PRI_ENTRIES(rx_bytes), +}; + +static const struct { + long base_off; + char string[ETH_GSTRING_LEN]; +} bnge_rx_pkts_pri_arr[] =3D { + BNGE_RX_STATS_PRI_ENTRIES(rx_packets), +}; + +static const struct { + long base_off; + char string[ETH_GSTRING_LEN]; +} bnge_tx_bytes_pri_arr[] =3D { + BNGE_TX_STATS_PRI_ENTRIES(tx_bytes), +}; + +static const struct { + long base_off; + char string[ETH_GSTRING_LEN]; +} bnge_tx_pkts_pri_arr[] =3D { + BNGE_TX_STATS_PRI_ENTRIES(tx_packets), +}; + +static const struct { + long offset; + char string[ETH_GSTRING_LEN]; +} bnge_port_stats_arr[] =3D { + BNGE_RX_STATS_ENTRY(rx_64b_frames), + BNGE_RX_STATS_ENTRY(rx_65b_127b_frames), + BNGE_RX_STATS_ENTRY(rx_128b_255b_frames), + BNGE_RX_STATS_ENTRY(rx_256b_511b_frames), + BNGE_RX_STATS_ENTRY(rx_512b_1023b_frames), + BNGE_RX_STATS_ENTRY(rx_1024b_1518b_frames), + BNGE_RX_STATS_ENTRY(rx_good_vlan_frames), + BNGE_RX_STATS_ENTRY(rx_1519b_2047b_frames), + BNGE_RX_STATS_ENTRY(rx_2048b_4095b_frames), + BNGE_RX_STATS_ENTRY(rx_4096b_9216b_frames), + BNGE_RX_STATS_ENTRY(rx_9217b_16383b_frames), + BNGE_RX_STATS_ENTRY(rx_total_frames), + BNGE_RX_STATS_ENTRY(rx_ucast_frames), + BNGE_RX_STATS_ENTRY(rx_mcast_frames), + BNGE_RX_STATS_ENTRY(rx_bcast_frames), + BNGE_RX_STATS_ENTRY(rx_fcs_err_frames), + BNGE_RX_STATS_ENTRY(rx_ctrl_frames), + BNGE_RX_STATS_ENTRY(rx_pause_frames), + BNGE_RX_STATS_ENTRY(rx_pfc_frames), + BNGE_RX_STATS_ENTRY(rx_align_err_frames), + BNGE_RX_STATS_ENTRY(rx_ovrsz_frames), + BNGE_RX_STATS_ENTRY(rx_jbr_frames), + BNGE_RX_STATS_ENTRY(rx_mtu_err_frames), + BNGE_RX_STATS_ENTRY(rx_tagged_frames), + BNGE_RX_STATS_ENTRY(rx_double_tagged_frames), + BNGE_RX_STATS_ENTRY(rx_good_frames), + BNGE_RX_STATS_ENTRY(rx_pfc_ena_frames_pri0), + BNGE_RX_STATS_ENTRY(rx_pfc_ena_frames_pri1), + BNGE_RX_STATS_ENTRY(rx_pfc_ena_frames_pri2), + BNGE_RX_STATS_ENTRY(rx_pfc_ena_frames_pri3), + BNGE_RX_STATS_ENTRY(rx_pfc_ena_frames_pri4), + BNGE_RX_STATS_ENTRY(rx_pfc_ena_frames_pri5), + BNGE_RX_STATS_ENTRY(rx_pfc_ena_frames_pri6), + BNGE_RX_STATS_ENTRY(rx_pfc_ena_frames_pri7), + BNGE_RX_STATS_ENTRY(rx_undrsz_frames), + BNGE_RX_STATS_ENTRY(rx_eee_lpi_events), + BNGE_RX_STATS_ENTRY(rx_eee_lpi_duration), + BNGE_RX_STATS_ENTRY(rx_bytes), + BNGE_RX_STATS_ENTRY(rx_runt_bytes), + BNGE_RX_STATS_ENTRY(rx_runt_frames), + BNGE_RX_STATS_ENTRY(rx_stat_discard), + BNGE_RX_STATS_ENTRY(rx_stat_err), + + BNGE_TX_STATS_ENTRY(tx_64b_frames), + BNGE_TX_STATS_ENTRY(tx_65b_127b_frames), + BNGE_TX_STATS_ENTRY(tx_128b_255b_frames), + BNGE_TX_STATS_ENTRY(tx_256b_511b_frames), + BNGE_TX_STATS_ENTRY(tx_512b_1023b_frames), + BNGE_TX_STATS_ENTRY(tx_1024b_1518b_frames), + BNGE_TX_STATS_ENTRY(tx_good_vlan_frames), + BNGE_TX_STATS_ENTRY(tx_1519b_2047b_frames), + BNGE_TX_STATS_ENTRY(tx_2048b_4095b_frames), + BNGE_TX_STATS_ENTRY(tx_4096b_9216b_frames), + BNGE_TX_STATS_ENTRY(tx_9217b_16383b_frames), + BNGE_TX_STATS_ENTRY(tx_good_frames), + BNGE_TX_STATS_ENTRY(tx_total_frames), + BNGE_TX_STATS_ENTRY(tx_ucast_frames), + BNGE_TX_STATS_ENTRY(tx_mcast_frames), + BNGE_TX_STATS_ENTRY(tx_bcast_frames), + BNGE_TX_STATS_ENTRY(tx_pause_frames), + BNGE_TX_STATS_ENTRY(tx_pfc_frames), + BNGE_TX_STATS_ENTRY(tx_jabber_frames), + BNGE_TX_STATS_ENTRY(tx_fcs_err_frames), + BNGE_TX_STATS_ENTRY(tx_err), + BNGE_TX_STATS_ENTRY(tx_fifo_underruns), + BNGE_TX_STATS_ENTRY(tx_pfc_ena_frames_pri0), + BNGE_TX_STATS_ENTRY(tx_pfc_ena_frames_pri1), + BNGE_TX_STATS_ENTRY(tx_pfc_ena_frames_pri2), + BNGE_TX_STATS_ENTRY(tx_pfc_ena_frames_pri3), + BNGE_TX_STATS_ENTRY(tx_pfc_ena_frames_pri4), + BNGE_TX_STATS_ENTRY(tx_pfc_ena_frames_pri5), + BNGE_TX_STATS_ENTRY(tx_pfc_ena_frames_pri6), + BNGE_TX_STATS_ENTRY(tx_pfc_ena_frames_pri7), + BNGE_TX_STATS_ENTRY(tx_eee_lpi_events), + BNGE_TX_STATS_ENTRY(tx_eee_lpi_duration), + BNGE_TX_STATS_ENTRY(tx_total_collisions), + BNGE_TX_STATS_ENTRY(tx_bytes), + BNGE_TX_STATS_ENTRY(tx_xthol_frames), + BNGE_TX_STATS_ENTRY(tx_stat_discard), + BNGE_TX_STATS_ENTRY(tx_stat_error), +}; + +static const struct { + long offset; + char string[ETH_GSTRING_LEN]; +} bnge_port_stats_ext_arr[] =3D { + BNGE_RX_STATS_EXT_ENTRY(link_down_events), + BNGE_RX_STATS_EXT_ENTRY(continuous_pause_events), + BNGE_RX_STATS_EXT_ENTRY(resume_pause_events), + BNGE_RX_STATS_EXT_ENTRY(continuous_roce_pause_events), + BNGE_RX_STATS_EXT_ENTRY(resume_roce_pause_events), + BNGE_RX_STATS_EXT_COS_ENTRIES, + BNGE_RX_STATS_EXT_PFC_ENTRIES, + BNGE_RX_STATS_EXT_ENTRY(rx_bits), + BNGE_RX_STATS_EXT_ENTRY(rx_buffer_passed_threshold), + BNGE_RX_STATS_EXT_ENTRY(rx_pcs_symbol_err), + BNGE_RX_STATS_EXT_ENTRY(rx_corrected_bits), + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRIES, + BNGE_RX_STATS_EXT_ENTRY(rx_fec_corrected_blocks), + BNGE_RX_STATS_EXT_ENTRY(rx_fec_uncorrectable_blocks), + BNGE_RX_STATS_EXT_ENTRY(rx_filter_miss), +}; + +static int bnge_get_num_tpa_ring_stats(struct bnge_dev *bd) +{ + if (BNGE_SUPPORTS_TPA(bd)) + return BNGE_NUM_TPA_RING_STATS; + return 0; +} + +#define BNGE_NUM_RING_ERR_STATS ARRAY_SIZE(bnge_ring_err_stats_arr) +#define BNGE_NUM_PORT_STATS ARRAY_SIZE(bnge_port_stats_arr) +#define BNGE_NUM_STATS_PRI \ + (ARRAY_SIZE(bnge_rx_bytes_pri_arr) + \ + ARRAY_SIZE(bnge_rx_pkts_pri_arr) + \ + ARRAY_SIZE(bnge_tx_bytes_pri_arr) + \ + ARRAY_SIZE(bnge_tx_pkts_pri_arr)) + +static int bnge_get_num_ring_stats(struct bnge_dev *bd) +{ + int rx, tx; + + rx =3D NUM_RING_RX_HW_STATS + NUM_RING_RX_SW_STATS + + bnge_get_num_tpa_ring_stats(bd); + tx =3D NUM_RING_TX_HW_STATS; + return rx * bd->rx_nr_rings + + tx * bd->tx_nr_rings_per_tc; +} + +static int bnge_get_num_stats(struct bnge_net *bn) +{ + int num_stats =3D bnge_get_num_ring_stats(bn->bd); + int len; + + num_stats +=3D BNGE_NUM_RING_ERR_STATS; + + if (bn->flags & BNGE_FLAG_PORT_STATS) + num_stats +=3D BNGE_NUM_PORT_STATS; + + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { + len =3D min_t(int, bn->fw_rx_stats_ext_size, + ARRAY_SIZE(bnge_port_stats_ext_arr)); + num_stats +=3D len; + len =3D min_t(int, bn->fw_tx_stats_ext_size, + ARRAY_SIZE(bnge_tx_port_stats_ext_arr)); + num_stats +=3D len; + if (bn->pri2cos_valid) + num_stats +=3D BNGE_NUM_STATS_PRI; + } + + return num_stats; +} + static void bnge_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -41,6 +409,247 @@ static void bnge_get_drvinfo(struct net_device *dev, strscpy(info->driver, DRV_NAME, sizeof(info->driver)); strscpy(info->fw_version, bd->fw_ver_str, sizeof(info->fw_version)); strscpy(info->bus_info, pci_name(bd->pdev), sizeof(info->bus_info)); + info->n_stats =3D bnge_get_num_stats(bn); +} + +static int bnge_get_sset_count(struct net_device *dev, int sset) +{ + struct bnge_net *bn =3D netdev_priv(dev); + + switch (sset) { + case ETH_SS_STATS: + return bnge_get_num_stats(bn); + default: + return -EOPNOTSUPP; + } +} + +static bool is_rx_ring(struct bnge_dev *bd, u16 ring_num) +{ + return ring_num < bd->rx_nr_rings; +} + +static bool is_tx_ring(struct bnge_dev *bd, u16 ring_num) +{ + u16 tx_base =3D 0; + + if (!(bd->flags & BNGE_EN_SHARED_CHNL)) + tx_base =3D bd->rx_nr_rings; + + if (ring_num >=3D tx_base && ring_num < (tx_base + bd->tx_nr_rings)) + return true; + return false; +} + +static void bnge_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *buf) +{ + struct bnge_total_ring_err_stats ring_err_stats =3D {0}; + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_dev *bd =3D bn->bd; + u64 *curr, *prev; + u32 tpa_stats; + u32 i, j =3D 0; + + if (!bn->bnapi) { + j +=3D bnge_get_num_ring_stats(bd); + goto skip_ring_stats; + } + + tpa_stats =3D bnge_get_num_tpa_ring_stats(bd); + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; + u64 *sw_stats =3D nqr->stats.sw_stats; + u64 *sw; + int k; + + if (is_rx_ring(bd, i)) { + for (k =3D 0; k < NUM_RING_RX_HW_STATS; j++, k++) + buf[j] =3D sw_stats[k]; + } + if (is_tx_ring(bd, i)) { + k =3D NUM_RING_RX_HW_STATS; + for (; k < NUM_RING_RX_HW_STATS + NUM_RING_TX_HW_STATS; + j++, k++) + buf[j] =3D sw_stats[k]; + } + if (!tpa_stats || !is_rx_ring(bd, i)) + goto skip_tpa_ring_stats; + + k =3D NUM_RING_RX_HW_STATS + NUM_RING_TX_HW_STATS; + for (; k < NUM_RING_RX_HW_STATS + NUM_RING_TX_HW_STATS + + tpa_stats; j++, k++) + buf[j] =3D sw_stats[k]; + +skip_tpa_ring_stats: + sw =3D (u64 *)&nqr->sw_stats->rx; + if (is_rx_ring(bd, i)) { + for (k =3D 0; k < NUM_RING_RX_SW_STATS; j++, k++) + buf[j] =3D sw[k]; + } + } + + bnge_get_ring_err_stats(bn, &ring_err_stats); + +skip_ring_stats: + curr =3D &ring_err_stats.rx_total_l4_csum_errors; + prev =3D &bn->ring_err_stats_prev.rx_total_l4_csum_errors; + for (i =3D 0; i < BNGE_NUM_RING_ERR_STATS; i++, j++, curr++, prev++) + buf[j] =3D *curr + *prev; + + if (bn->flags & BNGE_FLAG_PORT_STATS) { + u64 *port_stats =3D bn->port_stats.sw_stats; + + for (i =3D 0; i < BNGE_NUM_PORT_STATS; i++, j++) + buf[j] =3D *(port_stats + bnge_port_stats_arr[i].offset); + } + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { + u64 *rx_port_stats_ext =3D bn->rx_port_stats_ext.sw_stats; + u64 *tx_port_stats_ext =3D bn->tx_port_stats_ext.sw_stats; + u32 len; + + len =3D min_t(u32, bn->fw_rx_stats_ext_size, + ARRAY_SIZE(bnge_port_stats_ext_arr)); + for (i =3D 0; i < len; i++, j++) { + buf[j] =3D *(rx_port_stats_ext + + bnge_port_stats_ext_arr[i].offset); + } + len =3D min_t(u32, bn->fw_tx_stats_ext_size, + ARRAY_SIZE(bnge_tx_port_stats_ext_arr)); + for (i =3D 0; i < len; i++, j++) { + buf[j] =3D *(tx_port_stats_ext + + bnge_tx_port_stats_ext_arr[i].offset); + } + if (bn->pri2cos_valid) { + for (i =3D 0; i < 8; i++, j++) { + long n =3D bnge_rx_bytes_pri_arr[i].base_off + + bn->pri2cos_idx[i]; + + buf[j] =3D *(rx_port_stats_ext + n); + } + for (i =3D 0; i < 8; i++, j++) { + long n =3D bnge_rx_pkts_pri_arr[i].base_off + + bn->pri2cos_idx[i]; + + buf[j] =3D *(rx_port_stats_ext + n); + } + for (i =3D 0; i < 8; i++, j++) { + long n =3D bnge_tx_bytes_pri_arr[i].base_off + + bn->pri2cos_idx[i]; + + buf[j] =3D *(tx_port_stats_ext + n); + } + for (i =3D 0; i < 8; i++, j++) { + long n =3D bnge_tx_pkts_pri_arr[i].base_off + + bn->pri2cos_idx[i]; + + buf[j] =3D *(tx_port_stats_ext + n); + } + } + } +} + +static void bnge_get_strings(struct net_device *dev, u32 stringset, u8 *bu= f) +{ + struct bnge_net *bn =3D netdev_priv(dev); + struct bnge_dev *bd =3D bn->bd; + u32 i, j, num_str; + const char *str; + + switch (stringset) { + case ETH_SS_STATS: + for (i =3D 0; i < bd->nq_nr_rings; i++) { + if (is_rx_ring(bd, i)) + for (j =3D 0; j < NUM_RING_RX_HW_STATS; j++) { + str =3D bnge_ring_rx_stats_str[j]; + ethtool_sprintf(&buf, "[%d]: %s", i, + str); + } + if (is_tx_ring(bd, i)) + for (j =3D 0; j < NUM_RING_TX_HW_STATS; j++) { + str =3D bnge_ring_tx_stats_str[j]; + ethtool_sprintf(&buf, "[%d]: %s", i, + str); + } + num_str =3D bnge_get_num_tpa_ring_stats(bd); + if (!num_str || !is_rx_ring(bd, i)) + goto skip_tpa_stats; + + if (bd->max_tpa_v2) + for (j =3D 0; j < num_str; j++) { + str =3D bnge_ring_tpa2_stats_str[j]; + ethtool_sprintf(&buf, "[%d]: %s", i, + str); + } + else + for (j =3D 0; j < num_str; j++) { + str =3D bnge_ring_tpa_stats_str[j]; + ethtool_sprintf(&buf, "[%d]: %s", i, + str); + } +skip_tpa_stats: + if (is_rx_ring(bd, i)) + for (j =3D 0; j < NUM_RING_RX_SW_STATS; j++) { + str =3D bnge_rx_sw_stats_str[j]; + ethtool_sprintf(&buf, "[%d]: %s", i, + str); + } + } + for (i =3D 0; i < BNGE_NUM_RING_ERR_STATS; i++) + ethtool_puts(&buf, bnge_ring_err_stats_arr[i]); + + if (bn->flags & BNGE_FLAG_PORT_STATS) + for (i =3D 0; i < BNGE_NUM_PORT_STATS; i++) { + str =3D bnge_port_stats_arr[i].string; + ethtool_puts(&buf, str); + } + + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { + u32 len; + + len =3D min_t(u32, bn->fw_rx_stats_ext_size, + ARRAY_SIZE(bnge_port_stats_ext_arr)); + for (i =3D 0; i < len; i++) { + str =3D bnge_port_stats_ext_arr[i].string; + ethtool_puts(&buf, str); + } + + len =3D min_t(u32, bn->fw_tx_stats_ext_size, + ARRAY_SIZE(bnge_tx_port_stats_ext_arr)); + for (i =3D 0; i < len; i++) { + str =3D bnge_tx_port_stats_ext_arr[i].string; + ethtool_puts(&buf, str); + } + + if (bn->pri2cos_valid) { + for (i =3D 0; i < 8; i++) { + str =3D bnge_rx_bytes_pri_arr[i].string; + ethtool_puts(&buf, str); + } + + for (i =3D 0; i < 8; i++) { + str =3D bnge_rx_pkts_pri_arr[i].string; + ethtool_puts(&buf, str); + } + + for (i =3D 0; i < 8; i++) { + str =3D bnge_tx_bytes_pri_arr[i].string; + ethtool_puts(&buf, str); + } + + for (i =3D 0; i < 8; i++) { + str =3D bnge_tx_pkts_pri_arr[i].string; + ethtool_puts(&buf, str); + } + } + } + break; + default: + netdev_err(bd->netdev, "%s invalid request %x\n", + __func__, stringset); + break; + } } =20 static const struct ethtool_ops bnge_ethtool_ops =3D { @@ -50,6 +659,9 @@ static const struct ethtool_ops bnge_ethtool_ops =3D { .get_drvinfo =3D bnge_get_drvinfo, .get_link =3D bnge_get_link, .nway_reset =3D bnge_nway_reset, + .get_sset_count =3D bnge_get_sset_count, + .get_strings =3D bnge_get_strings, + .get_ethtool_stats =3D bnge_get_ethtool_stats, }; =20 void bnge_set_ethtool_ops(struct net_device *dev) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.c index d7eb9c7ed6d..b4c37bb4260 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c @@ -14,6 +14,7 @@ #include "bnge_hwrm_lib.h" #include "bnge_rmem.h" #include "bnge_resc.h" +#include "bnge_netdev.h" #include "bnge_link.h" =20 int bnge_hwrm_ver_get(struct bnge_dev *bd) @@ -596,6 +597,10 @@ int bnge_hwrm_func_qcaps(struct bnge_dev *bd) bd->flags |=3D BNGE_EN_ROCE_V1; if (flags & FUNC_QCAPS_RESP_FLAGS_ROCE_V2_SUPPORTED) bd->flags |=3D BNGE_EN_ROCE_V2; + if (flags & FUNC_QCAPS_RESP_FLAGS_EXT_STATS_SUPPORTED) + bd->fw_cap |=3D BNGE_FW_CAP_EXT_STATS_SUPPORTED; + if (flags & FUNC_QCAPS_RESP_FLAGS_PCIE_STATS_SUPPORTED) + bd->fw_cap |=3D BNGE_FW_CAP_PCIE_STATS_SUPPORTED; =20 pf->fw_fid =3D le16_to_cpu(resp->fid); pf->port_id =3D le16_to_cpu(resp->port_id); @@ -1438,3 +1443,141 @@ int bnge_hwrm_vnic_set_tpa(struct bnge_dev *bd, str= uct bnge_vnic_info *vnic, =20 return bnge_hwrm_req_send(bd, req); } + +int bnge_hwrm_func_qstat_ext(struct bnge_dev *bd, struct bnge_stats_mem *s= tats) +{ + struct hwrm_func_qstats_ext_output *resp; + struct hwrm_func_qstats_ext_input *req; + __le64 *hw_masks; + int rc; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_FUNC_QSTATS_EXT); + if (rc) + return rc; + + req->fid =3D cpu_to_le16(0xffff); + req->flags =3D FUNC_QSTATS_EXT_REQ_FLAGS_COUNTER_MASK; + + resp =3D bnge_hwrm_req_hold(bd, req); + rc =3D bnge_hwrm_req_send(bd, req); + if (!rc) { + hw_masks =3D &resp->rx_ucast_pkts; + bnge_copy_hw_masks(stats->hw_masks, hw_masks, stats->len / 8); + } + bnge_hwrm_req_drop(bd, req); + return rc; +} + +int bnge_hwrm_port_qstats_ext(struct bnge_dev *bd, u8 flags) +{ + struct hwrm_queue_pri2cos_qcfg_output *resp_qc; + struct bnge_net *bn =3D netdev_priv(bd->netdev); + struct hwrm_queue_pri2cos_qcfg_input *req_qc; + struct hwrm_port_qstats_ext_output *resp_qs; + struct hwrm_port_qstats_ext_input *req_qs; + struct bnge_pf_info *pf =3D &bd->pf; + u32 tx_stat_size; + int rc; + + if (!(bn->flags & BNGE_FLAG_PORT_STATS_EXT)) + return 0; + + if (flags && !(bd->fw_cap & BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED)) + return -EOPNOTSUPP; + + rc =3D bnge_hwrm_req_init(bd, req_qs, HWRM_PORT_QSTATS_EXT); + if (rc) + return rc; + + req_qs->flags =3D flags; + req_qs->port_id =3D cpu_to_le16(pf->port_id); + req_qs->rx_stat_size =3D cpu_to_le16(sizeof(struct rx_port_stats_ext)); + req_qs->rx_stat_host_addr =3D + cpu_to_le64(bn->rx_port_stats_ext.hw_stats_map); + tx_stat_size =3D bn->tx_port_stats_ext.hw_stats ? + sizeof(struct tx_port_stats_ext) : 0; + req_qs->tx_stat_size =3D cpu_to_le16(tx_stat_size); + req_qs->tx_stat_host_addr =3D + cpu_to_le64(bn->tx_port_stats_ext.hw_stats_map); + resp_qs =3D bnge_hwrm_req_hold(bd, req_qs); + rc =3D bnge_hwrm_req_send(bd, req_qs); + if (!rc) { + bn->fw_rx_stats_ext_size =3D + le16_to_cpu(resp_qs->rx_stat_size) / 8; + bn->fw_tx_stats_ext_size =3D tx_stat_size ? + le16_to_cpu(resp_qs->tx_stat_size) / 8 : 0; + } else { + bn->fw_rx_stats_ext_size =3D 0; + bn->fw_tx_stats_ext_size =3D 0; + } + bnge_hwrm_req_drop(bd, req_qs); + + if (flags) + return rc; + + if (bn->fw_tx_stats_ext_size <=3D + offsetof(struct tx_port_stats_ext, pfc_pri0_tx_duration_us) / 8) { + bn->pri2cos_valid =3D 0; + return rc; + } + + rc =3D bnge_hwrm_req_init(bd, req_qc, HWRM_QUEUE_PRI2COS_QCFG); + if (rc) + return rc; + + req_qc->flags =3D cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN); + + resp_qc =3D bnge_hwrm_req_hold(bd, req_qc); + rc =3D bnge_hwrm_req_send(bd, req_qc); + if (!rc) { + u8 *pri2cos; + int i, j; + + pri2cos =3D &resp_qc->pri0_cos_queue_id; + for (i =3D 0; i < 8; i++) { + u8 queue_id =3D pri2cos[i]; + u8 queue_idx; + + /* Per port queue IDs start from 0, 10, 20, etc */ + queue_idx =3D queue_id % 10; + if (queue_idx > BNGE_MAX_QUEUE) { + bn->pri2cos_valid =3D false; + bnge_hwrm_req_drop(bd, req_qc); + return rc; + } + for (j =3D 0; j < bd->max_q; j++) { + if (bd->q_ids[j] =3D=3D queue_id) + bn->pri2cos_idx[i] =3D queue_idx; + } + } + bn->pri2cos_valid =3D true; + } + bnge_hwrm_req_drop(bd, req_qc); + + return rc; +} + +int bnge_hwrm_port_qstats(struct bnge_dev *bd, u8 flags) +{ + struct bnge_net *bn =3D netdev_priv(bd->netdev); + struct hwrm_port_qstats_input *req; + struct bnge_pf_info *pf =3D &bd->pf; + int rc; + + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) + return 0; + + if (flags && !(bd->fw_cap & BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED)) + return -EOPNOTSUPP; + + rc =3D bnge_hwrm_req_init(bd, req, HWRM_PORT_QSTATS); + if (rc) + return rc; + + req->flags =3D flags; + req->port_id =3D cpu_to_le16(pf->port_id); + req->tx_stat_host_addr =3D cpu_to_le64(bn->port_stats.hw_stats_map + + BNGE_TX_PORT_STATS_BYTE_OFFSET); + req->rx_stat_host_addr =3D cpu_to_le64(bn->port_stats.hw_stats_map); + return bnge_hwrm_req_send(bd, req); +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/n= et/ethernet/broadcom/bnge/bnge_hwrm_lib.h index f947ca66111..d43ccd4c7b3 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h @@ -61,4 +61,7 @@ int bnge_hwrm_set_link_setting(struct bnge_net *bn, bool = set_pause); int bnge_hwrm_set_pause(struct bnge_net *bn); int bnge_hwrm_vnic_set_tpa(struct bnge_dev *bd, struct bnge_vnic_info *vni= c, u32 tpa_flags); +int bnge_hwrm_port_qstats(struct bnge_dev *bd, u8 flags); +int bnge_hwrm_port_qstats_ext(struct bnge_dev *bd, u8 flags); +int bnge_hwrm_func_qstat_ext(struct bnge_dev *bd, struct bnge_stats_mem *s= tats); #endif /* _BNGE_HWRM_LIB_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 82bbc370700..f9d7f90a825 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -41,6 +41,10 @@ static void bnge_free_stats_mem(struct bnge_net *bn, { struct bnge_dev *bd =3D bn->bd; =20 + kfree(stats->hw_masks); + stats->hw_masks =3D NULL; + kfree(stats->sw_stats); + stats->sw_stats =3D NULL; if (stats->hw_stats) { dma_free_coherent(bd->dev, stats->len, stats->hw_stats, stats->hw_stats_map); @@ -49,7 +53,7 @@ static void bnge_free_stats_mem(struct bnge_net *bn, } =20 static int bnge_alloc_stats_mem(struct bnge_net *bn, - struct bnge_stats_mem *stats) + struct bnge_stats_mem *stats, bool alloc_masks) { struct bnge_dev *bd =3D bn->bd; =20 @@ -58,7 +62,20 @@ static int bnge_alloc_stats_mem(struct bnge_net *bn, if (!stats->hw_stats) return -ENOMEM; =20 + stats->sw_stats =3D kzalloc(stats->len, GFP_KERNEL); + if (!stats->sw_stats) + goto stats_mem_err; + + if (alloc_masks) { + stats->hw_masks =3D kzalloc(stats->len, GFP_KERNEL); + if (!stats->hw_masks) + goto stats_mem_err; + } return 0; + +stats_mem_err: + bnge_free_stats_mem(bn, stats); + return -ENOMEM; } =20 static void bnge_free_ring_stats(struct bnge_net *bn) @@ -74,9 +91,107 @@ static void bnge_free_ring_stats(struct bnge_net *bn) struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; =20 bnge_free_stats_mem(bn, &nqr->stats); + + kfree(nqr->sw_stats); + nqr->sw_stats =3D NULL; + } +} + +static void bnge_fill_masks(u64 *mask_arr, u64 mask, int count) +{ + int i; + + for (i =3D 0; i < count; i++) + mask_arr[i] =3D mask; +} + +void bnge_copy_hw_masks(u64 *mask_arr, __le64 *hw_mask_arr, int count) +{ + int i; + + for (i =3D 0; i < count; i++) + mask_arr[i] =3D le64_to_cpu(hw_mask_arr[i]); +} + +static void bnge_init_stats(struct bnge_net *bn) +{ + struct bnge_napi *bnapi =3D bn->bnapi[0]; + struct bnge_nq_ring_info *nqr; + struct bnge_stats_mem *stats; + struct bnge_dev *bd =3D bn->bd; + __le64 *rx_stats, *tx_stats; + int rc, rx_count, tx_count; + u64 *rx_masks, *tx_masks; + u8 flags; + + nqr =3D &bnapi->nq_ring; + stats =3D &nqr->stats; + rc =3D bnge_hwrm_func_qstat_ext(bd, stats); + if (rc) { + u64 mask =3D (1ULL << 48) - 1; + + bnge_fill_masks(stats->hw_masks, mask, stats->len / 8); + } + if (bn->flags & BNGE_FLAG_PORT_STATS) { + stats =3D &bn->port_stats; + rx_stats =3D stats->hw_stats; + rx_masks =3D stats->hw_masks; + rx_count =3D sizeof(struct rx_port_stats) / 8; + tx_stats =3D rx_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + tx_masks =3D rx_masks + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + tx_count =3D sizeof(struct tx_port_stats) / 8; + + flags =3D PORT_QSTATS_REQ_FLAGS_COUNTER_MASK; + rc =3D bnge_hwrm_port_qstats(bd, flags); + if (rc) { + u64 mask =3D (1ULL << 40) - 1; + + bnge_fill_masks(rx_masks, mask, rx_count); + bnge_fill_masks(tx_masks, mask, tx_count); + } else { + bnge_copy_hw_masks(rx_masks, rx_stats, rx_count); + bnge_copy_hw_masks(tx_masks, tx_stats, tx_count); + bnge_hwrm_port_qstats(bd, 0); + } + } + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { + stats =3D &bn->rx_port_stats_ext; + rx_stats =3D stats->hw_stats; + rx_masks =3D stats->hw_masks; + rx_count =3D sizeof(struct rx_port_stats_ext) / 8; + stats =3D &bn->tx_port_stats_ext; + tx_stats =3D stats->hw_stats; + tx_masks =3D stats->hw_masks; + tx_count =3D sizeof(struct tx_port_stats_ext) / 8; + + flags =3D PORT_QSTATS_EXT_REQ_FLAGS_COUNTER_MASK; + rc =3D bnge_hwrm_port_qstats_ext(bd, flags); + if (rc) { + u64 mask =3D (1ULL << 40) - 1; + + bnge_fill_masks(rx_masks, mask, rx_count); + if (tx_stats) + bnge_fill_masks(tx_masks, mask, tx_count); + } else { + bnge_copy_hw_masks(rx_masks, rx_stats, rx_count); + if (tx_stats) + bnge_copy_hw_masks(tx_masks, tx_stats, + tx_count); + bnge_hwrm_port_qstats_ext(bd, 0); + } } } =20 +static void bnge_free_port_stats(struct bnge_net *bn) +{ + bn->flags &=3D ~BNGE_FLAG_PORT_STATS; + bn->flags &=3D ~BNGE_FLAG_PORT_STATS_EXT; + + bnge_free_stats_mem(bn, &bn->port_stats); + bnge_free_stats_mem(bn, &bn->rx_port_stats_ext); + bnge_free_stats_mem(bn, &bn->tx_port_stats_ext); +} + static int bnge_alloc_ring_stats(struct bnge_net *bn) { struct bnge_dev *bd =3D bn->bd; @@ -89,13 +204,48 @@ static int bnge_alloc_ring_stats(struct bnge_net *bn) struct bnge_napi *bnapi =3D bn->bnapi[i]; struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; =20 + nqr->sw_stats =3D kzalloc(sizeof(*nqr->sw_stats), GFP_KERNEL); + if (!nqr->sw_stats) { + rc =3D -ENOMEM; + goto err_free_ring_stats; + } + nqr->stats.len =3D size; - rc =3D bnge_alloc_stats_mem(bn, &nqr->stats); + rc =3D bnge_alloc_stats_mem(bn, &nqr->stats, !i); if (rc) goto err_free_ring_stats; =20 nqr->hw_stats_ctx_id =3D INVALID_STATS_CTX_ID; } + + if (!bn->port_stats.hw_stats) { + bn->port_stats.len =3D BNGE_PORT_STATS_SIZE; + rc =3D bnge_alloc_stats_mem(bn, &bn->port_stats, true); + if (rc) + goto err_free_ring_stats; + + bn->flags |=3D BNGE_FLAG_PORT_STATS; + } + + if (!(bd->fw_cap & BNGE_FW_CAP_EXT_STATS_SUPPORTED)) + return 0; + + if (!bn->rx_port_stats_ext.hw_stats) { + bn->rx_port_stats_ext.len =3D sizeof(struct rx_port_stats_ext); + /* Extended stats are optional */ + rc =3D bnge_alloc_stats_mem(bn, &bn->rx_port_stats_ext, true); + if (!rc) + return 0; + } + + if (!bn->tx_port_stats_ext.hw_stats) { + bn->tx_port_stats_ext.len =3D sizeof(struct tx_port_stats_ext); + /* Extended stats are optional */ + rc =3D bnge_alloc_stats_mem(bn, &bn->tx_port_stats_ext, true); + if (!rc) + return 0; + } + bn->flags |=3D BNGE_FLAG_PORT_STATS_EXT; return 0; =20 err_free_ring_stats: @@ -868,6 +1018,7 @@ static void bnge_free_core(struct bnge_net *bn) bnge_free_nq_arrays(bn); bnge_free_ring_stats(bn); bnge_free_ring_grps(bn); + bnge_free_port_stats(bn); bnge_free_vnics(bn); kfree(bn->tx_ring_map); bn->tx_ring_map =3D NULL; @@ -959,6 +1110,8 @@ static int bnge_alloc_core(struct bnge_net *bn) if (rc) goto err_free_core; =20 + bnge_init_stats(bn); + rc =3D bnge_alloc_vnics(bn); if (rc) goto err_free_core; @@ -2581,6 +2734,35 @@ static int bnge_close(struct net_device *dev) return 0; } =20 +static void bnge_get_one_ring_err_stats(struct bnge_dev *bd, + struct bnge_total_ring_err_stats *stats, + struct bnge_nq_ring_info *nqr) +{ + struct bnge_sw_stats *sw_stats =3D nqr->sw_stats; + u64 *hw_stats =3D nqr->stats.sw_stats; + + stats->rx_total_l4_csum_errors +=3D sw_stats->rx.rx_l4_csum_errors; + stats->rx_total_resets +=3D sw_stats->rx.rx_resets; + stats->rx_total_buf_errors +=3D sw_stats->rx.rx_buf_errors; + stats->rx_total_oom_discards +=3D sw_stats->rx.rx_oom_discards; + stats->rx_total_netpoll_discards +=3D sw_stats->rx.rx_netpoll_discards; + stats->rx_total_ring_discards +=3D + BNGE_GET_RING_STATS64(hw_stats, rx_discard_pkts); + stats->tx_total_resets +=3D sw_stats->tx.tx_resets; + stats->tx_total_ring_discards +=3D + BNGE_GET_RING_STATS64(hw_stats, tx_discard_pkts); +} + +void bnge_get_ring_err_stats(struct bnge_net *bn, + struct bnge_total_ring_err_stats *stats) +{ + int i; + + for (i =3D 0; i < bn->bd->nq_nr_rings; i++) + bnge_get_one_ring_err_stats(bn->bd, stats, + &bn->bnapi[i]->nq_ring); +} + static const struct net_device_ops bnge_netdev_ops =3D { .ndo_open =3D bnge_open, .ndo_stop =3D bnge_close, diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index 41e3ca671a7..d7713bd57c6 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -225,6 +225,72 @@ struct bnge_tpa_info { #define BNGE_NQ_HDL_IDX(hdl) ((hdl) & BNGE_NQ_HDL_IDX_MASK) #define BNGE_NQ_HDL_TYPE(hdl) (((hdl) & BNGE_NQ_HDL_TYPE_MASK) >> \ BNGE_NQ_HDL_TYPE_SHIFT) +#define BNGE_GET_RING_STATS64(sw, counter) \ + (*((sw) + offsetof(struct ctx_hw_stats, counter) / 8)) + +#define BNGE_GET_RX_PORT_STATS64(sw, counter) \ + (*((sw) + offsetof(struct rx_port_stats, counter) / 8)) + +#define BNGE_GET_TX_PORT_STATS64(sw, counter) \ + (*((sw) + offsetof(struct tx_port_stats, counter) / 8)) + +#define BNGE_PORT_STATS_SIZE \ + (sizeof(struct rx_port_stats) + sizeof(struct tx_port_stats) + 1024) + +#define BNGE_TX_PORT_STATS_BYTE_OFFSET \ + (sizeof(struct rx_port_stats) + 512) + +#define BNGE_RX_STATS_OFFSET(counter) \ + (offsetof(struct rx_port_stats, counter) / 8) + +#define BNGE_TX_STATS_OFFSET(counter) \ + ((offsetof(struct tx_port_stats, counter) + \ + BNGE_TX_PORT_STATS_BYTE_OFFSET) / 8) + +#define BNGE_RX_STATS_EXT_OFFSET(counter) \ + (offsetof(struct rx_port_stats_ext, counter) / 8) + +#define BNGE_RX_STATS_EXT_NUM_LEGACY \ + BNGE_RX_STATS_EXT_OFFSET(rx_fec_corrected_blocks) + +#define BNGE_TX_STATS_EXT_OFFSET(counter) \ + (offsetof(struct tx_port_stats_ext, counter) / 8) + +struct bnge_total_ring_err_stats { + u64 rx_total_l4_csum_errors; + u64 rx_total_resets; + u64 rx_total_buf_errors; + u64 rx_total_oom_discards; + u64 rx_total_netpoll_discards; + u64 rx_total_ring_discards; + u64 tx_total_resets; + u64 tx_total_ring_discards; +}; + +struct bnge_rx_sw_stats { + u64 rx_l4_csum_errors; + u64 rx_resets; + u64 rx_buf_errors; + u64 rx_oom_discards; + u64 rx_netpoll_discards; +}; + +struct bnge_tx_sw_stats { + u64 tx_resets; +}; + +struct bnge_stats_mem { + u64 *sw_stats; + u64 *hw_masks; + void *hw_stats; + dma_addr_t hw_stats_map; + int len; +}; + +struct bnge_sw_stats { + struct bnge_rx_sw_stats rx; + struct bnge_tx_sw_stats tx; +}; =20 struct bnge_net { struct bnge_dev *bd; @@ -292,6 +358,22 @@ struct bnge_net { __be16 vxlan_port; __be16 nge_port; __be16 vxlan_gpe_port; + + u64 flags; +#define BNGE_FLAG_PORT_STATS 0x1 +#define BNGE_FLAG_PORT_STATS_EXT 0x2 + + struct bnge_total_ring_err_stats ring_err_stats_prev; + + struct bnge_stats_mem port_stats; + struct bnge_stats_mem rx_port_stats_ext; + struct bnge_stats_mem tx_port_stats_ext; + u16 fw_rx_stats_ext_size; + u16 fw_tx_stats_ext_size; + + u8 pri2cos_idx[8]; + u8 pri2cos_valid; + }; =20 #define BNGE_DEFAULT_RX_RING_SIZE 511 @@ -357,14 +439,6 @@ void bnge_set_ring_params(struct bnge_dev *bd); bnge_writeq(bd, (db)->db_key64 | DBR_TYPE_NQ_ARM | \ DB_RING_IDX(db, idx), (db)->doorbell) =20 -struct bnge_stats_mem { - u64 *sw_stats; - u64 *hw_masks; - void *hw_stats; - dma_addr_t hw_stats_map; - int len; -}; - struct nqe_cn { __le16 type; #define NQ_CN_TYPE_MASK 0x3fUL @@ -408,6 +482,7 @@ struct bnge_nq_ring_info { struct bnge_db_info nq_db; =20 struct bnge_stats_mem stats; + struct bnge_sw_stats *sw_stats; u32 hw_stats_ctx_id; u8 has_more_work:1; =20 @@ -568,4 +643,7 @@ u8 *__bnge_alloc_rx_frag(struct bnge_net *bn, dma_addr_= t *mapping, struct bnge_rx_ring_info *rxr, gfp_t gfp); int bnge_alloc_rx_netmem(struct bnge_net *bn, struct bnge_rx_ring_info *rx= r, u16 prod, gfp_t gfp); +void bnge_get_ring_err_stats(struct bnge_net *bn, + struct bnge_total_ring_err_stats *stats); +void bnge_copy_hw_masks(u64 *mask_arr, __le64 *hw_mask_arr, int count); #endif /* _BNGE_NETDEV_H_ */ --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-il1-f225.google.com (mail-il1-f225.google.com [209.85.166.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3E982346775 for ; Wed, 26 Nov 2025 19:50:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.225 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186656; cv=none; b=n+gNHK4ku3vDXzHRkwQGslTlhdJrTy3nAyXrYkBhsKsBVa2PMn5Un+7h8GhXWrIumDIyqQM8nqD8hu33jdeXCCE4yP86l/w1xyP61x1pg+IxjOM4dZuI/olYI5rQ8OkdhrB6+OYcPqdQIt+QODhljQwTP6DNZ6xlC/Db1LG+W74= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186656; c=relaxed/simple; bh=BdToKwzhHDUrBZibBWqCuDSMZ+L/D7pPWXii5IIWxJs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=r8332oYZfsVD4w9wV0h29ME4NWki8WI07z65gM3I0g6UD3SfdnL+TzT0dH4yxS0o5UvYdwbMxtubTLnUTzRYiuMwZr/TH2aFJB6oPJAeNzBS6Ke2KaraG2ZD4G8mqYgfuzmUV+CztiWq3mvXsjopgFy8mHxvEUo6YeSyRxzgLfo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=IIFWL6zU; arc=none smtp.client-ip=209.85.166.225 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="IIFWL6zU" Received: by mail-il1-f225.google.com with SMTP id e9e14a558f8ab-4336f492d75so999065ab.1 for ; Wed, 26 Nov 2025 11:50:54 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186653; x=1764791453; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=JbNNdnMVfUObfWb7xsLH9p8NbtGDNVo859r7X/oBhzg=; b=l6HSLtatZ113qCJ/r9VFj6A4tjfNVde09U6cttyI62yBXOV/vy2/gtAW3nYgFgi7at l+3SlQnmTtvBKRVfSHwa0Q2hTWx4ZtXPExvysYKcvInTPBld0Mg/DVOSM2DG2DsPfRvc sXg8Mh3V+xCOyOEXcN51jLsMkMGhhG08FYAl6J96cN9+MxjhQ4cbRYCN0jp7FuYcwfCX wlyBtBzFz+xe9pr2HsIhEhbARzWKq0P3+RgjdBZ6kprtfVEgzsBKZitfpHWRE4sC20AX tOOEk961J7XxJpnPvSsaaVJ8JPmLCpcuXnsZq9hEBBCBJDJURDAUp3gdJf9Eb2sodO71 87ig== X-Forwarded-Encrypted: i=1; AJvYcCV4BBFgOCgRwsml96XIKYN0WjWqM2d9OUtN45NstTloZVbiNAoKdxwyIZT+g+wio2KYWV8QD7eZqD19bbQ=@vger.kernel.org X-Gm-Message-State: AOJu0YyptUoJN1ZcpHtbKYfTtXtUcn3pBmqmPLTNFzC74Tg/VkrA4hEx OE6yHvxB5patsEalafjhMk76vFKuf0G7s6EpUS6LiRnwbAM4tXJ/WqJeNyKz5u19yj2eHZotQ6e T+zyuVhbOAtnSJhL4SuA4JCeHlnc+xzjiktx/cFD1UOGEoW84ybnH7Ijs1YdlEMHsZdrdWKlJYf O+t8qIgYXn2Ddr3qZcIaQhwbi4xH+/8/r6vzm/N1mbho+iljbWHLkTYXdz6X9CnO5fMJDcXkJms HR1glS/0y0vTnYQMIa4/o/d6Q== X-Gm-Gg: ASbGncv+WvavBBZK1oYYc9UxS2cGvx4oH1+aRNeizR/joGdmH8pvoZEt+jjrLESEuzN UNe+u3ZvxEypAzrSQ+DmEQnt3dpbigagu6eGnd0uAfMCTicbAfcG7XeuFKxgMm3hjZNdok4O9H8 4NbqBXhLG+UtlDvHPnbeR/X0sAWexKoyMRc7B0x5XINJvYXtVn8by0WPxLh7dkxe0ONGgJlh9cS fG7Rlf/C7AAvOvMh7ld0pCXJz5A7dyCHq0wfOyiHuQkM9PaGHThGi3b3qoht7AWYvIFS578hgZ0 QZeldVNOqNEMw1elQ0kOgOwRtTCDWXPmKp4LD5ErxTlz7za9s5fIvIcLLeRPHnhWzaTaKPYeAHJ g+idNehj+DQKqpXqkL8rszWJG163dQ8FfevhvTGDh0Sx4tbsavqGLPNhTUwJZHDTN+clFek8c9W Crbz91ceEht4SMaBiExAelLKK3LAH/qoVgeq1ysAB2FApxRFGG9ns= X-Google-Smtp-Source: AGHT+IHbEH2nFDYMapuxOXQkYueqdpbCMD0/e/gLp6LnojgoPPSB/uze5/K6D8izQWjyBMOvRDqXOn/k8S++ X-Received: by 2002:a05:6e02:b4c:b0:433:7900:f1b6 with SMTP id e9e14a558f8ab-435b9842e5emr173349995ab.7.1764186653398; Wed, 26 Nov 2025 11:50:53 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-11.dlp.protect.broadcom.com. [144.49.247.11]) by smtp-relay.gmail.com with ESMTPS id 8926c6da1cb9f-5b954b2dfb2sm1830113173.36.2025.11.26.11.50.53 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:53 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-2956cdcdc17so1159025ad.3 for ; Wed, 26 Nov 2025 11:50:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186652; x=1764791452; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JbNNdnMVfUObfWb7xsLH9p8NbtGDNVo859r7X/oBhzg=; b=IIFWL6zU0gIW5esnhSta1CTmxMA13CgQ/RdEEqy+rA5NqNN+YRvpRFtc/ZgDkNnMCb o3ACoKMERI/rmcCbHHG13x2vR1Q6CCAMtehR3T5bftR3yq84cQw+lZ/B6t++3VAiQfVN BbGuav9tHDDVqTX2UCax4vx/tR6Jl9e6jF5g8= X-Forwarded-Encrypted: i=1; AJvYcCXImDLTWIRMiLLF5LkSst947QwQ5Z7u0IUQfnWRVzXCk6Bg79R+1eewxLmPo+PQGD1QAhYAELi5B1/599k=@vger.kernel.org X-Received: by 2002:a17:902:ef51:b0:295:9b39:4533 with SMTP id d9443c01a7336-29b6c57210emr239858105ad.30.1764186651886; Wed, 26 Nov 2025 11:50:51 -0800 (PST) X-Received: by 2002:a17:902:ef51:b0:295:9b39:4533 with SMTP id d9443c01a7336-29b6c57210emr239857815ad.30.1764186651480; Wed, 26 Nov 2025 11:50:51 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:51 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 11/12] bng_en: Create per-PF workqueue and timer for asynchronous events Date: Thu, 27 Nov 2025 01:19:30 +0530 Message-ID: <20251126194931.455830-12-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Use a dedicated workqueue and timer for each PF to handle events. This sets up the infrastructure for the next patch, which will implement the event handling logic. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- drivers/net/ethernet/broadcom/bnge/bnge.h | 10 ++++++ .../net/ethernet/broadcom/bnge/bnge_core.c | 35 ++++++++++++++++++- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 31 ++++++++++++++++ .../net/ethernet/broadcom/bnge/bnge_netdev.h | 3 ++ 4 files changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethern= et/broadcom/bnge/bnge.h index 72d9865ba7b..0b75d6139b1 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h @@ -136,6 +136,7 @@ struct bnge_dev { unsigned long state; #define BNGE_STATE_DRV_REGISTERED 0 #define BNGE_STATE_OPEN 1 +#define BNGE_STATE_IN_SP_TASK 2 =20 u64 fw_cap; =20 @@ -208,9 +209,18 @@ struct bnge_dev { u8 max_q; u8 port_count; =20 + unsigned int current_interval; +#define BNGE_TIMER_INTERVAL HZ + + struct timer_list timer; struct bnge_irq *irq_tbl; u16 irqs_acquired; =20 + struct workqueue_struct *bnge_pf_wq; + struct work_struct sp_task; + unsigned long sp_event; +#define BNGE_PERIODIC_STATS_SP_EVENT 0 + /* To protect link related settings during link changes and * ethtool settings changes. */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/e= thernet/broadcom/bnge/bnge_core.c index 2c72dd34d50..dfa501f912a 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c @@ -238,6 +238,23 @@ static int bnge_map_db_bar(struct bnge_dev *bd) return 0; } =20 +static struct workqueue_struct * +bnge_create_workqueue_thread(struct bnge_dev *bd, char thread_name[]) +{ + struct workqueue_struct *wq; + char *wq_name; + + wq_name =3D kasprintf(GFP_KERNEL, "%s-%s", thread_name, + dev_name(bd->dev)); + if (!wq_name) + return NULL; + + wq =3D create_singlethread_workqueue(wq_name); + + kfree(wq_name); + return wq; +} + static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id= *ent) { unsigned int max_irqs; @@ -277,6 +294,10 @@ static int bnge_probe_one(struct pci_dev *pdev, const = struct pci_device_id *ent) goto err_devl_free; } =20 + INIT_WORK(&bd->sp_task, bnge_sp_task); + timer_setup(&bd->timer, bnge_timer, 0); + bd->current_interval =3D BNGE_TIMER_INTERVAL; + rc =3D bnge_init_hwrm_resources(bd); if (rc) goto err_bar_unmap; @@ -318,14 +339,24 @@ static int bnge_probe_one(struct pci_dev *pdev, const= struct pci_device_id *ent) goto err_config_uninit; } =20 + bd->bnge_pf_wq =3D bnge_create_workqueue_thread(bd, "bnge_pf_wq"); + if (!bd->bnge_pf_wq) { + dev_err(&pdev->dev, "Unable to create workqueue.\n"); + rc =3D -ENOMEM; + goto err_free_irq; + } + rc =3D bnge_netdev_alloc(bd, max_irqs); if (rc) - goto err_free_irq; + goto err_free_workq; =20 pci_save_state(pdev); =20 return 0; =20 +err_free_workq: + destroy_workqueue(bd->bnge_pf_wq); + err_free_irq: bnge_free_irqs(bd); =20 @@ -356,6 +387,8 @@ static void bnge_remove_one(struct pci_dev *pdev) =20 bnge_netdev_free(bd); =20 + destroy_workqueue(bd->bnge_pf_wq); + bnge_free_irqs(bd); =20 bnge_net_uninit_dflt_config(bd); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index f9d7f90a825..824374c1d9c 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -253,6 +253,33 @@ static int bnge_alloc_ring_stats(struct bnge_net *bn) return rc; } =20 +void bnge_timer(struct timer_list *t) +{ + struct bnge_dev *bd =3D timer_container_of(bd, t, timer); + struct bnge_net *bn =3D netdev_priv(bd->netdev); + struct net_device *dev =3D bd->netdev; + + if (!netif_running(dev) || !test_bit(BNGE_STATE_OPEN, &bd->state)) + return; + + if (atomic_read(&bn->intr_sem) !=3D 0) + goto bnge_restart_timer; + +bnge_restart_timer: + mod_timer(&bd->timer, jiffies + bd->current_interval); +} + +void bnge_sp_task(struct work_struct *work) +{ + struct bnge_dev *bd =3D container_of(work, struct bnge_dev, sp_task); + + set_bit(BNGE_STATE_IN_SP_TASK, &bd->state); + smp_mb__after_atomic(); + + smp_mb__before_atomic(); + clear_bit(BNGE_STATE_IN_SP_TASK, &bd->state); +} + static void bnge_free_nq_desc_arr(struct bnge_nq_ring_info *nqr) { struct bnge_ring_struct *ring =3D &nqr->ring_struct; @@ -2111,6 +2138,7 @@ static void bnge_disable_int_sync(struct bnge_net *bn) struct bnge_dev *bd =3D bn->bd; int i; =20 + atomic_inc(&bn->intr_sem); bnge_disable_int(bn); for (i =3D 0; i < bd->nq_nr_rings; i++) { int map_idx =3D bnge_cp_num_to_irq_num(bn, i); @@ -2124,6 +2152,7 @@ static void bnge_enable_int(struct bnge_net *bn) struct bnge_dev *bd =3D bn->bd; int i; =20 + atomic_set(&bn->intr_sem, 0); for (i =3D 0; i < bd->nq_nr_rings; i++) { struct bnge_napi *bnapi =3D bn->bnapi[i]; struct bnge_nq_ring_info *nqr =3D &bnapi->nq_ring; @@ -2677,6 +2706,7 @@ static int bnge_open_core(struct bnge_net *bn) =20 bnge_enable_int(bn); bnge_tx_enable(bn); + mod_timer(&bd->timer, jiffies + bd->current_interval); /* Poll link status and check for SFP+ module status */ mutex_lock(&bd->link_lock); bnge_get_port_module_status(bn); @@ -2718,6 +2748,7 @@ static void bnge_close_core(struct bnge_net *bn) clear_bit(BNGE_STATE_OPEN, &bd->state); bnge_shutdown_nic(bn); bnge_disable_napi(bn); + timer_delete_sync(&bd->timer); bnge_free_all_rings_bufs(bn); bnge_free_irq(bn); bnge_del_napi(bn); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.h index d7713bd57c6..9f5430d4180 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -352,6 +352,7 @@ struct bnge_net { =20 unsigned long state; #define BNGE_STATE_NAPI_DISABLED 0 + atomic_t intr_sem; =20 u32 msg_enable; u16 max_tpa; @@ -646,4 +647,6 @@ int bnge_alloc_rx_netmem(struct bnge_net *bn, struct bn= ge_rx_ring_info *rxr, void bnge_get_ring_err_stats(struct bnge_net *bn, struct bnge_total_ring_err_stats *stats); void bnge_copy_hw_masks(u64 *mask_arr, __le64 *hw_mask_arr, int count); +void bnge_timer(struct timer_list *t); +void bnge_sp_task(struct work_struct *work); #endif /* _BNGE_NETDEV_H_ */ --=20 2.47.3 From nobody Mon Dec 1 22:37:15 2025 Received: from mail-ua1-f97.google.com (mail-ua1-f97.google.com [209.85.222.97]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2F006346A08 for ; Wed, 26 Nov 2025 19:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.97 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186662; cv=none; b=gGPVfLyfTFmgQZ3xjPfE4Cwt3cF35H/MQa9cG60jkwq5SN4rSyhqzq6MEaSptbJQoeuWSdrGTvMk9x+aXEmDQl62jISLTYaDz6vCHpfwCOugq1WfzMbB7bAo+GEql4Ud4Upate2aS3i1i1lxCq0YSU9Z36tJMMihA/MwDcqCwxY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764186662; c=relaxed/simple; bh=mOMNgsdaJGLje42JWqQX6EDqvamZOoQqsVrpT5JU02Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jIrvq640NpmNbZWEsGPXm7GFkEUpeJudOb1txqOz+JTELNFZ/+7N4XVt4X61Uwv8heXxvKQe7IkHEyBCw9SodcznhmyEaN/fOeJR+2B8iiDl/bPr8vti3+z09H8inQ8rr6CU3Yy1FnYMjYgnQgn7XZnUp6icSchQpDa3ZjZ0ZCE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=MwFzhtE/; arc=none smtp.client-ip=209.85.222.97 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="MwFzhtE/" Received: by mail-ua1-f97.google.com with SMTP id a1e0cc1a2514c-9372149216bso72695241.3 for ; Wed, 26 Nov 2025 11:50:58 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764186658; x=1764791458; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=m5S4fHoRERV2MSCcvgLtmo8rkmlmMx1nGkGx6XewVPE=; b=an0TQ63KMexyeLD6nKCsKlxBH5JJGrWoVUUWc4ecWxAdQ6sqd1bfAhODzXGh7XlnDX ey1FaV4MjbL2hQuwmkX9svqSkFMI48t/+IiMPdhV1UX6NWMgLLmrwkkeL0yxpbnB8iIQ OHvjl8JUZyS9fLyA6763uFkl5+hU8wlEUWZZJz3BY6OUwb9vqwmTG3dh1Qmio67OU08T BXykG2v/HBZtw3VbQY1XQqhnomQIuDW6kU4IHxkcOZOAd2RL/yWWhQHi8aEA21L9vP9R t2TgttLP5KuD0CfmcN8/1ZH9agUVu/pHuoygy3rg4bOoHu4gOaB/An1IfnW4Nc2RAneJ /QHg== X-Forwarded-Encrypted: i=1; AJvYcCWuWQz0vG7cN5TCmqRMmyUW/HUzI4FMODxWY1CN+So1CzgUGj9iWBv1GCW1kHu2X3HtD33HiqzJb2d8Pao=@vger.kernel.org X-Gm-Message-State: AOJu0YyQREPStCDrqaPFeMkMOCR0bVpgIg0u+seoWYIlMO4I5Ft0GE5V V1HItehyU+cU5ljINiaprdi7gTg5lhGT0L2OJcdupGt41O3y811l/hfG6t5hvi+HuFe/GrQ70d+ 1tRo3nO+qmYdmzYu8QSSvJNkuB/j08rfjUyZR0AsPxzLwawUT19Q42Ux95VnMc6OR7keXAf3ZHZ wBvNkPP4dE+77uXcZS/26sei1BEy3IVZMHJnA7u9MEPKGiyfFU8zboCYKXQr9OT9nkCI7W5r1q7 6MnOy+rX8iduAM1YHCKji6ZlerJ X-Gm-Gg: ASbGncuOOm0mHB0WS3i27MUrG4g7/DrKtYbC6OexwmSOGWPHQhQrqcVHOunS8hyweX4 xJxryVptYmdRHwd1Na0IIkrILxsxMpVPt5M0snAQaBw9PGclr3k6HMHxy4WajxbI4S2hiCOJxS0 USx30E3BV9yQvr326F0kDsiDHVhY0aHudS13tFKjCakqzaE7D0dPOui6tUpz1m7YZ1mkDFLY57y uXylkf3eVhvuz+ZMyV6E2ge+Lo3PHw0nCteAABAKZgZboCWq21biwnThqiZr3OUhTZ4GEgvBprT JckRNfwBhEKMZythwMRINkT+GRsjiLN0AdJk8QaHKzPr1bgaRsNTXvOR3zi61Jn5Um6L/BDj4WO oJGhVzCd8PAePipOkpudHkiZCk6dF3R1z4FEDhuMsNoMCPDlDXI5ggOuew2l0beRalUcd2zY10S ojBYcIygkYrd36aXtP+VYaKHWSq+0hdqEXB28/Fmizv+kLHtLO4So= X-Google-Smtp-Source: AGHT+IEt4BIf4MjyRo/VwlO1ZW+YSl+hDiDM1xRVOZd/hTBRtSgiV1kq3/z7xjyueRIJ4CdqOA4E6kGXytnC X-Received: by 2002:a05:6102:4189:b0:5d6:254f:4e24 with SMTP id ada2fe7eead31-5e2243dd64amr3109567137.32.1764186657968; Wed, 26 Nov 2025 11:50:57 -0800 (PST) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-11.dlp.protect.broadcom.com. [144.49.247.11]) by smtp-relay.gmail.com with ESMTPS id ada2fe7eead31-5e1bd92ec2bsm2521201137.1.2025.11.26.11.50.57 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Nov 2025 11:50:57 -0800 (PST) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f197.google.com with SMTP id d9443c01a7336-297ddb3c707so826405ad.2 for ; Wed, 26 Nov 2025 11:50:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1764186656; x=1764791456; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=m5S4fHoRERV2MSCcvgLtmo8rkmlmMx1nGkGx6XewVPE=; b=MwFzhtE/VriYPuHpEZa6jVOQAF9NjGgw/LgMP4GKlnA3isBG04z3FVfyHQlelBWC3Z SAMrWuvlvA2+ziKqBY8UlRqUWRSSkPXid3hC7TlMjInqDY7OeK0TayIvrYTVRvgGLEAe ORToP9iIcZlhdckWKRX0Nvx8WdsHOsdqVRk00= X-Forwarded-Encrypted: i=1; AJvYcCVyZgt1VJP99E6CF0t2wNfP4JNJbQh4FtLkzfaRaJGlo+GejfEqHgUOtolgR+8DiBMQ0hrUkmPq7yScZHw=@vger.kernel.org X-Received: by 2002:a17:902:d58c:b0:294:fcae:826 with SMTP id d9443c01a7336-29bab2fa50bmr91295875ad.59.1764186656361; Wed, 26 Nov 2025 11:50:56 -0800 (PST) X-Received: by 2002:a17:902:d58c:b0:294:fcae:826 with SMTP id d9443c01a7336-29bab2fa50bmr91295605ad.59.1764186655972; Wed, 26 Nov 2025 11:50:55 -0800 (PST) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b25e638sm206782375ad.58.2025.11.26.11.50.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 11:50:55 -0800 (PST) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Rajashekar Hudumula Subject: [v3, net-next 12/12] bng_en: Query firmware for statistics and accumulate Date: Thu, 27 Nov 2025 01:19:31 +0530 Message-ID: <20251126194931.455830-13-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> References: <20251126194931.455830-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Content-Type: text/plain; charset="utf-8" Use the per-PF workqueue and timer infrastructure to asynchronously fetch statistics from firmware and accumulate them in the PF context. With this patch, ethtool -S exposes all hardware stats. Signed-off-by: Bhargava Marreddy Reviewed-by: Vikas Gupta Reviewed-by: Rajashekar Hudumula --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net= /ethernet/broadcom/bnge/bnge_netdev.c index 824374c1d9c..262713260a4 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -253,6 +253,17 @@ static int bnge_alloc_ring_stats(struct bnge_net *bn) return rc; } =20 +static void __bnge_queue_sp_work(struct bnge_dev *bd) +{ + queue_work(bd->bnge_pf_wq, &bd->sp_task); +} + +static void bnge_queue_sp_work(struct bnge_dev *bd, unsigned int event) +{ + set_bit(event, &bd->sp_event); + __bnge_queue_sp_work(bd); +} + void bnge_timer(struct timer_list *t) { struct bnge_dev *bd =3D timer_container_of(bd, t, timer); @@ -265,16 +276,100 @@ void bnge_timer(struct timer_list *t) if (atomic_read(&bn->intr_sem) !=3D 0) goto bnge_restart_timer; =20 + if (BNGE_LINK_IS_UP(bd) && bn->stats_coal_ticks) + bnge_queue_sp_work(bd, BNGE_PERIODIC_STATS_SP_EVENT); + bnge_restart_timer: mod_timer(&bd->timer, jiffies + bd->current_interval); } =20 +static void bnge_add_one_ctr(u64 hw, u64 *sw, u64 mask) +{ + u64 sw_tmp; + + hw &=3D mask; + sw_tmp =3D (*sw & ~mask) | hw; + if (hw < (*sw & mask)) + sw_tmp +=3D mask + 1; + WRITE_ONCE(*sw, sw_tmp); +} + +static void __bnge_accumulate_stats(__le64 *hw_stats, u64 *sw_stats, u64 *= masks, + int count) +{ + int i; + + for (i =3D 0; i < count; i++) { + u64 hw =3D le64_to_cpu(READ_ONCE(hw_stats[i])); + + if (masks[i] =3D=3D -1ULL) + sw_stats[i] =3D hw; + else + bnge_add_one_ctr(hw, &sw_stats[i], masks[i]); + } +} + +static void bnge_accumulate_stats(struct bnge_stats_mem *stats) +{ + if (!stats->hw_stats) + return; + + __bnge_accumulate_stats(stats->hw_stats, stats->sw_stats, + stats->hw_masks, stats->len / 8); +} + +static void bnge_accumulate_all_stats(struct bnge_dev *bd) +{ + struct bnge_net *bn =3D netdev_priv(bd->netdev); + struct bnge_stats_mem *ring0_stats; + int i; + + for (i =3D 0; i < bd->nq_nr_rings; i++) { + struct bnge_napi *bnapi =3D bn->bnapi[i]; + struct bnge_nq_ring_info *nqr; + struct bnge_stats_mem *stats; + + nqr =3D &bnapi->nq_ring; + stats =3D &nqr->stats; + if (!i) + ring0_stats =3D stats; + __bnge_accumulate_stats(stats->hw_stats, stats->sw_stats, + ring0_stats->hw_masks, + ring0_stats->len / 8); + } + if (bn->flags & BNGE_FLAG_PORT_STATS) { + struct bnge_stats_mem *stats =3D &bn->port_stats; + __le64 *hw_stats =3D stats->hw_stats; + u64 *sw_stats =3D stats->sw_stats; + u64 *masks =3D stats->hw_masks; + int cnt; + + cnt =3D sizeof(struct rx_port_stats) / 8; + __bnge_accumulate_stats(hw_stats, sw_stats, masks, cnt); + + hw_stats +=3D BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + sw_stats +=3D BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + masks +=3D BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; + cnt =3D sizeof(struct tx_port_stats) / 8; + __bnge_accumulate_stats(hw_stats, sw_stats, masks, cnt); + } + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { + bnge_accumulate_stats(&bn->rx_port_stats_ext); + bnge_accumulate_stats(&bn->tx_port_stats_ext); + } +} + void bnge_sp_task(struct work_struct *work) { struct bnge_dev *bd =3D container_of(work, struct bnge_dev, sp_task); =20 set_bit(BNGE_STATE_IN_SP_TASK, &bd->state); smp_mb__after_atomic(); + if (test_and_clear_bit(BNGE_PERIODIC_STATS_SP_EVENT, &bd->sp_event)) { + bnge_hwrm_port_qstats(bd, 0); + bnge_hwrm_port_qstats_ext(bd, 0); + bnge_accumulate_all_stats(bd); + } =20 smp_mb__before_atomic(); clear_bit(BNGE_STATE_IN_SP_TASK, &bd->state); --=20 2.47.3