diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom')
26 files changed, 666 insertions, 194 deletions
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index 9fdef874f5ca..666522d64775 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -25,6 +25,7 @@ config B44 select SSB select MII select PHYLIB + select FIXED_PHY if BCM47XX help If you have a network (Ethernet) controller of this type, say Y or M here. diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c index 63f1a8c3a7fb..dd80ccfca19d 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c @@ -163,11 +163,30 @@ static void bcmasp_set_msglevel(struct net_device *dev, u32 level) static void bcmasp_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct bcmasp_intf *intf = netdev_priv(dev); + struct bcmasp_priv *priv = intf->parent; + struct device *kdev = &priv->pdev->dev; + u32 phy_wolopts = 0; + + if (dev->phydev) { + phy_ethtool_get_wol(dev->phydev, wol); + phy_wolopts = wol->wolopts; + } + + /* MAC is not wake-up capable, return what the PHY does */ + if (!device_can_wakeup(kdev)) + return; + + /* Overlay MAC capabilities with that of the PHY queried before */ + wol->supported |= BCMASP_SUPPORTED_WAKE; + wol->wolopts |= intf->wolopts; + + /* Return the PHY configured magic password */ + if (phy_wolopts & WAKE_MAGICSECURE) + return; - wol->supported = BCMASP_SUPPORTED_WAKE; - wol->wolopts = intf->wolopts; memset(wol->sopass, 0, sizeof(wol->sopass)); + /* Otherwise the MAC one */ if (wol->wolopts & WAKE_MAGICSECURE) memcpy(wol->sopass, intf->sopass, sizeof(intf->sopass)); } @@ -177,10 +196,21 @@ static int bcmasp_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct bcmasp_intf *intf = netdev_priv(dev); struct bcmasp_priv *priv = intf->parent; struct device *kdev = &priv->pdev->dev; + int ret = 0; + + /* Try Wake-on-LAN from the PHY first */ + if (dev->phydev) { + ret = phy_ethtool_set_wol(dev->phydev, wol); + if (ret != -EOPNOTSUPP && wol->wolopts) + return ret; + } if (!device_can_wakeup(kdev)) return -EOPNOTSUPP; + if (wol->wolopts & ~BCMASP_SUPPORTED_WAKE) + return -EINVAL; + /* Interface Specific */ intf->wolopts = wol->wolopts; if (intf->wolopts & WAKE_MAGICSECURE) diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 0353359c3fe9..888f28f11406 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -31,6 +31,7 @@ #include <linux/ssb/ssb.h> #include <linux/slab.h> #include <linux/phy.h> +#include <linux/phy_fixed.h> #include <linux/uaccess.h> #include <asm/io.h> @@ -2233,7 +2234,6 @@ static int b44_register_phy_one(struct b44 *bp) struct mii_bus *mii_bus; struct ssb_device *sdev = bp->sdev; struct phy_device *phydev; - char bus_id[MII_BUS_ID_SIZE + 3]; struct ssb_sprom *sprom = &sdev->bus->sprom; int err; @@ -2260,27 +2260,26 @@ static int b44_register_phy_one(struct b44 *bp) goto err_out_mdiobus; } - if (!mdiobus_is_registered_device(bp->mii_bus, bp->phy_addr) && - (sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) { - + phydev = mdiobus_get_phy(bp->mii_bus, bp->phy_addr); + if (!phydev && + sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM)) { dev_info(sdev->dev, "could not find PHY at %i, use fixed one\n", bp->phy_addr); - bp->phy_addr = 0; - snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, "fixed-0", - bp->phy_addr); - } else { - snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id, - bp->phy_addr); + phydev = fixed_phy_register_100fd(); + if (!IS_ERR(phydev)) + bp->phy_addr = phydev->mdio.addr; } - phydev = phy_connect(bp->dev, bus_id, &b44_adjust_link, - PHY_INTERFACE_MODE_MII); - if (IS_ERR(phydev)) { + if (IS_ERR_OR_NULL(phydev)) + err = -ENODEV; + else + err = phy_connect_direct(bp->dev, phydev, &b44_adjust_link, + PHY_INTERFACE_MODE_MII); + if (err) { dev_err(sdev->dev, "could not attach PHY at %i\n", bp->phy_addr); - err = PTR_ERR(phydev); goto err_out_mdiobus_unregister; } @@ -2293,7 +2292,6 @@ static int b44_register_phy_one(struct b44 *bp) linkmode_copy(phydev->advertising, phydev->supported); bp->old_link = 0; - bp->phy_addr = phydev->mdio.addr; phy_attached_info(phydev); @@ -2311,10 +2309,15 @@ err_out: static void b44_unregister_phy_one(struct b44 *bp) { - struct net_device *dev = bp->dev; struct mii_bus *mii_bus = bp->mii_bus; + struct net_device *dev = bp->dev; + struct phy_device *phydev; + + phydev = dev->phydev; - phy_disconnect(dev->phydev); + phy_disconnect(phydev); + if (phy_is_pseudo_fixed_link(phydev)) + fixed_phy_unregister(phydev); mdiobus_unregister(mii_bus); mdiobus_free(mii_bus); } diff --git a/drivers/net/ethernet/broadcom/bnge/Makefile b/drivers/net/ethernet/broadcom/bnge/Makefile index 6142d9c57f49..ea6596854e5c 100644 --- a/drivers/net/ethernet/broadcom/bnge/Makefile +++ b/drivers/net/ethernet/broadcom/bnge/Makefile @@ -9,4 +9,5 @@ bng_en-y := bnge_core.o \ bnge_rmem.o \ bnge_resc.o \ bnge_netdev.o \ - bnge_ethtool.o + bnge_ethtool.o \ + bnge_auxr.o diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h index 7aed5f81cd51..411744894349 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge.h @@ -11,6 +11,7 @@ #include <linux/bnxt/hsi.h> #include "bnge_rmem.h" #include "bnge_resc.h" +#include "bnge_auxr.h" #define DRV_VER_MAJ 1 #define DRV_VER_MIN 15 @@ -22,6 +23,12 @@ enum board_idx { BCM57708, }; +struct bnge_auxr_priv { + struct auxiliary_device aux_dev; + struct bnge_auxr_dev *auxr_dev; + int id; +}; + struct bnge_pf_info { u16 fw_fid; u16 port_id; @@ -197,6 +204,9 @@ struct bnge_dev { struct bnge_irq *irq_tbl; u16 irqs_acquired; + + struct bnge_auxr_priv *aux_priv; + struct bnge_auxr_dev *auxr_dev; }; static inline bool bnge_is_roce_en(struct bnge_dev *bd) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_auxr.c b/drivers/net/ethernet/broadcom/bnge/bnge_auxr.c new file mode 100644 index 000000000000..d64592b64e17 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_auxr.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2025 Broadcom. + +#include <linux/module.h> + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/netdevice.h> +#include <linux/rtnetlink.h> +#include <linux/bitops.h> +#include <linux/irq.h> +#include <asm/byteorder.h> +#include <linux/bitmap.h> +#include <linux/auxiliary_bus.h> +#include <linux/bnxt/hsi.h> + +#include "bnge.h" +#include "bnge_hwrm.h" +#include "bnge_auxr.h" + +static DEFINE_IDA(bnge_aux_dev_ids); + +static void bnge_fill_msix_vecs(struct bnge_dev *bd, + struct bnge_msix_info *info) +{ + struct bnge_auxr_dev *auxr_dev = bd->auxr_dev; + int num_msix, i; + + if (!auxr_dev->auxr_info->msix_requested) { + dev_warn(bd->dev, "Requested MSI-X vectors not allocated\n"); + return; + } + num_msix = auxr_dev->auxr_info->msix_requested; + for (i = 0; i < num_msix; i++) { + info[i].vector = bd->irq_tbl[i].vector; + info[i].db_offset = bd->db_offset; + info[i].ring_idx = i; + } +} + +int bnge_register_dev(struct bnge_auxr_dev *auxr_dev, + void *handle) +{ + struct bnge_dev *bd = pci_get_drvdata(auxr_dev->pdev); + struct bnge_auxr_info *auxr_info; + int rc = 0; + + netdev_lock(bd->netdev); + mutex_lock(&auxr_dev->auxr_dev_lock); + if (!bd->irq_tbl) { + rc = -ENODEV; + goto exit; + } + + if (!bnge_aux_has_enough_resources(bd)) { + rc = -ENOMEM; + goto exit; + } + + auxr_info = auxr_dev->auxr_info; + auxr_info->handle = handle; + + auxr_info->msix_requested = bd->aux_num_msix; + + bnge_fill_msix_vecs(bd, bd->auxr_dev->msix_info); + auxr_dev->flags |= BNGE_ARDEV_MSIX_ALLOC; + +exit: + mutex_unlock(&auxr_dev->auxr_dev_lock); + netdev_unlock(bd->netdev); + return rc; +} +EXPORT_SYMBOL(bnge_register_dev); + +void bnge_unregister_dev(struct bnge_auxr_dev *auxr_dev) +{ + struct bnge_dev *bd = pci_get_drvdata(auxr_dev->pdev); + struct bnge_auxr_info *auxr_info; + + auxr_info = auxr_dev->auxr_info; + netdev_lock(bd->netdev); + mutex_lock(&auxr_dev->auxr_dev_lock); + if (auxr_info->msix_requested) + auxr_dev->flags &= ~BNGE_ARDEV_MSIX_ALLOC; + auxr_info->msix_requested = 0; + + mutex_unlock(&auxr_dev->auxr_dev_lock); + netdev_unlock(bd->netdev); +} +EXPORT_SYMBOL(bnge_unregister_dev); + +int bnge_send_msg(struct bnge_auxr_dev *auxr_dev, struct bnge_fw_msg *fw_msg) +{ + struct bnge_dev *bd = pci_get_drvdata(auxr_dev->pdev); + struct output *resp; + struct input *req; + u32 resp_len; + int rc; + + rc = bnge_hwrm_req_init(bd, req, 0 /* don't care */); + if (rc) + return rc; + + rc = bnge_hwrm_req_replace(bd, req, fw_msg->msg, fw_msg->msg_len); + if (rc) + goto drop_req; + + bnge_hwrm_req_timeout(bd, req, fw_msg->timeout); + resp = bnge_hwrm_req_hold(bd, req); + rc = bnge_hwrm_req_send(bd, req); + resp_len = le16_to_cpu(resp->resp_len); + if (resp_len) { + if (fw_msg->resp_max_len < resp_len) + resp_len = fw_msg->resp_max_len; + + memcpy(fw_msg->resp, resp, resp_len); + } +drop_req: + bnge_hwrm_req_drop(bd, req); + return rc; +} +EXPORT_SYMBOL(bnge_send_msg); + +void bnge_rdma_aux_device_uninit(struct bnge_dev *bd) +{ + struct bnge_auxr_priv *aux_priv; + struct auxiliary_device *adev; + + /* Skip if no auxiliary device init was done. */ + if (!bd->aux_priv) + return; + + aux_priv = bd->aux_priv; + adev = &aux_priv->aux_dev; + auxiliary_device_uninit(adev); +} + +static void bnge_aux_dev_release(struct device *dev) +{ + struct bnge_auxr_priv *aux_priv = + container_of(dev, struct bnge_auxr_priv, aux_dev.dev); + struct bnge_dev *bd = pci_get_drvdata(aux_priv->auxr_dev->pdev); + + ida_free(&bnge_aux_dev_ids, aux_priv->id); + kfree(aux_priv->auxr_dev->auxr_info); + bd->auxr_dev = NULL; + kfree(aux_priv->auxr_dev); + kfree(aux_priv); + bd->aux_priv = NULL; +} + +void bnge_rdma_aux_device_del(struct bnge_dev *bd) +{ + if (!bd->auxr_dev) + return; + + auxiliary_device_delete(&bd->aux_priv->aux_dev); +} + +static void bnge_set_auxr_dev_info(struct bnge_auxr_dev *auxr_dev, + struct bnge_dev *bd) +{ + auxr_dev->pdev = bd->pdev; + auxr_dev->l2_db_size = bd->db_size; + auxr_dev->l2_db_size_nc = bd->db_size; + auxr_dev->l2_db_offset = bd->db_offset; + mutex_init(&auxr_dev->auxr_dev_lock); + + if (bd->flags & BNGE_EN_ROCE_V1) + auxr_dev->flags |= BNGE_ARDEV_ROCEV1_SUPP; + if (bd->flags & BNGE_EN_ROCE_V2) + auxr_dev->flags |= BNGE_ARDEV_ROCEV2_SUPP; + + auxr_dev->chip_num = bd->chip_num; + auxr_dev->hw_ring_stats_size = bd->hw_ring_stats_size; + auxr_dev->pf_port_id = bd->pf.port_id; + auxr_dev->en_state = bd->state; + auxr_dev->bar0 = bd->bar0; +} + +void bnge_rdma_aux_device_add(struct bnge_dev *bd) +{ + struct auxiliary_device *aux_dev; + int rc; + + if (!bd->auxr_dev) + return; + + aux_dev = &bd->aux_priv->aux_dev; + rc = auxiliary_device_add(aux_dev); + if (rc) { + dev_warn(bd->dev, "Failed to add auxiliary device for ROCE\n"); + auxiliary_device_uninit(aux_dev); + bd->flags &= ~BNGE_EN_ROCE; + } + + bd->auxr_dev->net = bd->netdev; +} + +void bnge_rdma_aux_device_init(struct bnge_dev *bd) +{ + struct auxiliary_device *aux_dev; + struct bnge_auxr_info *auxr_info; + struct bnge_auxr_priv *aux_priv; + struct bnge_auxr_dev *auxr_dev; + int rc; + + if (!bnge_is_roce_en(bd)) + return; + + aux_priv = kzalloc(sizeof(*aux_priv), GFP_KERNEL); + if (!aux_priv) + goto exit; + + aux_priv->id = ida_alloc(&bnge_aux_dev_ids, GFP_KERNEL); + if (aux_priv->id < 0) { + dev_warn(bd->dev, "ida alloc failed for aux device\n"); + kfree(aux_priv); + goto exit; + } + + aux_dev = &aux_priv->aux_dev; + aux_dev->id = aux_priv->id; + aux_dev->name = "rdma"; + aux_dev->dev.parent = &bd->pdev->dev; + aux_dev->dev.release = bnge_aux_dev_release; + + rc = auxiliary_device_init(aux_dev); + if (rc) { + ida_free(&bnge_aux_dev_ids, aux_priv->id); + kfree(aux_priv); + goto exit; + } + bd->aux_priv = aux_priv; + + auxr_dev = kzalloc(sizeof(*auxr_dev), GFP_KERNEL); + if (!auxr_dev) + goto aux_dev_uninit; + + aux_priv->auxr_dev = auxr_dev; + + auxr_info = kzalloc(sizeof(*auxr_info), GFP_KERNEL); + if (!auxr_info) + goto aux_dev_uninit; + + auxr_dev->auxr_info = auxr_info; + bd->auxr_dev = auxr_dev; + bnge_set_auxr_dev_info(auxr_dev, bd); + + return; + +aux_dev_uninit: + auxiliary_device_uninit(aux_dev); +exit: + bd->flags &= ~BNGE_EN_ROCE; +} diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_auxr.h b/drivers/net/ethernet/broadcom/bnge/bnge_auxr.h new file mode 100644 index 000000000000..6c5c15ef2b0a --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnge/bnge_auxr.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2025 Broadcom */ + +#ifndef _BNGE_AUXR_H_ +#define _BNGE_AUXR_H_ + +#include <linux/auxiliary_bus.h> + +#define BNGE_MIN_ROCE_CP_RINGS 2 +#define BNGE_MIN_ROCE_STAT_CTXS 1 + +#define BNGE_MAX_ROCE_MSIX 64 + +struct hwrm_async_event_cmpl; +struct bnge; + +struct bnge_msix_info { + u32 vector; + u32 ring_idx; + u32 db_offset; +}; + +struct bnge_fw_msg { + void *msg; + int msg_len; + void *resp; + int resp_max_len; + int timeout; +}; + +struct bnge_auxr_info { + void *handle; + u16 msix_requested; +}; + +enum { + BNGE_ARDEV_ROCEV1_SUPP = BIT(0), + BNGE_ARDEV_ROCEV2_SUPP = BIT(1), + BNGE_ARDEV_MSIX_ALLOC = BIT(2), +}; + +#define BNGE_ARDEV_ROCE_SUPP (BNGE_ARDEV_ROCEV1_SUPP | \ + BNGE_ARDEV_ROCEV2_SUPP) + +struct bnge_auxr_dev { + struct net_device *net; + struct pci_dev *pdev; + void __iomem *bar0; + + struct bnge_msix_info msix_info[BNGE_MAX_ROCE_MSIX]; + + u32 flags; + + struct bnge_auxr_info *auxr_info; + + /* Doorbell BAR size in bytes mapped by L2 driver. */ + int l2_db_size; + /* Doorbell BAR size in bytes mapped as non-cacheable. */ + int l2_db_size_nc; + /* Doorbell offset in bytes within l2_db_size_nc. */ + int l2_db_offset; + + u16 chip_num; + u16 hw_ring_stats_size; + u16 pf_port_id; + unsigned long en_state; + + u16 auxr_num_msix_vec; + u16 auxr_num_ctxs; + + /* serialize auxr operations */ + struct mutex auxr_dev_lock; +}; + +void bnge_rdma_aux_device_uninit(struct bnge_dev *bdev); +void bnge_rdma_aux_device_del(struct bnge_dev *bdev); +void bnge_rdma_aux_device_add(struct bnge_dev *bdev); +void bnge_rdma_aux_device_init(struct bnge_dev *bdev); +int bnge_register_dev(struct bnge_auxr_dev *adev, + void *handle); +void bnge_unregister_dev(struct bnge_auxr_dev *adev); +int bnge_send_msg(struct bnge_auxr_dev *adev, struct bnge_fw_msg *fw_msg); + +#endif /* _BNGE_AUXR_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c index 2c72dd34d50d..c94e132bebc8 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c @@ -41,6 +41,11 @@ static void bnge_print_device_info(struct pci_dev *pdev, enum board_idx idx) bool bnge_aux_registered(struct bnge_dev *bd) { + struct bnge_auxr_dev *ba_dev = bd->auxr_dev; + + if (ba_dev && ba_dev->auxr_info->msix_requested) + return true; + return false; } @@ -312,16 +317,20 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) spin_lock_init(&bd->db_lock); #endif + bnge_rdma_aux_device_init(bd); + rc = bnge_alloc_irqs(bd); if (rc) { dev_err(&pdev->dev, "Error IRQ allocation rc = %d\n", rc); - goto err_config_uninit; + goto err_uninit_auxr; } rc = bnge_netdev_alloc(bd, max_irqs); if (rc) goto err_free_irq; + bnge_rdma_aux_device_add(bd); + pci_save_state(pdev); return 0; @@ -329,6 +338,9 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) err_free_irq: bnge_free_irqs(bd); +err_uninit_auxr: + bnge_rdma_aux_device_uninit(bd); + err_config_uninit: bnge_net_uninit_dflt_config(bd); @@ -354,10 +366,14 @@ static void bnge_remove_one(struct pci_dev *pdev) { struct bnge_dev *bd = pci_get_drvdata(pdev); + bnge_rdma_aux_device_del(bd); + bnge_netdev_free(bd); bnge_free_irqs(bd); + bnge_rdma_aux_device_uninit(bd); + bnge_net_uninit_dflt_config(bd); bnge_devlink_unregister(bd); diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c index 0f971af24142..c3087e5cd875 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c @@ -98,6 +98,46 @@ void bnge_hwrm_req_alloc_flags(struct bnge_dev *bd, void *req, gfp_t gfp) ctx->gfp = gfp; } +int bnge_hwrm_req_replace(struct bnge_dev *bd, void *req, void *new_req, + u32 len) +{ + struct bnge_hwrm_ctx *ctx = __hwrm_ctx_get(bd, req); + struct input *internal_req = req; + u16 req_type; + + if (!ctx) + return -EINVAL; + + if (len > BNGE_HWRM_CTX_OFFSET) + return -E2BIG; + + /* free any existing slices */ + ctx->allocated = BNGE_HWRM_DMA_SIZE - BNGE_HWRM_CTX_OFFSET; + if (ctx->slice_addr) { + dma_free_coherent(bd->dev, ctx->slice_size, + ctx->slice_addr, ctx->slice_handle); + ctx->slice_addr = NULL; + } + ctx->gfp = GFP_KERNEL; + + if ((bd->fw_cap & BNGE_FW_CAP_SHORT_CMD) || len > BNGE_HWRM_MAX_REQ_LEN) { + memcpy(internal_req, new_req, len); + } else { + internal_req->req_type = ((struct input *)new_req)->req_type; + ctx->req = new_req; + } + + ctx->req_len = len; + ctx->req->resp_addr = cpu_to_le64(ctx->dma_handle + + BNGE_HWRM_RESP_OFFSET); + + /* update sentinel for potentially new request type */ + req_type = le16_to_cpu(internal_req->req_type); + ctx->sentinel = bnge_cal_sentinel(ctx, req_type); + + return 0; +} + void bnge_hwrm_req_flags(struct bnge_dev *bd, void *req, enum bnge_hwrm_ctx_flags flags) { diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h index 83794a12cc81..6df629761d95 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.h @@ -107,4 +107,6 @@ int bnge_hwrm_req_send_silent(struct bnge_dev *bd, void *req); void bnge_hwrm_req_alloc_flags(struct bnge_dev *bd, void *req, gfp_t flags); void *bnge_hwrm_req_dma_slice(struct bnge_dev *bd, void *req, u32 size, dma_addr_t *dma); +int bnge_hwrm_req_replace(struct bnge_dev *bd, void *req, void *new_req, + u32 len); #endif /* _BNGE_HWRM_H_ */ diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c index 62ebe03a0dcf..943df5f60f01 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.c @@ -34,6 +34,18 @@ static unsigned int bnge_get_max_func_stat_ctxs(struct bnge_dev *bd) return bd->hw_resc.max_stat_ctxs; } +bool bnge_aux_has_enough_resources(struct bnge_dev *bd) +{ + unsigned int max_stat_ctxs; + + max_stat_ctxs = bnge_get_max_func_stat_ctxs(bd); + if (max_stat_ctxs <= BNGE_MIN_ROCE_STAT_CTXS || + bd->nq_nr_rings == max_stat_ctxs) + return false; + + return true; +} + static unsigned int bnge_get_max_func_cp_rings(struct bnge_dev *bd) { return bd->hw_resc.max_cp_rings; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h index 0d6213b27580..b62a634669f6 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_resc.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_resc.h @@ -74,6 +74,7 @@ void bnge_net_uninit_dflt_config(struct bnge_dev *bd); void bnge_aux_init_dflt_config(struct bnge_dev *bd); u32 bnge_get_rxfh_indir_size(struct bnge_dev *bd); int bnge_cal_nr_rss_ctxs(u16 rx_rings); +bool bnge_aux_has_enough_resources(struct bnge_dev *bd); static inline u32 bnge_adjust_pow_two(u32 total_ent, u16 ent_per_blk) diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index cb1011f6fd30..805daae9dd36 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -6444,7 +6444,6 @@ bnx2_reset_task(struct work_struct *work) if (!(pcicmd & PCI_COMMAND_MEMORY)) { /* in case PCI block has reset */ pci_restore_state(bp->pdev); - pci_save_state(bp->pdev); } rc = bnx2_init_nic(bp, 1); if (rc) { @@ -8718,7 +8717,6 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev) } else { pci_set_master(pdev); pci_restore_state(pdev); - pci_save_state(pdev); if (netif_running(dev)) err = bnx2_init_nic(bp, 1); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index fc8dec37a9e4..3d853eeb976f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -3355,19 +3355,11 @@ static int bnx2x_get_rxfh_fields(struct net_device *dev, return 0; } -static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, - u32 *rules __always_unused) +static u32 bnx2x_get_rx_ring_count(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); - switch (info->cmd) { - case ETHTOOL_GRXRINGS: - info->data = BNX2X_NUM_ETH_QUEUES(bp); - return 0; - default: - DP(BNX2X_MSG_ETHTOOL, "Command parameters not supported\n"); - return -EOPNOTSUPP; - } + return BNX2X_NUM_ETH_QUEUES(bp); } static int bnx2x_set_rxfh_fields(struct net_device *dev, @@ -3674,7 +3666,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = { .get_strings = bnx2x_get_strings, .set_phys_id = bnx2x_set_phys_id, .get_ethtool_stats = bnx2x_get_ethtool_stats, - .get_rxnfc = bnx2x_get_rxnfc, + .get_rx_ring_count = bnx2x_get_rx_ring_count, .get_rxfh_indir_size = bnx2x_get_rxfh_indir_size, .get_rxfh = bnx2x_get_rxfh, .set_rxfh = bnx2x_set_rxfh, @@ -3702,7 +3694,7 @@ static const struct ethtool_ops bnx2x_vf_ethtool_ops = { .get_sset_count = bnx2x_get_sset_count, .get_strings = bnx2x_get_strings, .get_ethtool_stats = bnx2x_get_ethtool_stats, - .get_rxnfc = bnx2x_get_rxnfc, + .get_rx_ring_count = bnx2x_get_rx_ring_count, .get_rxfh_indir_size = bnx2x_get_rxfh_indir_size, .get_rxfh = bnx2x_get_rxfh, .set_rxfh = bnx2x_set_rxfh, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index f0f05d7315ac..6a1cc2032bf3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -308,8 +308,11 @@ static int bnx2x_set_storm_rx_mode(struct bnx2x *bp); /**************************************************************************** * General service functions ****************************************************************************/ - -static int bnx2x_hwtstamp_ioctl(struct bnx2x *bp, struct ifreq *ifr); +static int bnx2x_hwtstamp_set(struct net_device *dev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack); +static int bnx2x_hwtstamp_get(struct net_device *dev, + struct kernel_hwtstamp_config *config); static void __storm_memset_dma_mapping(struct bnx2x *bp, u32 addr, dma_addr_t mapping) @@ -12813,14 +12816,9 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!netif_running(dev)) return -EAGAIN; - switch (cmd) { - case SIOCSHWTSTAMP: - return bnx2x_hwtstamp_ioctl(bp, ifr); - default: - DP(NETIF_MSG_LINK, "ioctl: phy id 0x%x, reg 0x%x, val_in 0x%x\n", - mdio->phy_id, mdio->reg_num, mdio->val_in); - return mdio_mii_ioctl(&bp->mdio, mdio, cmd); - } + DP(NETIF_MSG_LINK, "ioctl: phy id 0x%x, reg 0x%x, val_in 0x%x\n", + mdio->phy_id, mdio->reg_num, mdio->val_in); + return mdio_mii_ioctl(&bp->mdio, mdio, cmd); } static int bnx2x_validate_addr(struct net_device *dev) @@ -13036,6 +13034,8 @@ static const struct net_device_ops bnx2x_netdev_ops = { .ndo_get_phys_port_id = bnx2x_get_phys_port_id, .ndo_set_vf_link_state = bnx2x_set_vf_link_state, .ndo_features_check = bnx2x_features_check, + .ndo_hwtstamp_get = bnx2x_hwtstamp_get, + .ndo_hwtstamp_set = bnx2x_hwtstamp_set, }; static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, @@ -14216,7 +14216,6 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev) pci_set_master(pdev); pci_restore_state(pdev); - pci_save_state(pdev); if (netif_running(dev)) bnx2x_set_power_state(bp, PCI_D0); @@ -15350,31 +15349,57 @@ int bnx2x_configure_ptp_filters(struct bnx2x *bp) return 0; } -static int bnx2x_hwtstamp_ioctl(struct bnx2x *bp, struct ifreq *ifr) +static int bnx2x_hwtstamp_set(struct net_device *dev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) { - struct hwtstamp_config config; + struct bnx2x *bp = netdev_priv(dev); int rc; - DP(BNX2X_MSG_PTP, "HWTSTAMP IOCTL called\n"); + DP(BNX2X_MSG_PTP, "HWTSTAMP SET called\n"); - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; + if (!netif_running(dev)) { + NL_SET_ERR_MSG_MOD(extack, "Device is down"); + return -EAGAIN; + } DP(BNX2X_MSG_PTP, "Requested tx_type: %d, requested rx_filters = %d\n", - config.tx_type, config.rx_filter); + config->tx_type, config->rx_filter); + + switch (config->tx_type) { + case HWTSTAMP_TX_ON: + case HWTSTAMP_TX_OFF: + break; + default: + NL_SET_ERR_MSG_MOD(extack, + "One-step timestamping is not supported"); + return -ERANGE; + } bp->hwtstamp_ioctl_called = true; - bp->tx_type = config.tx_type; - bp->rx_filter = config.rx_filter; + bp->tx_type = config->tx_type; + bp->rx_filter = config->rx_filter; rc = bnx2x_configure_ptp_filters(bp); - if (rc) + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "HW configuration failure"); return rc; + } + + config->rx_filter = bp->rx_filter; + + return 0; +} + +static int bnx2x_hwtstamp_get(struct net_device *dev, + struct kernel_hwtstamp_config *config) +{ + struct bnx2x *bp = netdev_priv(dev); - config.rx_filter = bp->rx_filter; + config->rx_filter = bp->rx_filter; + config->tx_type = bp->tx_type; - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; + return 0; } /* Configures HW for PTP */ diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index a625e7c311dd..d17d0ea89c36 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -877,7 +877,7 @@ static bool __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr, next_tx_int: cons = NEXT_TX(cons); - dev_consume_skb_any(skb); + napi_consume_skb(skb, budget); } WRITE_ONCE(txr->tx_cons, cons); @@ -4479,7 +4479,14 @@ static void bnxt_init_one_rx_agg_ring_rxbd(struct bnxt *bp, ring->fw_ring_id = INVALID_HW_RING_ID; if ((bp->flags & BNXT_FLAG_AGG_RINGS)) { type = ((u32)BNXT_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) | - RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP; + RX_BD_TYPE_RX_AGG_BD; + + /* On P7, setting EOP will cause the chip to disable + * Relaxed Ordering (RO) for TPA data. Disable EOP for + * potentially higher performance with RO. + */ + if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA)) + type |= RX_BD_FLAGS_AGG_EOP; bnxt_init_rxbd_pages(ring, type); } @@ -5688,6 +5695,10 @@ int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap, int bmap_size, u16 cmd = bnxt_vf_req_snif[i]; unsigned int bit, idx; + if ((bp->fw_cap & BNXT_FW_CAP_LINK_ADMIN) && + cmd == HWRM_PORT_PHY_QCFG) + continue; + idx = cmd / 32; bit = cmd % 32; data[idx] |= 1 << bit; @@ -8506,6 +8517,11 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp) if (flags & FUNC_QCFG_RESP_FLAGS_ENABLE_RDMA_SRIOV) bp->fw_cap |= BNXT_FW_CAP_ENABLE_RDMA_SRIOV; + if (resp->roce_bidi_opt_mode & + FUNC_QCFG_RESP_ROCE_BIDI_OPT_MODE_DEDICATED) + bp->cos0_cos1_shared = 1; + else + bp->cos0_cos1_shared = 0; switch (resp->port_partition_type) { case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_0: @@ -9653,6 +9669,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp) bp->flags |= BNXT_FLAG_ROCEV1_CAP; if (flags & FUNC_QCAPS_RESP_FLAGS_ROCE_V2_SUPPORTED) bp->flags |= BNXT_FLAG_ROCEV2_CAP; + if (flags & FUNC_QCAPS_RESP_FLAGS_LINK_ADMIN_STATUS_SUPPORTED) + bp->fw_cap |= BNXT_FW_CAP_LINK_ADMIN; if (flags & FUNC_QCAPS_RESP_FLAGS_PCIE_STATS_SUPPORTED) bp->fw_cap |= BNXT_FW_CAP_PCIE_STATS_SUPPORTED; if (flags & FUNC_QCAPS_RESP_FLAGS_HOT_RESET_CAPABLE) @@ -14020,11 +14038,19 @@ static void bnxt_dump_rx_sw_state(struct bnxt_napi *bnapi) static void bnxt_dump_cp_sw_state(struct bnxt_napi *bnapi) { - struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; - int i = bnapi->index; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring, *cpr2; + int i = bnapi->index, j; netdev_info(bnapi->bp->dev, "[%d]: cp{fw_ring: %d raw_cons: %x}\n", i, cpr->cp_ring_struct.fw_ring_id, cpr->cp_raw_cons); + for (j = 0; j < cpr->cp_ring_count; j++) { + cpr2 = &cpr->cp_ring_arr[j]; + if (!cpr2->bnapi) + continue; + netdev_info(bnapi->bp->dev, "[%d.%d]: cp{fw_ring: %d raw_cons: %x}\n", + i, j, cpr2->cp_ring_struct.fw_ring_id, + cpr2->cp_raw_cons); + } } static void bnxt_dbg_dump_states(struct bnxt *bp) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 3613a172483a..f5f07a7e6b29 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -131,6 +131,7 @@ struct rx_bd { #define RX_BD_TYPE_48B_BD_SIZE (2 << 4) #define RX_BD_TYPE_64B_BD_SIZE (3 << 4) #define RX_BD_FLAGS_SOP (1 << 6) + #define RX_BD_FLAGS_AGG_EOP (1 << 6) #define RX_BD_FLAGS_EOP (1 << 7) #define RX_BD_FLAGS_BUFFERS (3 << 8) #define RX_BD_FLAGS_1_BUFFER_PACKET (0 << 8) @@ -2424,6 +2425,7 @@ struct bnxt { u8 tc_to_qidx[BNXT_MAX_QUEUE]; u8 q_ids[BNXT_MAX_QUEUE]; u8 max_q; + u8 cos0_cos1_shared; u8 num_tc; u16 max_pfcwd_tmo_ms; @@ -2482,6 +2484,7 @@ struct bnxt { #define BNXT_FW_CAP_ROCE_VF_RESC_MGMT_SUPPORTED BIT_ULL(6) #define BNXT_FW_CAP_KONG_MB_CHNL BIT_ULL(7) #define BNXT_FW_CAP_ROCE_VF_DYN_ALLOC_SUPPORT BIT_ULL(8) + #define BNXT_FW_CAP_LINK_ADMIN BIT_ULL(9) #define BNXT_FW_CAP_OVS_64BIT_HANDLE BIT_ULL(10) #define BNXT_FW_CAP_TRUSTED_VF BIT_ULL(11) #define BNXT_FW_CAP_ERROR_RECOVERY BIT_ULL(13) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c index 67ca02d84c97..15de802bbac4 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c @@ -1086,7 +1086,8 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, } static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id, - struct devlink_param_gset_ctx *ctx) + struct devlink_param_gset_ctx *ctx, + struct netlink_ext_ack *extack) { struct bnxt *bp = bnxt_get_bp_from_dl(dl); struct hwrm_nvm_get_variable_input *req; @@ -1168,7 +1169,8 @@ static int bnxt_dl_msix_validate(struct devlink *dl, u32 id, } static int bnxt_remote_dev_reset_get(struct devlink *dl, u32 id, - struct devlink_param_gset_ctx *ctx) + struct devlink_param_gset_ctx *ctx, + struct netlink_ext_ack *extack) { struct bnxt *bp = bnxt_get_bp_from_dl(dl); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 41686a6f84b5..068e191ede19 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -688,16 +688,22 @@ skip_ring_stats: buf[j] = *(rx_port_stats_ext + n); } for (i = 0; i < 8; i++, j++) { - long n = bnxt_tx_bytes_pri_arr[i].base_off + - bp->pri2cos_idx[i]; + u8 cos_idx = bp->pri2cos_idx[i]; + long n; + n = bnxt_tx_bytes_pri_arr[i].base_off + cos_idx; buf[j] = *(tx_port_stats_ext + n); + if (bp->cos0_cos1_shared && !cos_idx) + buf[j] += *(tx_port_stats_ext + n + 1); } for (i = 0; i < 8; i++, j++) { - long n = bnxt_tx_pkts_pri_arr[i].base_off + - bp->pri2cos_idx[i]; + u8 cos_idx = bp->pri2cos_idx[i]; + long n; + n = bnxt_tx_pkts_pri_arr[i].base_off + cos_idx; buf[j] = *(tx_port_stats_ext + n); + if (bp->cos0_cos1_shared && !cos_idx) + buf[j] += *(tx_port_stats_ext + n + 1); } } } @@ -1764,6 +1770,13 @@ static int bnxt_set_rxfh_fields(struct net_device *dev, return rc; } +static u32 bnxt_get_rx_ring_count(struct net_device *dev) +{ + struct bnxt *bp = netdev_priv(dev); + + return bp->rx_nr_rings; +} + static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, u32 *rule_locs) { @@ -1771,10 +1784,6 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, int rc = 0; switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = bp->rx_nr_rings; - break; - case ETHTOOL_GRXCLSRLCNT: cmd->rule_cnt = bp->ntp_fltr_count; cmd->data = bp->max_fltr | RX_CLS_LOC_SPECIAL; @@ -4617,6 +4626,11 @@ static int bnxt_get_module_status(struct bnxt *bp, struct netlink_ext_ack *extac PORT_PHY_QCFG_RESP_MODULE_STATUS_WARNINGMSG) return 0; + if (bp->link_info.phy_type == PORT_PHY_QCFG_RESP_PHY_TYPE_BASET || + bp->link_info.phy_type == PORT_PHY_QCFG_RESP_PHY_TYPE_BASETE){ + NL_SET_ERR_MSG_MOD(extack, "Operation not supported as PHY type is Base-T"); + return -EOPNOTSUPP; + } switch (bp->link_info.module_status) { case PORT_PHY_QCFG_RESP_MODULE_STATUS_PWRDOWN: NL_SET_ERR_MSG_MOD(extack, "Transceiver module is powering down"); @@ -5605,6 +5619,7 @@ const struct ethtool_ops bnxt_ethtool_ops = { .set_channels = bnxt_set_channels, .get_rxnfc = bnxt_get_rxnfc, .set_rxnfc = bnxt_set_rxnfc, + .get_rx_ring_count = bnxt_get_rx_ring_count, .get_rxfh_indir_size = bnxt_get_rxfh_indir_size, .get_rxfh_key_size = bnxt_get_rxfh_key_size, .get_rxfh = bnxt_get_rxfh, diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c index 0abaa2bbe357..a8a74f07bb54 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c @@ -952,7 +952,6 @@ static int bnxt_ptp_pps_init(struct bnxt *bp) snprintf(ptp_info->pin_config[i].name, sizeof(ptp_info->pin_config[i].name), "bnxt_pps%d", i); ptp_info->pin_config[i].index = i; - ptp_info->pin_config[i].chan = i; if (*pin_usg == BNXT_PPS_PIN_PPS_IN) ptp_info->pin_config[i].func = PTP_PF_EXTTS; else if (*pin_usg == BNXT_PPS_PIN_PPS_OUT) @@ -969,6 +968,8 @@ static int bnxt_ptp_pps_init(struct bnxt *bp) ptp_info->n_per_out = 1; ptp_info->pps = 1; ptp_info->verify = bnxt_ptp_verify; + ptp_info->supported_extts_flags = PTP_RISING_EDGE | PTP_STRICT_FLAGS; + ptp_info->supported_perout_flags = PTP_PEROUT_DUTY_CYCLE; return 0; } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c index 80fed2c07b9e..be7deb9cc410 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@ -332,6 +332,38 @@ int bnxt_set_vf_bw(struct net_device *dev, int vf_id, int min_tx_rate, return rc; } +static int bnxt_set_vf_link_admin_state(struct bnxt *bp, int vf_id) +{ + struct hwrm_func_cfg_input *req; + struct bnxt_vf_info *vf; + int rc; + + if (!(bp->fw_cap & BNXT_FW_CAP_LINK_ADMIN)) + return 0; + + vf = &bp->pf.vf[vf_id]; + + rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req); + if (rc) + return rc; + + req->fid = cpu_to_le16(vf->fw_fid); + switch (vf->flags & (BNXT_VF_LINK_FORCED | BNXT_VF_LINK_UP)) { + case BNXT_VF_LINK_FORCED: + req->options = + FUNC_CFG_REQ_OPTIONS_LINK_ADMIN_STATE_FORCED_DOWN; + break; + case (BNXT_VF_LINK_FORCED | BNXT_VF_LINK_UP): + req->options = FUNC_CFG_REQ_OPTIONS_LINK_ADMIN_STATE_FORCED_UP; + break; + default: + req->options = FUNC_CFG_REQ_OPTIONS_LINK_ADMIN_STATE_AUTO; + break; + } + req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_ADMIN_LINK_STATE); + return hwrm_req_send(bp, req); +} + int bnxt_set_vf_link_state(struct net_device *dev, int vf_id, int link) { struct bnxt *bp = netdev_priv(dev); @@ -357,10 +389,11 @@ int bnxt_set_vf_link_state(struct net_device *dev, int vf_id, int link) break; default: netdev_err(bp->dev, "Invalid link option\n"); - rc = -EINVAL; - break; + return -EINVAL; } - if (vf->flags & (BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED)) + if (bp->fw_cap & BNXT_FW_CAP_LINK_ADMIN) + rc = bnxt_set_vf_link_admin_state(bp, vf_id); + else if (vf->flags & (BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED)) rc = bnxt_hwrm_fwd_async_event_cmpl(bp, vf, ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE); return rc; @@ -666,15 +699,21 @@ static int bnxt_hwrm_func_vf_resc_cfg(struct bnxt *bp, int num_vfs, bool reset) hwrm_req_hold(bp, req); for (i = 0; i < num_vfs; i++) { + struct bnxt_vf_info *vf = &pf->vf[i]; + + vf->fw_fid = pf->first_vf_id + i; + rc = bnxt_set_vf_link_admin_state(bp, i); + if (rc) + break; + if (reset) __bnxt_set_vf_params(bp, i); - req->vf_id = cpu_to_le16(pf->first_vf_id + i); + req->vf_id = cpu_to_le16(vf->fw_fid); rc = hwrm_req_send(bp, req); if (rc) break; pf->active_vfs = i + 1; - pf->vf[i].fw_fid = pf->first_vf_id + i; } if (pf->active_vfs) { @@ -741,6 +780,12 @@ static int bnxt_hwrm_func_cfg(struct bnxt *bp, int num_vfs) FUNC_CFG_REQ_ENABLES_NUM_VNICS | FUNC_CFG_REQ_ENABLES_NUM_HW_RING_GRPS); + if (bp->fw_cap & BNXT_FW_CAP_LINK_ADMIN) { + req->options = FUNC_CFG_REQ_OPTIONS_LINK_ADMIN_STATE_AUTO; + req->enables |= + cpu_to_le32(FUNC_CFG_REQ_ENABLES_ADMIN_LINK_STATE); + } + mtu = bp->dev->mtu + VLAN_ETH_HLEN; req->mru = cpu_to_le16(mtu); req->admin_mtu = cpu_to_le16(mtu); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c index f8c2c72b382d..927971c362f1 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c @@ -142,7 +142,6 @@ int bnxt_register_dev(struct bnxt_en_dev *edev, edev->ulp_tbl->msix_requested = bnxt_get_ulp_msix_num(bp); bnxt_fill_msix_vecs(bp, bp->edev->msix_entries); - edev->flags |= BNXT_EN_FLAG_MSIX_REQUESTED; exit: mutex_unlock(&edev->en_dev_lock); netdev_unlock(dev); @@ -159,8 +158,6 @@ void bnxt_unregister_dev(struct bnxt_en_dev *edev) ulp = edev->ulp_tbl; netdev_lock(dev); mutex_lock(&edev->en_dev_lock); - if (ulp->msix_requested) - edev->flags &= ~BNXT_EN_FLAG_MSIX_REQUESTED; edev->ulp_tbl->msix_requested = 0; if (ulp->max_async_event_id) @@ -298,7 +295,7 @@ void bnxt_ulp_irq_stop(struct bnxt *bp) struct bnxt_ulp_ops *ops; bool reset = false; - if (!edev || !(edev->flags & BNXT_EN_FLAG_MSIX_REQUESTED)) + if (!edev) return; if (bnxt_ulp_registered(bp->edev)) { @@ -321,7 +318,7 @@ void bnxt_ulp_irq_restart(struct bnxt *bp, int err) struct bnxt_en_dev *edev = bp->edev; struct bnxt_ulp_ops *ops; - if (!edev || !(edev->flags & BNXT_EN_FLAG_MSIX_REQUESTED)) + if (!edev) return; if (bnxt_ulp_registered(bp->edev)) { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h index 7b9dd8ebe4bc..3c5b8a53f715 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h @@ -58,7 +58,6 @@ struct bnxt_en_dev { #define BNXT_EN_FLAG_ROCEV2_CAP 0x2 #define BNXT_EN_FLAG_ROCE_CAP (BNXT_EN_FLAG_ROCEV1_CAP | \ BNXT_EN_FLAG_ROCEV2_CAP) - #define BNXT_EN_FLAG_MSIX_REQUESTED 0x4 #define BNXT_EN_FLAG_ULP_STOPPED 0x8 #define BNXT_EN_FLAG_VF 0x10 #define BNXT_EN_VF(edev) ((edev)->flags & BNXT_EN_FLAG_VF) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 98971ae4f87d..05512aa10c20 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -35,7 +35,6 @@ #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/phy.h> -#include <linux/platform_data/bcmgenet.h> #include <linux/unaligned.h> @@ -1641,6 +1640,13 @@ static int bcmgenet_get_num_flows(struct bcmgenet_priv *priv) return res; } +static u32 bcmgenet_get_rx_ring_count(struct net_device *dev) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + + return priv->hw_params->rx_queues ?: 1; +} + static int bcmgenet_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, u32 *rule_locs) { @@ -1650,9 +1656,6 @@ static int bcmgenet_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, int i = 0; switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = priv->hw_params->rx_queues ?: 1; - break; case ETHTOOL_GRXCLSRLCNT: cmd->rule_cnt = bcmgenet_get_num_flows(priv); cmd->data = MAX_NUM_OF_FS_RULES | RX_CLS_LOC_SPECIAL; @@ -1701,6 +1704,7 @@ static const struct ethtool_ops bcmgenet_ethtool_ops = { .get_ts_info = ethtool_op_get_ts_info, .get_rxnfc = bcmgenet_get_rxnfc, .set_rxnfc = bcmgenet_set_rxnfc, + .get_rx_ring_count = bcmgenet_get_rx_ring_count, .get_pauseparam = bcmgenet_get_pauseparam, .set_pauseparam = bcmgenet_set_pauseparam, }; @@ -3926,7 +3930,6 @@ MODULE_DEVICE_TABLE(of, bcmgenet_match); static int bcmgenet_probe(struct platform_device *pdev) { - struct bcmgenet_platform_data *pd = pdev->dev.platform_data; const struct bcmgenet_plat_data *pdata; struct bcmgenet_priv *priv; struct net_device *dev; @@ -4010,9 +4013,6 @@ static int bcmgenet_probe(struct platform_device *pdev) priv->version = pdata->version; priv->dma_max_burst_length = pdata->dma_max_burst_length; priv->flags = pdata->flags; - } else { - priv->version = pd->genet_version; - priv->dma_max_burst_length = DMA_MAX_BURST_LENGTH; } priv->clk = devm_clk_get_optional(&priv->pdev->dev, "enet"); @@ -4062,16 +4062,13 @@ static int bcmgenet_probe(struct platform_device *pdev) if (device_get_phy_mode(&pdev->dev) == PHY_INTERFACE_MODE_INTERNAL) bcmgenet_power_up(priv, GENET_POWER_PASSIVE); - if (pd && !IS_ERR_OR_NULL(pd->mac_address)) - eth_hw_addr_set(dev, pd->mac_address); - else - if (device_get_ethdev_address(&pdev->dev, dev)) - if (has_acpi_companion(&pdev->dev)) { - u8 addr[ETH_ALEN]; + if (device_get_ethdev_address(&pdev->dev, dev)) + if (has_acpi_companion(&pdev->dev)) { + u8 addr[ETH_ALEN]; - bcmgenet_get_hw_addr(priv, addr); - eth_hw_addr_set(dev, addr); - } + bcmgenet_get_hw_addr(priv, addr); + eth_hw_addr_set(dev, addr); + } if (!is_valid_ether_addr(dev->dev_addr)) { dev_warn(&pdev->dev, "using random Ethernet MAC\n"); diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 573e8b279e52..38f854b94a79 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -20,7 +20,6 @@ #include <linux/of.h> #include <linux/of_net.h> #include <linux/of_mdio.h> -#include <linux/platform_data/bcmgenet.h> #include <linux/platform_data/mdio-bcm-unimac.h> #include "bcmgenet.h" @@ -436,23 +435,6 @@ static struct device_node *bcmgenet_mii_of_find_mdio(struct bcmgenet_priv *priv) return priv->mdio_dn; } -static void bcmgenet_mii_pdata_init(struct bcmgenet_priv *priv, - struct unimac_mdio_pdata *ppd) -{ - struct device *kdev = &priv->pdev->dev; - struct bcmgenet_platform_data *pd = kdev->platform_data; - - if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) { - /* - * Internal or external PHY with MDIO access - */ - if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR) - ppd->phy_mask = 1 << pd->phy_address; - else - ppd->phy_mask = 0; - } -} - static int bcmgenet_mii_wait(void *wait_func_data) { struct bcmgenet_priv *priv = wait_func_data; @@ -467,7 +449,6 @@ static int bcmgenet_mii_wait(void *wait_func_data) static int bcmgenet_mii_register(struct bcmgenet_priv *priv) { struct platform_device *pdev = priv->pdev; - struct bcmgenet_platform_data *pdata = pdev->dev.platform_data; struct device_node *dn = pdev->dev.of_node; struct unimac_mdio_pdata ppd; struct platform_device *ppdev; @@ -511,8 +492,6 @@ static int bcmgenet_mii_register(struct bcmgenet_priv *priv) ppdev->dev.parent = &pdev->dev; if (dn) ppdev->dev.of_node = bcmgenet_mii_of_find_mdio(priv); - else if (pdata) - bcmgenet_mii_pdata_init(priv, &ppd); else ppd.phy_mask = ~0; @@ -594,58 +573,6 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv) return 0; } -static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv) -{ - struct device *kdev = &priv->pdev->dev; - struct bcmgenet_platform_data *pd = kdev->platform_data; - char phy_name[MII_BUS_ID_SIZE + 3]; - char mdio_bus_id[MII_BUS_ID_SIZE]; - struct phy_device *phydev; - - snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d", - UNIMAC_MDIO_DRV_NAME, priv->pdev->id); - - if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) { - snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, - mdio_bus_id, pd->phy_address); - - /* - * Internal or external PHY with MDIO access - */ - phydev = phy_attach(priv->dev, phy_name, pd->phy_interface); - if (IS_ERR(phydev)) { - dev_err(kdev, "failed to register PHY device\n"); - return PTR_ERR(phydev); - } - } else { - /* - * MoCA port or no MDIO access. - * Use fixed PHY to represent the link layer. - */ - struct fixed_phy_status fphy_status = { - .link = 1, - .speed = pd->phy_speed, - .duplex = pd->phy_duplex, - .pause = 0, - .asym_pause = 0, - }; - - phydev = fixed_phy_register(&fphy_status, NULL); - if (IS_ERR(phydev)) { - dev_err(kdev, "failed to register fixed PHY device\n"); - return PTR_ERR(phydev); - } - - /* Make sure we initialize MoCA PHYs with a link down */ - phydev->link = 0; - - } - - priv->phy_interface = pd->phy_interface; - - return 0; -} - static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv) { struct device *kdev = &priv->pdev->dev; @@ -656,7 +583,7 @@ static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv) else if (has_acpi_companion(kdev)) return bcmgenet_phy_interface_init(priv); else - return bcmgenet_mii_pd_init(priv); + return -EINVAL; } int bcmgenet_mii_init(struct net_device *dev) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index d78cafdb2094..75f66587983d 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -12719,29 +12719,17 @@ static int tg3_get_sset_count(struct net_device *dev, int sset) } } -static int tg3_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, - u32 *rules __always_unused) +static u32 tg3_get_rx_ring_count(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); if (!tg3_flag(tp, SUPPORT_MSIX)) - return -EOPNOTSUPP; - - switch (info->cmd) { - case ETHTOOL_GRXRINGS: - if (netif_running(tp->dev)) - info->data = tp->rxq_cnt; - else { - info->data = num_online_cpus(); - if (info->data > TG3_RSS_MAX_NUM_QS) - info->data = TG3_RSS_MAX_NUM_QS; - } + return 1; - return 0; + if (netif_running(tp->dev)) + return tp->rxq_cnt; - default: - return -EOPNOTSUPP; - } + return min_t(u32, netif_get_num_default_rss_queues(), tp->rxq_max); } static u32 tg3_get_rxfh_indir_size(struct net_device *dev) @@ -14268,7 +14256,7 @@ static const struct ethtool_ops tg3_ethtool_ops = { .get_coalesce = tg3_get_coalesce, .set_coalesce = tg3_set_coalesce, .get_sset_count = tg3_get_sset_count, - .get_rxnfc = tg3_get_rxnfc, + .get_rx_ring_count = tg3_get_rx_ring_count, .get_rxfh_indir_size = tg3_get_rxfh_indir_size, .get_rxfh = tg3_get_rxfh, .set_rxfh = tg3_set_rxfh, @@ -18349,7 +18337,6 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev) pci_set_master(pdev); pci_restore_state(pdev); - pci_save_state(pdev); if (!netdev || !netif_running(netdev)) { rc = PCI_ERS_RESULT_RECOVERED; |
