Merge branch 'bnxt_en-WoL-selftest-XDP_TX-optimize'
Michael Chan says: ==================== bnxt_en: Updates for net-next. Main changes are to add WoL and selftest features, optimize XDP_TX by using short BDs, and to cap the usage of MSIX. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
5422e5a390
@ -4532,6 +4532,9 @@ static int bnxt_hwrm_func_qcaps(struct bnxt *bp)
|
||||
pf->max_tx_wm_flows = le32_to_cpu(resp->max_tx_wm_flows);
|
||||
pf->max_rx_em_flows = le32_to_cpu(resp->max_rx_em_flows);
|
||||
pf->max_rx_wm_flows = le32_to_cpu(resp->max_rx_wm_flows);
|
||||
if (resp->flags &
|
||||
cpu_to_le32(FUNC_QCAPS_RESP_FLAGS_WOL_MAGICPKT_SUPPORTED))
|
||||
bp->flags |= BNXT_FLAG_WOL_CAP;
|
||||
} else {
|
||||
#ifdef CONFIG_BNXT_SRIOV
|
||||
struct bnxt_vf_info *vf = &bp->vf;
|
||||
@ -5180,9 +5183,10 @@ static unsigned int bnxt_get_max_func_irqs(struct bnxt *bp)
|
||||
{
|
||||
#if defined(CONFIG_BNXT_SRIOV)
|
||||
if (BNXT_VF(bp))
|
||||
return bp->vf.max_irqs;
|
||||
return min_t(unsigned int, bp->vf.max_irqs,
|
||||
bp->vf.max_cp_rings);
|
||||
#endif
|
||||
return bp->pf.max_irqs;
|
||||
return min_t(unsigned int, bp->pf.max_irqs, bp->pf.max_cp_rings);
|
||||
}
|
||||
|
||||
void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs)
|
||||
@ -5839,6 +5843,76 @@ static int bnxt_hwrm_port_led_qcaps(struct bnxt *bp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_hwrm_alloc_wol_fltr(struct bnxt *bp)
|
||||
{
|
||||
struct hwrm_wol_filter_alloc_input req = {0};
|
||||
struct hwrm_wol_filter_alloc_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_WOL_FILTER_ALLOC, -1, -1);
|
||||
req.port_id = cpu_to_le16(bp->pf.port_id);
|
||||
req.wol_type = WOL_FILTER_ALLOC_REQ_WOL_TYPE_MAGICPKT;
|
||||
req.enables = cpu_to_le32(WOL_FILTER_ALLOC_REQ_ENABLES_MAC_ADDRESS);
|
||||
memcpy(req.mac_address, bp->dev->dev_addr, ETH_ALEN);
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
if (!rc)
|
||||
bp->wol_filter_id = resp->wol_filter_id;
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bnxt_hwrm_free_wol_fltr(struct bnxt *bp)
|
||||
{
|
||||
struct hwrm_wol_filter_free_input req = {0};
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_WOL_FILTER_FREE, -1, -1);
|
||||
req.port_id = cpu_to_le16(bp->pf.port_id);
|
||||
req.enables = cpu_to_le32(WOL_FILTER_FREE_REQ_ENABLES_WOL_FILTER_ID);
|
||||
req.wol_filter_id = bp->wol_filter_id;
|
||||
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static u16 bnxt_hwrm_get_wol_fltrs(struct bnxt *bp, u16 handle)
|
||||
{
|
||||
struct hwrm_wol_filter_qcfg_input req = {0};
|
||||
struct hwrm_wol_filter_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
u16 next_handle = 0;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_WOL_FILTER_QCFG, -1, -1);
|
||||
req.port_id = cpu_to_le16(bp->pf.port_id);
|
||||
req.handle = cpu_to_le16(handle);
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
if (!rc) {
|
||||
next_handle = le16_to_cpu(resp->next_handle);
|
||||
if (next_handle != 0) {
|
||||
if (resp->wol_type ==
|
||||
WOL_FILTER_ALLOC_REQ_WOL_TYPE_MAGICPKT) {
|
||||
bp->wol = 1;
|
||||
bp->wol_filter_id = resp->wol_filter_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
return next_handle;
|
||||
}
|
||||
|
||||
static void bnxt_get_wol_settings(struct bnxt *bp)
|
||||
{
|
||||
u16 handle = 0;
|
||||
|
||||
if (!BNXT_PF(bp) || !(bp->flags & BNXT_FLAG_WOL_CAP))
|
||||
return;
|
||||
|
||||
do {
|
||||
handle = bnxt_hwrm_get_wol_fltrs(bp, handle);
|
||||
} while (handle && handle != 0xffff);
|
||||
}
|
||||
|
||||
static bool bnxt_eee_config_ok(struct bnxt *bp)
|
||||
{
|
||||
struct ethtool_eee *eee = &bp->eee;
|
||||
@ -6024,6 +6098,43 @@ int bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtnl_lock held, open the NIC half way by allocating all resources, but
|
||||
* NAPI, IRQ, and TX are not enabled. This is mainly used for offline
|
||||
* self tests.
|
||||
*/
|
||||
int bnxt_half_open_nic(struct bnxt *bp)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = bnxt_alloc_mem(bp, false);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc);
|
||||
goto half_open_err;
|
||||
}
|
||||
rc = bnxt_init_nic(bp, false);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc);
|
||||
goto half_open_err;
|
||||
}
|
||||
return 0;
|
||||
|
||||
half_open_err:
|
||||
bnxt_free_skbs(bp);
|
||||
bnxt_free_mem(bp, false);
|
||||
dev_close(bp->dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtnl_lock held, this call can only be made after a previous successful
|
||||
* call to bnxt_half_open_nic().
|
||||
*/
|
||||
void bnxt_half_close_nic(struct bnxt *bp)
|
||||
{
|
||||
bnxt_hwrm_resource_free(bp, false, false);
|
||||
bnxt_free_skbs(bp);
|
||||
bnxt_free_mem(bp, false);
|
||||
}
|
||||
|
||||
static int bnxt_open(struct net_device *dev)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
@ -7208,6 +7319,7 @@ static void bnxt_remove_one(struct pci_dev *pdev)
|
||||
bnxt_clear_int_mode(bp);
|
||||
bnxt_hwrm_func_drv_unrgtr(bp);
|
||||
bnxt_free_hwrm_resources(bp);
|
||||
bnxt_ethtool_free(bp);
|
||||
bnxt_dcb_free(bp);
|
||||
kfree(bp->edev);
|
||||
bp->edev = NULL;
|
||||
@ -7530,6 +7642,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
bnxt_hwrm_func_qcfg(bp);
|
||||
bnxt_hwrm_port_led_qcaps(bp);
|
||||
bnxt_ethtool_init(bp);
|
||||
|
||||
bnxt_set_rx_skb_mode(bp, false);
|
||||
bnxt_set_tpa_flags(bp);
|
||||
@ -7575,6 +7688,12 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (rc)
|
||||
goto init_err_pci_clean;
|
||||
|
||||
bnxt_get_wol_settings(bp);
|
||||
if (bp->flags & BNXT_FLAG_WOL_CAP)
|
||||
device_set_wakeup_enable(&pdev->dev, bp->wol);
|
||||
else
|
||||
device_set_wakeup_capable(&pdev->dev, false);
|
||||
|
||||
rc = register_netdev(dev);
|
||||
if (rc)
|
||||
goto init_err_clr_int;
|
||||
@ -7598,6 +7717,88 @@ init_err_free:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void bnxt_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
struct bnxt *bp;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
rtnl_lock();
|
||||
bp = netdev_priv(dev);
|
||||
if (!bp)
|
||||
goto shutdown_exit;
|
||||
|
||||
if (netif_running(dev))
|
||||
dev_close(dev);
|
||||
|
||||
if (system_state == SYSTEM_POWER_OFF) {
|
||||
bnxt_clear_int_mode(bp);
|
||||
pci_wake_from_d3(pdev, bp->wol);
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
}
|
||||
|
||||
shutdown_exit:
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int bnxt_suspend(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
int rc = 0;
|
||||
|
||||
rtnl_lock();
|
||||
if (netif_running(dev)) {
|
||||
netif_device_detach(dev);
|
||||
rc = bnxt_close(dev);
|
||||
}
|
||||
bnxt_hwrm_func_drv_unrgtr(bp);
|
||||
rtnl_unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_resume(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
int rc = 0;
|
||||
|
||||
rtnl_lock();
|
||||
if (bnxt_hwrm_ver_get(bp) || bnxt_hwrm_func_drv_rgtr(bp)) {
|
||||
rc = -ENODEV;
|
||||
goto resume_exit;
|
||||
}
|
||||
rc = bnxt_hwrm_func_reset(bp);
|
||||
if (rc) {
|
||||
rc = -EBUSY;
|
||||
goto resume_exit;
|
||||
}
|
||||
bnxt_get_wol_settings(bp);
|
||||
if (netif_running(dev)) {
|
||||
rc = bnxt_open(dev);
|
||||
if (!rc)
|
||||
netif_device_attach(dev);
|
||||
}
|
||||
|
||||
resume_exit:
|
||||
rtnl_unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(bnxt_pm_ops, bnxt_suspend, bnxt_resume);
|
||||
#define BNXT_PM_OPS (&bnxt_pm_ops)
|
||||
|
||||
#else
|
||||
|
||||
#define BNXT_PM_OPS NULL
|
||||
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
/**
|
||||
* bnxt_io_error_detected - called when PCI error is detected
|
||||
* @pdev: Pointer to PCI device
|
||||
@ -7714,6 +7915,8 @@ static struct pci_driver bnxt_pci_driver = {
|
||||
.id_table = bnxt_pci_tbl,
|
||||
.probe = bnxt_init_one,
|
||||
.remove = bnxt_remove_one,
|
||||
.shutdown = bnxt_shutdown,
|
||||
.driver.pm = BNXT_PM_OPS,
|
||||
.err_handler = &bnxt_err_handler,
|
||||
#if defined(CONFIG_BNXT_SRIOV)
|
||||
.sriov_configure = bnxt_sriov_configure,
|
||||
|
@ -426,8 +426,6 @@ struct rx_tpa_end_cmp_ext {
|
||||
|
||||
#define BNXT_MIN_PKT_SIZE 52
|
||||
|
||||
#define BNXT_NUM_TESTS(bp) 0
|
||||
|
||||
#define BNXT_DEFAULT_RX_RING_SIZE 511
|
||||
#define BNXT_DEFAULT_TX_RING_SIZE 511
|
||||
|
||||
@ -911,6 +909,14 @@ struct bnxt_led_info {
|
||||
__le16 led_color_caps;
|
||||
};
|
||||
|
||||
#define BNXT_MAX_TEST 8
|
||||
|
||||
struct bnxt_test_info {
|
||||
u8 offline_mask;
|
||||
u16 timeout;
|
||||
char string[BNXT_MAX_TEST][ETH_GSTRING_LEN];
|
||||
};
|
||||
|
||||
#define BNXT_GRCPF_REG_WINDOW_BASE_OUT 0x400
|
||||
#define BNXT_CAG_REG_LEGACY_INT_STATUS 0x4014
|
||||
#define BNXT_CAG_REG_BASE 0x300000
|
||||
@ -989,6 +995,7 @@ struct bnxt {
|
||||
#define BNXT_FLAG_UDP_RSS_CAP 0x800
|
||||
#define BNXT_FLAG_EEE_CAP 0x1000
|
||||
#define BNXT_FLAG_NEW_RSS_CAP 0x2000
|
||||
#define BNXT_FLAG_WOL_CAP 0x4000
|
||||
#define BNXT_FLAG_ROCEV1_CAP 0x8000
|
||||
#define BNXT_FLAG_ROCEV2_CAP 0x10000
|
||||
#define BNXT_FLAG_ROCE_CAP (BNXT_FLAG_ROCEV1_CAP | \
|
||||
@ -1180,6 +1187,12 @@ struct bnxt {
|
||||
u32 lpi_tmr_lo;
|
||||
u32 lpi_tmr_hi;
|
||||
|
||||
u8 num_tests;
|
||||
struct bnxt_test_info *test_info;
|
||||
|
||||
u8 wol_filter_id;
|
||||
u8 wol;
|
||||
|
||||
u8 num_leds;
|
||||
struct bnxt_led_info leds[BNXT_MAX_LED];
|
||||
|
||||
@ -1238,8 +1251,12 @@ void bnxt_tx_disable(struct bnxt *bp);
|
||||
void bnxt_tx_enable(struct bnxt *bp);
|
||||
int bnxt_hwrm_set_pause(struct bnxt *);
|
||||
int bnxt_hwrm_set_link_setting(struct bnxt *, bool, bool);
|
||||
int bnxt_hwrm_alloc_wol_fltr(struct bnxt *bp);
|
||||
int bnxt_hwrm_free_wol_fltr(struct bnxt *bp);
|
||||
int bnxt_hwrm_fw_set_time(struct bnxt *);
|
||||
int bnxt_open_nic(struct bnxt *, bool, bool);
|
||||
int bnxt_half_open_nic(struct bnxt *bp);
|
||||
void bnxt_half_close_nic(struct bnxt *bp);
|
||||
int bnxt_close_nic(struct bnxt *, bool, bool);
|
||||
int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs, int tx_xdp);
|
||||
int bnxt_setup_mq_tc(struct net_device *dev, u8 tc);
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2014-2016 Broadcom Corporation
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -17,6 +18,7 @@
|
||||
#include <linux/firmware.h>
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_xdp.h"
|
||||
#include "bnxt_ethtool.h"
|
||||
#include "bnxt_nvm_defs.h" /* NVRAM content constant and structure defs */
|
||||
#include "bnxt_fw_hdr.h" /* Firmware hdr constant and structure defs */
|
||||
@ -209,6 +211,10 @@ static int bnxt_get_sset_count(struct net_device *dev, int sset)
|
||||
|
||||
return num_stats;
|
||||
}
|
||||
case ETH_SS_TEST:
|
||||
if (!bp->num_tests)
|
||||
return -EOPNOTSUPP;
|
||||
return bp->num_tests;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@ -306,6 +312,11 @@ static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETH_SS_TEST:
|
||||
if (bp->num_tests)
|
||||
memcpy(buf, bp->test_info->string,
|
||||
bp->num_tests * ETH_GSTRING_LEN);
|
||||
break;
|
||||
default:
|
||||
netdev_err(bp->dev, "bnxt_get_strings invalid request %x\n",
|
||||
stringset);
|
||||
@ -824,7 +835,7 @@ static void bnxt_get_drvinfo(struct net_device *dev,
|
||||
sizeof(info->fw_version));
|
||||
strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
|
||||
info->n_stats = BNXT_NUM_STATS * bp->cp_nr_rings;
|
||||
info->testinfo_len = BNXT_NUM_TESTS(bp);
|
||||
info->testinfo_len = bp->num_tests;
|
||||
/* TODO CHIMP_FW: eeprom dump details */
|
||||
info->eedump_len = 0;
|
||||
/* TODO CHIMP FW: reg dump details */
|
||||
@ -832,6 +843,45 @@ static void bnxt_get_drvinfo(struct net_device *dev,
|
||||
kfree(pkglog);
|
||||
}
|
||||
|
||||
static void bnxt_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
|
||||
wol->supported = 0;
|
||||
wol->wolopts = 0;
|
||||
memset(&wol->sopass, 0, sizeof(wol->sopass));
|
||||
if (bp->flags & BNXT_FLAG_WOL_CAP) {
|
||||
wol->supported = WAKE_MAGIC;
|
||||
if (bp->wol)
|
||||
wol->wolopts = WAKE_MAGIC;
|
||||
}
|
||||
}
|
||||
|
||||
static int bnxt_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
|
||||
if (wol->wolopts & ~WAKE_MAGIC)
|
||||
return -EINVAL;
|
||||
|
||||
if (wol->wolopts & WAKE_MAGIC) {
|
||||
if (!(bp->flags & BNXT_FLAG_WOL_CAP))
|
||||
return -EINVAL;
|
||||
if (!bp->wol) {
|
||||
if (bnxt_hwrm_alloc_wol_fltr(bp))
|
||||
return -EBUSY;
|
||||
bp->wol = 1;
|
||||
}
|
||||
} else {
|
||||
if (bp->wol) {
|
||||
if (bnxt_hwrm_free_wol_fltr(bp))
|
||||
return -EBUSY;
|
||||
bp->wol = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 _bnxt_fw_to_ethtool_adv_spds(u16 fw_speeds, u8 fw_pause)
|
||||
{
|
||||
u32 speed_mask = 0;
|
||||
@ -2128,12 +2178,372 @@ static int bnxt_set_phys_id(struct net_device *dev,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_selftest_irq(struct bnxt *bp, u16 cmpl_ring)
|
||||
{
|
||||
struct hwrm_selftest_irq_input req = {0};
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_SELFTEST_IRQ, cmpl_ring, -1);
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
}
|
||||
|
||||
static int bnxt_test_irq(struct bnxt *bp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bp->cp_nr_rings; i++) {
|
||||
u16 cmpl_ring = bp->grp_info[i].cp_fw_ring_id;
|
||||
int rc;
|
||||
|
||||
rc = bnxt_hwrm_selftest_irq(bp, cmpl_ring);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_mac_loopback(struct bnxt *bp, bool enable)
|
||||
{
|
||||
struct hwrm_port_mac_cfg_input req = {0};
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_MAC_CFG, -1, -1);
|
||||
|
||||
req.enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_LPBK);
|
||||
if (enable)
|
||||
req.lpbk = PORT_MAC_CFG_REQ_LPBK_LOCAL;
|
||||
else
|
||||
req.lpbk = PORT_MAC_CFG_REQ_LPBK_NONE;
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
}
|
||||
|
||||
static int bnxt_disable_an_for_lpbk(struct bnxt *bp,
|
||||
struct hwrm_port_phy_cfg_input *req)
|
||||
{
|
||||
struct bnxt_link_info *link_info = &bp->link_info;
|
||||
u16 fw_advertising = link_info->advertising;
|
||||
u16 fw_speed;
|
||||
int rc;
|
||||
|
||||
if (!link_info->autoneg)
|
||||
return 0;
|
||||
|
||||
fw_speed = PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_1GB;
|
||||
if (netif_carrier_ok(bp->dev))
|
||||
fw_speed = bp->link_info.link_speed;
|
||||
else if (fw_advertising & BNXT_LINK_SPEED_MSK_10GB)
|
||||
fw_speed = PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_10GB;
|
||||
else if (fw_advertising & BNXT_LINK_SPEED_MSK_25GB)
|
||||
fw_speed = PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_25GB;
|
||||
else if (fw_advertising & BNXT_LINK_SPEED_MSK_40GB)
|
||||
fw_speed = PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_40GB;
|
||||
else if (fw_advertising & BNXT_LINK_SPEED_MSK_50GB)
|
||||
fw_speed = PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_50GB;
|
||||
|
||||
req->force_link_speed = cpu_to_le16(fw_speed);
|
||||
req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE |
|
||||
PORT_PHY_CFG_REQ_FLAGS_RESET_PHY);
|
||||
rc = hwrm_send_message(bp, req, sizeof(*req), HWRM_CMD_TIMEOUT);
|
||||
req->flags = 0;
|
||||
req->force_link_speed = cpu_to_le16(0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_phy_loopback(struct bnxt *bp, bool enable)
|
||||
{
|
||||
struct hwrm_port_phy_cfg_input req = {0};
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_CFG, -1, -1);
|
||||
|
||||
if (enable) {
|
||||
bnxt_disable_an_for_lpbk(bp, &req);
|
||||
req.lpbk = PORT_PHY_CFG_REQ_LPBK_LOCAL;
|
||||
} else {
|
||||
req.lpbk = PORT_PHY_CFG_REQ_LPBK_NONE;
|
||||
}
|
||||
req.enables = cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_LPBK);
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
}
|
||||
|
||||
static int bnxt_rx_loopback(struct bnxt *bp, struct bnxt_napi *bnapi,
|
||||
u32 raw_cons, int pkt_size)
|
||||
{
|
||||
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
|
||||
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
|
||||
struct bnxt_sw_rx_bd *rx_buf;
|
||||
struct rx_cmp *rxcmp;
|
||||
u16 cp_cons, cons;
|
||||
u8 *data;
|
||||
u32 len;
|
||||
int i;
|
||||
|
||||
cp_cons = RING_CMP(raw_cons);
|
||||
rxcmp = (struct rx_cmp *)
|
||||
&cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
|
||||
cons = rxcmp->rx_cmp_opaque;
|
||||
rx_buf = &rxr->rx_buf_ring[cons];
|
||||
data = rx_buf->data_ptr;
|
||||
len = le32_to_cpu(rxcmp->rx_cmp_len_flags_type) >> RX_CMP_LEN_SHIFT;
|
||||
if (len != pkt_size)
|
||||
return -EIO;
|
||||
i = ETH_ALEN;
|
||||
if (!ether_addr_equal(data + i, bnapi->bp->dev->dev_addr))
|
||||
return -EIO;
|
||||
i += ETH_ALEN;
|
||||
for ( ; i < pkt_size; i++) {
|
||||
if (data[i] != (u8)(i & 0xff))
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_poll_loopback(struct bnxt *bp, int pkt_size)
|
||||
{
|
||||
struct bnxt_napi *bnapi = bp->bnapi[0];
|
||||
struct bnxt_cp_ring_info *cpr;
|
||||
struct tx_cmp *txcmp;
|
||||
int rc = -EIO;
|
||||
u32 raw_cons;
|
||||
u32 cons;
|
||||
int i;
|
||||
|
||||
cpr = &bnapi->cp_ring;
|
||||
raw_cons = cpr->cp_raw_cons;
|
||||
for (i = 0; i < 200; i++) {
|
||||
cons = RING_CMP(raw_cons);
|
||||
txcmp = &cpr->cp_desc_ring[CP_RING(cons)][CP_IDX(cons)];
|
||||
|
||||
if (!TX_CMP_VALID(txcmp, raw_cons)) {
|
||||
udelay(5);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The valid test of the entry must be done first before
|
||||
* reading any further.
|
||||
*/
|
||||
dma_rmb();
|
||||
if (TX_CMP_TYPE(txcmp) == CMP_TYPE_RX_L2_CMP) {
|
||||
rc = bnxt_rx_loopback(bp, bnapi, raw_cons, pkt_size);
|
||||
raw_cons = NEXT_RAW_CMP(raw_cons);
|
||||
raw_cons = NEXT_RAW_CMP(raw_cons);
|
||||
break;
|
||||
}
|
||||
raw_cons = NEXT_RAW_CMP(raw_cons);
|
||||
}
|
||||
cpr->cp_raw_cons = raw_cons;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_run_loopback(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_tx_ring_info *txr = &bp->tx_ring[0];
|
||||
int pkt_size, i = 0;
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t map;
|
||||
u8 *data;
|
||||
int rc;
|
||||
|
||||
pkt_size = min(bp->dev->mtu + ETH_HLEN, bp->rx_copy_thresh);
|
||||
skb = netdev_alloc_skb(bp->dev, pkt_size);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
data = skb_put(skb, pkt_size);
|
||||
eth_broadcast_addr(data);
|
||||
i += ETH_ALEN;
|
||||
ether_addr_copy(&data[i], bp->dev->dev_addr);
|
||||
i += ETH_ALEN;
|
||||
for ( ; i < pkt_size; i++)
|
||||
data[i] = (u8)(i & 0xff);
|
||||
|
||||
map = dma_map_single(&bp->pdev->dev, skb->data, pkt_size,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (dma_mapping_error(&bp->pdev->dev, map)) {
|
||||
dev_kfree_skb(skb);
|
||||
return -EIO;
|
||||
}
|
||||
bnxt_xmit_xdp(bp, txr, map, pkt_size, 0);
|
||||
|
||||
/* Sync BD data before updating doorbell */
|
||||
wmb();
|
||||
|
||||
writel(DB_KEY_TX | txr->tx_prod, txr->tx_doorbell);
|
||||
writel(DB_KEY_TX | txr->tx_prod, txr->tx_doorbell);
|
||||
rc = bnxt_poll_loopback(bp, pkt_size);
|
||||
|
||||
dma_unmap_single(&bp->pdev->dev, map, pkt_size, PCI_DMA_TODEVICE);
|
||||
dev_kfree_skb(skb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_run_fw_tests(struct bnxt *bp, u8 test_mask, u8 *test_results)
|
||||
{
|
||||
struct hwrm_selftest_exec_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
struct hwrm_selftest_exec_input req = {0};
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_SELFTEST_EXEC, -1, -1);
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
resp->test_success = 0;
|
||||
req.flags = test_mask;
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), bp->test_info->timeout);
|
||||
*test_results = resp->test_success;
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define BNXT_DRV_TESTS 3
|
||||
#define BNXT_MACLPBK_TEST_IDX (bp->num_tests - BNXT_DRV_TESTS)
|
||||
#define BNXT_PHYLPBK_TEST_IDX (BNXT_MACLPBK_TEST_IDX + 1)
|
||||
#define BNXT_IRQ_TEST_IDX (BNXT_MACLPBK_TEST_IDX + 2)
|
||||
|
||||
static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
|
||||
u64 *buf)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
bool offline = false;
|
||||
u8 test_results = 0;
|
||||
u8 test_mask = 0;
|
||||
int rc, i;
|
||||
|
||||
if (!bp->num_tests || !BNXT_SINGLE_PF(bp))
|
||||
return;
|
||||
memset(buf, 0, sizeof(u64) * bp->num_tests);
|
||||
if (!netif_running(dev)) {
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (etest->flags & ETH_TEST_FL_OFFLINE) {
|
||||
if (bp->pf.active_vfs) {
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
netdev_warn(dev, "Offline tests cannot be run with active VFs\n");
|
||||
return;
|
||||
}
|
||||
offline = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < bp->num_tests - BNXT_DRV_TESTS; i++) {
|
||||
u8 bit_val = 1 << i;
|
||||
|
||||
if (!(bp->test_info->offline_mask & bit_val))
|
||||
test_mask |= bit_val;
|
||||
else if (offline)
|
||||
test_mask |= bit_val;
|
||||
}
|
||||
if (!offline) {
|
||||
bnxt_run_fw_tests(bp, test_mask, &test_results);
|
||||
} else {
|
||||
rc = bnxt_close_nic(bp, false, false);
|
||||
if (rc)
|
||||
return;
|
||||
bnxt_run_fw_tests(bp, test_mask, &test_results);
|
||||
|
||||
buf[BNXT_MACLPBK_TEST_IDX] = 1;
|
||||
bnxt_hwrm_mac_loopback(bp, true);
|
||||
msleep(250);
|
||||
rc = bnxt_half_open_nic(bp);
|
||||
if (rc) {
|
||||
bnxt_hwrm_mac_loopback(bp, false);
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
return;
|
||||
}
|
||||
if (bnxt_run_loopback(bp))
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
else
|
||||
buf[BNXT_MACLPBK_TEST_IDX] = 0;
|
||||
|
||||
bnxt_hwrm_mac_loopback(bp, false);
|
||||
bnxt_hwrm_phy_loopback(bp, true);
|
||||
msleep(1000);
|
||||
if (bnxt_run_loopback(bp)) {
|
||||
buf[BNXT_PHYLPBK_TEST_IDX] = 1;
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
}
|
||||
bnxt_hwrm_phy_loopback(bp, false);
|
||||
bnxt_half_close_nic(bp);
|
||||
bnxt_open_nic(bp, false, true);
|
||||
}
|
||||
if (bnxt_test_irq(bp)) {
|
||||
buf[BNXT_IRQ_TEST_IDX] = 1;
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
}
|
||||
for (i = 0; i < bp->num_tests - BNXT_DRV_TESTS; i++) {
|
||||
u8 bit_val = 1 << i;
|
||||
|
||||
if ((test_mask & bit_val) && !(test_results & bit_val)) {
|
||||
buf[i] = 1;
|
||||
etest->flags |= ETH_TEST_FL_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_ethtool_init(struct bnxt *bp)
|
||||
{
|
||||
struct hwrm_selftest_qlist_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
struct hwrm_selftest_qlist_input req = {0};
|
||||
struct bnxt_test_info *test_info;
|
||||
int i, rc;
|
||||
|
||||
if (bp->hwrm_spec_code < 0x10704 || !BNXT_SINGLE_PF(bp))
|
||||
return;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_SELFTEST_QLIST, -1, -1);
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
if (rc)
|
||||
goto ethtool_init_exit;
|
||||
|
||||
test_info = kzalloc(sizeof(*bp->test_info), GFP_KERNEL);
|
||||
if (!test_info)
|
||||
goto ethtool_init_exit;
|
||||
|
||||
bp->test_info = test_info;
|
||||
bp->num_tests = resp->num_tests + BNXT_DRV_TESTS;
|
||||
if (bp->num_tests > BNXT_MAX_TEST)
|
||||
bp->num_tests = BNXT_MAX_TEST;
|
||||
|
||||
test_info->offline_mask = resp->offline_tests;
|
||||
test_info->timeout = le16_to_cpu(resp->test_timeout);
|
||||
if (!test_info->timeout)
|
||||
test_info->timeout = HWRM_CMD_TIMEOUT;
|
||||
for (i = 0; i < bp->num_tests; i++) {
|
||||
char *str = test_info->string[i];
|
||||
char *fw_str = resp->test0_name + i * 32;
|
||||
|
||||
if (i == BNXT_MACLPBK_TEST_IDX) {
|
||||
strcpy(str, "Mac loopback test (offline)");
|
||||
} else if (i == BNXT_PHYLPBK_TEST_IDX) {
|
||||
strcpy(str, "Phy loopback test (offline)");
|
||||
} else if (i == BNXT_IRQ_TEST_IDX) {
|
||||
strcpy(str, "Interrupt_test (offline)");
|
||||
} else {
|
||||
strlcpy(str, fw_str, ETH_GSTRING_LEN);
|
||||
strncat(str, " test", ETH_GSTRING_LEN - strlen(str));
|
||||
if (test_info->offline_mask & (1 << i))
|
||||
strncat(str, " (offline)",
|
||||
ETH_GSTRING_LEN - strlen(str));
|
||||
else
|
||||
strncat(str, " (online)",
|
||||
ETH_GSTRING_LEN - strlen(str));
|
||||
}
|
||||
}
|
||||
|
||||
ethtool_init_exit:
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
}
|
||||
|
||||
void bnxt_ethtool_free(struct bnxt *bp)
|
||||
{
|
||||
kfree(bp->test_info);
|
||||
bp->test_info = NULL;
|
||||
}
|
||||
|
||||
const struct ethtool_ops bnxt_ethtool_ops = {
|
||||
.get_link_ksettings = bnxt_get_link_ksettings,
|
||||
.set_link_ksettings = bnxt_set_link_ksettings,
|
||||
.get_pauseparam = bnxt_get_pauseparam,
|
||||
.set_pauseparam = bnxt_set_pauseparam,
|
||||
.get_drvinfo = bnxt_get_drvinfo,
|
||||
.get_wol = bnxt_get_wol,
|
||||
.set_wol = bnxt_set_wol,
|
||||
.get_coalesce = bnxt_get_coalesce,
|
||||
.set_coalesce = bnxt_set_coalesce,
|
||||
.get_msglevel = bnxt_get_msglevel,
|
||||
@ -2161,4 +2571,5 @@ const struct ethtool_ops bnxt_ethtool_ops = {
|
||||
.get_module_eeprom = bnxt_get_module_eeprom,
|
||||
.nway_reset = bnxt_nway_reset,
|
||||
.set_phys_id = bnxt_set_phys_id,
|
||||
.self_test = bnxt_self_test,
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2014-2016 Broadcom Corporation
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -38,5 +39,7 @@ extern const struct ethtool_ops bnxt_ethtool_ops;
|
||||
u32 _bnxt_fw_to_ethtool_adv_spds(u16, u8);
|
||||
u32 bnxt_fw_to_ethtool_speed(u16);
|
||||
u16 bnxt_get_fw_auto_link_speeds(u32);
|
||||
void bnxt_ethtool_init(struct bnxt *bp);
|
||||
void bnxt_ethtool_free(struct bnxt *bp);
|
||||
|
||||
#endif
|
||||
|
@ -11,19 +11,21 @@
|
||||
#ifndef BNXT_HSI_H
|
||||
#define BNXT_HSI_H
|
||||
|
||||
/* HSI and HWRM Specification 1.7.0 */
|
||||
/* HSI and HWRM Specification 1.7.6 */
|
||||
#define HWRM_VERSION_MAJOR 1
|
||||
#define HWRM_VERSION_MINOR 7
|
||||
#define HWRM_VERSION_UPDATE 0
|
||||
#define HWRM_VERSION_UPDATE 6
|
||||
|
||||
#define HWRM_VERSION_STR "1.7.0"
|
||||
#define HWRM_VERSION_RSVD 2 /* non-zero means beta version */
|
||||
|
||||
#define HWRM_VERSION_STR "1.7.6.2"
|
||||
/*
|
||||
* Following is the signature for HWRM message field that indicates not
|
||||
* applicable (All F's). Need to cast it the size of the field if needed.
|
||||
*/
|
||||
#define HWRM_NA_SIGNATURE ((__le32)(-1))
|
||||
#define HWRM_MAX_REQ_LEN (128) /* hwrm_func_buf_rgtr */
|
||||
#define HWRM_MAX_RESP_LEN (176) /* hwrm_func_qstats */
|
||||
#define HWRM_MAX_RESP_LEN (248) /* hwrm_selftest_qlist */
|
||||
#define HW_HASH_INDEX_SIZE 0x80 /* 7 bit indirection table index. */
|
||||
#define HW_HASH_KEY_SIZE 40
|
||||
#define HWRM_RESP_VALID_KEY 1 /* valid key for HWRM response */
|
||||
@ -571,9 +573,10 @@ struct hwrm_ver_get_output {
|
||||
__le16 max_req_win_len;
|
||||
__le16 max_resp_len;
|
||||
__le16 def_req_timeout;
|
||||
u8 init_pending;
|
||||
#define VER_GET_RESP_INIT_PENDING_DEV_NOT_RDY 0x1UL
|
||||
u8 unused_0;
|
||||
u8 unused_1;
|
||||
u8 unused_2;
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
@ -809,6 +812,8 @@ struct hwrm_func_qcfg_output {
|
||||
#define FUNC_QCFG_RESP_FLAGS_OOB_WOL_BMP_ENABLED 0x2UL
|
||||
#define FUNC_QCFG_RESP_FLAGS_FW_DCBX_AGENT_ENABLED 0x4UL
|
||||
#define FUNC_QCFG_RESP_FLAGS_STD_TX_RING_MODE_ENABLED 0x8UL
|
||||
#define FUNC_QCFG_RESP_FLAGS_FW_LLDP_AGENT_ENABLED 0x10UL
|
||||
#define FUNC_QCFG_RESP_FLAGS_MULTI_HOST 0x20UL
|
||||
u8 mac_address[6];
|
||||
__le16 pci_id;
|
||||
__le16 alloc_rsscos_ctx;
|
||||
@ -827,10 +832,12 @@ struct hwrm_func_qcfg_output {
|
||||
#define FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_5 0x3UL
|
||||
#define FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR2_0 0x4UL
|
||||
#define FUNC_QCFG_RESP_PORT_PARTITION_TYPE_UNKNOWN 0xffUL
|
||||
u8 unused_0;
|
||||
u8 port_pf_cnt;
|
||||
#define FUNC_QCFG_RESP_PORT_PF_CNT_UNAVAIL 0x0UL
|
||||
__le16 dflt_vnic_id;
|
||||
u8 unused_1;
|
||||
u8 unused_2;
|
||||
u8 host_cnt;
|
||||
#define FUNC_QCFG_RESP_HOST_CNT_UNAVAIL 0x0UL
|
||||
u8 unused_0;
|
||||
__le32 min_bw;
|
||||
#define FUNC_QCFG_RESP_MIN_BW_BW_VALUE_MASK 0xfffffffUL
|
||||
#define FUNC_QCFG_RESP_MIN_BW_BW_VALUE_SFT 0
|
||||
@ -867,12 +874,12 @@ struct hwrm_func_qcfg_output {
|
||||
#define FUNC_QCFG_RESP_EVB_MODE_NO_EVB 0x0UL
|
||||
#define FUNC_QCFG_RESP_EVB_MODE_VEB 0x1UL
|
||||
#define FUNC_QCFG_RESP_EVB_MODE_VEPA 0x2UL
|
||||
u8 unused_3;
|
||||
u8 unused_1;
|
||||
__le16 alloc_vfs;
|
||||
__le32 alloc_mcast_filters;
|
||||
__le32 alloc_hw_ring_grps;
|
||||
__le16 alloc_sp_tx_rings;
|
||||
u8 unused_4;
|
||||
u8 unused_2;
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
@ -888,16 +895,13 @@ struct hwrm_func_cfg_input {
|
||||
u8 unused_0;
|
||||
u8 unused_1;
|
||||
__le32 flags;
|
||||
#define FUNC_CFG_REQ_FLAGS_PROM_MODE 0x1UL
|
||||
#define FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK 0x2UL
|
||||
#define FUNC_CFG_REQ_FLAGS_SRC_IP_ADDR_CHECK 0x4UL
|
||||
#define FUNC_CFG_REQ_FLAGS_VLAN_PRI_MATCH 0x8UL
|
||||
#define FUNC_CFG_REQ_FLAGS_DFLT_PRI_NOMATCH 0x10UL
|
||||
#define FUNC_CFG_REQ_FLAGS_DISABLE_PAUSE 0x20UL
|
||||
#define FUNC_CFG_REQ_FLAGS_DISABLE_STP 0x40UL
|
||||
#define FUNC_CFG_REQ_FLAGS_DISABLE_LLDP 0x80UL
|
||||
#define FUNC_CFG_REQ_FLAGS_DISABLE_PTPV2 0x100UL
|
||||
#define FUNC_CFG_REQ_FLAGS_STD_TX_RING_MODE 0x200UL
|
||||
#define FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE 0x1UL
|
||||
#define FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE 0x2UL
|
||||
#define FUNC_CFG_REQ_FLAGS_RSVD_MASK 0x1fcUL
|
||||
#define FUNC_CFG_REQ_FLAGS_RSVD_SFT 2
|
||||
#define FUNC_CFG_REQ_FLAGS_STD_TX_RING_MODE_ENABLE 0x200UL
|
||||
#define FUNC_CFG_REQ_FLAGS_STD_TX_RING_MODE_DISABLE 0x400UL
|
||||
#define FUNC_CFG_REQ_FLAGS_VIRT_MAC_PERSIST 0x800UL
|
||||
__le32 enables;
|
||||
#define FUNC_CFG_REQ_ENABLES_MTU 0x1UL
|
||||
#define FUNC_CFG_REQ_ENABLES_MRU 0x2UL
|
||||
@ -1013,7 +1017,7 @@ struct hwrm_func_qstats_output {
|
||||
__le64 tx_ucast_pkts;
|
||||
__le64 tx_mcast_pkts;
|
||||
__le64 tx_bcast_pkts;
|
||||
__le64 tx_err_pkts;
|
||||
__le64 tx_discard_pkts;
|
||||
__le64 tx_drop_pkts;
|
||||
__le64 tx_ucast_bytes;
|
||||
__le64 tx_mcast_bytes;
|
||||
@ -1021,7 +1025,7 @@ struct hwrm_func_qstats_output {
|
||||
__le64 rx_ucast_pkts;
|
||||
__le64 rx_mcast_pkts;
|
||||
__le64 rx_bcast_pkts;
|
||||
__le64 rx_err_pkts;
|
||||
__le64 rx_discard_pkts;
|
||||
__le64 rx_drop_pkts;
|
||||
__le64 rx_ucast_bytes;
|
||||
__le64 rx_mcast_bytes;
|
||||
@ -4743,6 +4747,165 @@ struct hwrm_temp_monitor_query_output {
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
/* hwrm_wol_filter_alloc */
|
||||
/* Input (64 bytes) */
|
||||
struct hwrm_wol_filter_alloc_input {
|
||||
__le16 req_type;
|
||||
__le16 cmpl_ring;
|
||||
__le16 seq_id;
|
||||
__le16 target_id;
|
||||
__le64 resp_addr;
|
||||
__le32 flags;
|
||||
__le32 enables;
|
||||
#define WOL_FILTER_ALLOC_REQ_ENABLES_MAC_ADDRESS 0x1UL
|
||||
#define WOL_FILTER_ALLOC_REQ_ENABLES_PATTERN_OFFSET 0x2UL
|
||||
#define WOL_FILTER_ALLOC_REQ_ENABLES_PATTERN_BUF_SIZE 0x4UL
|
||||
#define WOL_FILTER_ALLOC_REQ_ENABLES_PATTERN_BUF_ADDR 0x8UL
|
||||
#define WOL_FILTER_ALLOC_REQ_ENABLES_PATTERN_MASK_ADDR 0x10UL
|
||||
#define WOL_FILTER_ALLOC_REQ_ENABLES_PATTERN_MASK_SIZE 0x20UL
|
||||
__le16 port_id;
|
||||
u8 wol_type;
|
||||
#define WOL_FILTER_ALLOC_REQ_WOL_TYPE_MAGICPKT 0x0UL
|
||||
#define WOL_FILTER_ALLOC_REQ_WOL_TYPE_BMP 0x1UL
|
||||
#define WOL_FILTER_ALLOC_REQ_WOL_TYPE_INVALID 0xffUL
|
||||
u8 unused_0;
|
||||
__le32 unused_1;
|
||||
u8 mac_address[6];
|
||||
__le16 pattern_offset;
|
||||
__le16 pattern_buf_size;
|
||||
__le16 pattern_mask_size;
|
||||
__le32 unused_2;
|
||||
__le64 pattern_buf_addr;
|
||||
__le64 pattern_mask_addr;
|
||||
};
|
||||
|
||||
/* Output (16 bytes) */
|
||||
struct hwrm_wol_filter_alloc_output {
|
||||
__le16 error_code;
|
||||
__le16 req_type;
|
||||
__le16 seq_id;
|
||||
__le16 resp_len;
|
||||
u8 wol_filter_id;
|
||||
u8 unused_0;
|
||||
__le16 unused_1;
|
||||
u8 unused_2;
|
||||
u8 unused_3;
|
||||
u8 unused_4;
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
/* hwrm_wol_filter_free */
|
||||
/* Input (32 bytes) */
|
||||
struct hwrm_wol_filter_free_input {
|
||||
__le16 req_type;
|
||||
__le16 cmpl_ring;
|
||||
__le16 seq_id;
|
||||
__le16 target_id;
|
||||
__le64 resp_addr;
|
||||
__le32 flags;
|
||||
#define WOL_FILTER_FREE_REQ_FLAGS_FREE_ALL_WOL_FILTERS 0x1UL
|
||||
__le32 enables;
|
||||
#define WOL_FILTER_FREE_REQ_ENABLES_WOL_FILTER_ID 0x1UL
|
||||
__le16 port_id;
|
||||
u8 wol_filter_id;
|
||||
u8 unused_0[5];
|
||||
};
|
||||
|
||||
/* Output (16 bytes) */
|
||||
struct hwrm_wol_filter_free_output {
|
||||
__le16 error_code;
|
||||
__le16 req_type;
|
||||
__le16 seq_id;
|
||||
__le16 resp_len;
|
||||
__le32 unused_0;
|
||||
u8 unused_1;
|
||||
u8 unused_2;
|
||||
u8 unused_3;
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
/* hwrm_wol_filter_qcfg */
|
||||
/* Input (56 bytes) */
|
||||
struct hwrm_wol_filter_qcfg_input {
|
||||
__le16 req_type;
|
||||
__le16 cmpl_ring;
|
||||
__le16 seq_id;
|
||||
__le16 target_id;
|
||||
__le64 resp_addr;
|
||||
__le16 port_id;
|
||||
__le16 handle;
|
||||
__le32 unused_0;
|
||||
__le64 pattern_buf_addr;
|
||||
__le16 pattern_buf_size;
|
||||
u8 unused_1;
|
||||
u8 unused_2;
|
||||
u8 unused_3[3];
|
||||
u8 unused_4;
|
||||
__le64 pattern_mask_addr;
|
||||
__le16 pattern_mask_size;
|
||||
__le16 unused_5[3];
|
||||
};
|
||||
|
||||
/* Output (32 bytes) */
|
||||
struct hwrm_wol_filter_qcfg_output {
|
||||
__le16 error_code;
|
||||
__le16 req_type;
|
||||
__le16 seq_id;
|
||||
__le16 resp_len;
|
||||
__le16 next_handle;
|
||||
u8 wol_filter_id;
|
||||
u8 wol_type;
|
||||
#define WOL_FILTER_QCFG_RESP_WOL_TYPE_MAGICPKT 0x0UL
|
||||
#define WOL_FILTER_QCFG_RESP_WOL_TYPE_BMP 0x1UL
|
||||
#define WOL_FILTER_QCFG_RESP_WOL_TYPE_INVALID 0xffUL
|
||||
__le32 unused_0;
|
||||
u8 mac_address[6];
|
||||
__le16 pattern_offset;
|
||||
__le16 pattern_size;
|
||||
__le16 pattern_mask_size;
|
||||
u8 unused_1;
|
||||
u8 unused_2;
|
||||
u8 unused_3;
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
/* hwrm_wol_reason_qcfg */
|
||||
/* Input (40 bytes) */
|
||||
struct hwrm_wol_reason_qcfg_input {
|
||||
__le16 req_type;
|
||||
__le16 cmpl_ring;
|
||||
__le16 seq_id;
|
||||
__le16 target_id;
|
||||
__le64 resp_addr;
|
||||
__le16 port_id;
|
||||
u8 unused_0;
|
||||
u8 unused_1;
|
||||
u8 unused_2[3];
|
||||
u8 unused_3;
|
||||
__le64 wol_pkt_buf_addr;
|
||||
__le16 wol_pkt_buf_size;
|
||||
__le16 unused_4[3];
|
||||
};
|
||||
|
||||
/* Output (16 bytes) */
|
||||
struct hwrm_wol_reason_qcfg_output {
|
||||
__le16 error_code;
|
||||
__le16 req_type;
|
||||
__le16 seq_id;
|
||||
__le16 resp_len;
|
||||
u8 wol_filter_id;
|
||||
u8 wol_reason;
|
||||
#define WOL_REASON_QCFG_RESP_WOL_REASON_MAGICPKT 0x0UL
|
||||
#define WOL_REASON_QCFG_RESP_WOL_REASON_BMP 0x1UL
|
||||
#define WOL_REASON_QCFG_RESP_WOL_REASON_INVALID 0xffUL
|
||||
u8 wol_pkt_len;
|
||||
u8 unused_0;
|
||||
u8 unused_1;
|
||||
u8 unused_2;
|
||||
u8 unused_3;
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
/* hwrm_nvm_read */
|
||||
/* Input (40 bytes) */
|
||||
struct hwrm_nvm_read_input {
|
||||
@ -4773,32 +4936,6 @@ struct hwrm_nvm_read_output {
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
/* hwrm_nvm_raw_dump */
|
||||
/* Input (32 bytes) */
|
||||
struct hwrm_nvm_raw_dump_input {
|
||||
__le16 req_type;
|
||||
__le16 cmpl_ring;
|
||||
__le16 seq_id;
|
||||
__le16 target_id;
|
||||
__le64 resp_addr;
|
||||
__le64 host_dest_addr;
|
||||
__le32 offset;
|
||||
__le32 len;
|
||||
};
|
||||
|
||||
/* Output (16 bytes) */
|
||||
struct hwrm_nvm_raw_dump_output {
|
||||
__le16 error_code;
|
||||
__le16 req_type;
|
||||
__le16 seq_id;
|
||||
__le16 resp_len;
|
||||
__le32 unused_0;
|
||||
u8 unused_1;
|
||||
u8 unused_2;
|
||||
u8 unused_3;
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
/* hwrm_nvm_get_dir_entries */
|
||||
/* Input (24 bytes) */
|
||||
struct hwrm_nvm_get_dir_entries_input {
|
||||
@ -4881,6 +5018,15 @@ struct hwrm_nvm_write_output {
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
/* Command specific Error Codes (8 bytes) */
|
||||
struct hwrm_nvm_write_cmd_err {
|
||||
u8 code;
|
||||
#define NVM_WRITE_CMD_ERR_CODE_UNKNOWN 0x0UL
|
||||
#define NVM_WRITE_CMD_ERR_CODE_FRAG_ERR 0x1UL
|
||||
#define NVM_WRITE_CMD_ERR_CODE_NO_SPACE 0x2UL
|
||||
u8 unused_0[7];
|
||||
};
|
||||
|
||||
/* hwrm_nvm_modify */
|
||||
/* Input (40 bytes) */
|
||||
struct hwrm_nvm_modify_input {
|
||||
@ -5112,6 +5258,100 @@ struct hwrm_nvm_install_update_cmd_err {
|
||||
u8 unused_0[7];
|
||||
};
|
||||
|
||||
/* hwrm_selftest_qlist */
|
||||
/* Input (16 bytes) */
|
||||
struct hwrm_selftest_qlist_input {
|
||||
__le16 req_type;
|
||||
__le16 cmpl_ring;
|
||||
__le16 seq_id;
|
||||
__le16 target_id;
|
||||
__le64 resp_addr;
|
||||
};
|
||||
|
||||
/* Output (248 bytes) */
|
||||
struct hwrm_selftest_qlist_output {
|
||||
__le16 error_code;
|
||||
__le16 req_type;
|
||||
__le16 seq_id;
|
||||
__le16 resp_len;
|
||||
u8 num_tests;
|
||||
u8 available_tests;
|
||||
#define SELFTEST_QLIST_RESP_AVAILABLE_TESTS_NVM_TEST 0x1UL
|
||||
#define SELFTEST_QLIST_RESP_AVAILABLE_TESTS_LINK_TEST 0x2UL
|
||||
#define SELFTEST_QLIST_RESP_AVAILABLE_TESTS_REGISTER_TEST 0x4UL
|
||||
#define SELFTEST_QLIST_RESP_AVAILABLE_TESTS_MEMORY_TEST 0x8UL
|
||||
u8 offline_tests;
|
||||
#define SELFTEST_QLIST_RESP_OFFLINE_TESTS_NVM_TEST 0x1UL
|
||||
#define SELFTEST_QLIST_RESP_OFFLINE_TESTS_LINK_TEST 0x2UL
|
||||
#define SELFTEST_QLIST_RESP_OFFLINE_TESTS_REGISTER_TEST 0x4UL
|
||||
#define SELFTEST_QLIST_RESP_OFFLINE_TESTS_MEMORY_TEST 0x8UL
|
||||
u8 unused_0;
|
||||
__le16 test_timeout;
|
||||
u8 unused_1;
|
||||
u8 unused_2;
|
||||
char test0_name[32];
|
||||
char test1_name[32];
|
||||
char test2_name[32];
|
||||
char test3_name[32];
|
||||
char test4_name[32];
|
||||
char test5_name[32];
|
||||
char test6_name[32];
|
||||
char test7_name[32];
|
||||
};
|
||||
|
||||
/* hwrm_selftest_exec */
|
||||
/* Input (24 bytes) */
|
||||
struct hwrm_selftest_exec_input {
|
||||
__le16 req_type;
|
||||
__le16 cmpl_ring;
|
||||
__le16 seq_id;
|
||||
__le16 target_id;
|
||||
__le64 resp_addr;
|
||||
u8 flags;
|
||||
#define SELFTEST_EXEC_REQ_FLAGS_NVM_TEST 0x1UL
|
||||
#define SELFTEST_EXEC_REQ_FLAGS_LINK_TEST 0x2UL
|
||||
#define SELFTEST_EXEC_REQ_FLAGS_REGISTER_TEST 0x4UL
|
||||
#define SELFTEST_EXEC_REQ_FLAGS_MEMORY_TEST 0x8UL
|
||||
u8 unused_0[7];
|
||||
};
|
||||
|
||||
/* Output (16 bytes) */
|
||||
struct hwrm_selftest_exec_output {
|
||||
__le16 error_code;
|
||||
__le16 req_type;
|
||||
__le16 seq_id;
|
||||
__le16 resp_len;
|
||||
u8 requested_tests;
|
||||
#define SELFTEST_EXEC_RESP_REQUESTED_TESTS_NVM_TEST 0x1UL
|
||||
#define SELFTEST_EXEC_RESP_REQUESTED_TESTS_LINK_TEST 0x2UL
|
||||
#define SELFTEST_EXEC_RESP_REQUESTED_TESTS_REGISTER_TEST 0x4UL
|
||||
#define SELFTEST_EXEC_RESP_REQUESTED_TESTS_MEMORY_TEST 0x8UL
|
||||
u8 test_success;
|
||||
#define SELFTEST_EXEC_RESP_TEST_SUCCESS_NVM_TEST 0x1UL
|
||||
#define SELFTEST_EXEC_RESP_TEST_SUCCESS_LINK_TEST 0x2UL
|
||||
#define SELFTEST_EXEC_RESP_TEST_SUCCESS_REGISTER_TEST 0x4UL
|
||||
#define SELFTEST_EXEC_RESP_TEST_SUCCESS_MEMORY_TEST 0x8UL
|
||||
__le16 unused_0[3];
|
||||
};
|
||||
|
||||
/* hwrm_selftest_irq */
|
||||
/* Input (16 bytes) */
|
||||
struct hwrm_selftest_irq_input {
|
||||
__le16 req_type;
|
||||
__le16 cmpl_ring;
|
||||
__le16 seq_id;
|
||||
__le16 target_id;
|
||||
__le64 resp_addr;
|
||||
};
|
||||
|
||||
/* Output (8 bytes) */
|
||||
struct hwrm_selftest_irq_output {
|
||||
__le16 error_code;
|
||||
__le16 req_type;
|
||||
__le16 seq_id;
|
||||
__le16 resp_len;
|
||||
};
|
||||
|
||||
/* Hardware Resource Manager Specification */
|
||||
/* Input (16 bytes) */
|
||||
struct input {
|
||||
@ -5130,6 +5370,16 @@ struct output {
|
||||
__le16 resp_len;
|
||||
};
|
||||
|
||||
/* Short Command Structure (16 bytes) */
|
||||
struct hwrm_short_input {
|
||||
__le16 req_type;
|
||||
__le16 signature;
|
||||
#define SHORT_REQ_SIGNATURE_SHORT_CMD 0x4321UL
|
||||
__le16 unused_0;
|
||||
__le16 size;
|
||||
__le64 req_addr;
|
||||
};
|
||||
|
||||
/* Command numbering (8 bytes) */
|
||||
struct cmd_nums {
|
||||
__le16 req_type;
|
||||
@ -5252,11 +5502,15 @@ struct cmd_nums {
|
||||
#define HWRM_CFA_FLOW_FLUSH (0x105UL)
|
||||
#define HWRM_CFA_FLOW_STATS (0x106UL)
|
||||
#define HWRM_CFA_FLOW_INFO (0x107UL)
|
||||
#define HWRM_SELFTEST_QLIST (0x200UL)
|
||||
#define HWRM_SELFTEST_EXEC (0x201UL)
|
||||
#define HWRM_SELFTEST_IRQ (0x202UL)
|
||||
#define HWRM_DBG_READ_DIRECT (0xff10UL)
|
||||
#define HWRM_DBG_READ_INDIRECT (0xff11UL)
|
||||
#define HWRM_DBG_WRITE_DIRECT (0xff12UL)
|
||||
#define HWRM_DBG_WRITE_INDIRECT (0xff13UL)
|
||||
#define HWRM_DBG_DUMP (0xff14UL)
|
||||
#define HWRM_NVM_FACTORY_DEFAULTS (0xffeeUL)
|
||||
#define HWRM_NVM_VALIDATE_OPTION (0xffefUL)
|
||||
#define HWRM_NVM_FLUSH (0xfff0UL)
|
||||
#define HWRM_NVM_GET_VARIABLE (0xfff1UL)
|
||||
@ -5464,6 +5718,7 @@ struct hwrm_struct_hdr {
|
||||
#define STRUCT_HDR_STRUCT_ID_DCBX_FEATURE_STATE 0x422UL
|
||||
#define STRUCT_HDR_STRUCT_ID_LLDP_GENERIC 0x424UL
|
||||
#define STRUCT_HDR_STRUCT_ID_LLDP_DEVICE 0x426UL
|
||||
#define STRUCT_HDR_STRUCT_ID_AFM_OPAQUE 0x1UL
|
||||
#define STRUCT_HDR_STRUCT_ID_PORT_DESCRIPTION 0xaUL
|
||||
__le16 len;
|
||||
u8 version;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2014-2016 Broadcom Corporation
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -84,6 +85,9 @@ int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting)
|
||||
u32 func_flags;
|
||||
int rc;
|
||||
|
||||
if (bp->hwrm_spec_code < 0x10701)
|
||||
return -ENOTSUPP;
|
||||
|
||||
rc = bnxt_vf_ndo_prep(bp, vf_id);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -96,9 +100,9 @@ int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting)
|
||||
|
||||
func_flags = vf->func_flags;
|
||||
if (setting)
|
||||
func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK;
|
||||
func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE;
|
||||
else
|
||||
func_flags &= ~FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK;
|
||||
func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE;
|
||||
/*TODO: if the driver supports VLAN filter on guest VLAN,
|
||||
* the spoof check should also include vlan anti-spoofing
|
||||
*/
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2014-2016 Broadcom Corporation
|
||||
* Copyright (c) 2016-2017 Broadcom Limited
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -19,11 +19,10 @@
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_xdp.h"
|
||||
|
||||
static void bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
||||
dma_addr_t mapping, u32 len, u16 rx_prod)
|
||||
void bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
||||
dma_addr_t mapping, u32 len, u16 rx_prod)
|
||||
{
|
||||
struct bnxt_sw_tx_bd *tx_buf;
|
||||
struct tx_bd_ext *txbd1;
|
||||
struct tx_bd *txbd;
|
||||
u32 flags;
|
||||
u16 prod;
|
||||
@ -33,22 +32,12 @@ static void bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
||||
tx_buf->rx_prod = rx_prod;
|
||||
|
||||
txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
|
||||
flags = (len << TX_BD_LEN_SHIFT) | TX_BD_TYPE_LONG_TX_BD |
|
||||
(2 << TX_BD_FLAGS_BD_CNT_SHIFT) | TX_BD_FLAGS_COAL_NOW |
|
||||
flags = (len << TX_BD_LEN_SHIFT) | (1 << TX_BD_FLAGS_BD_CNT_SHIFT) |
|
||||
TX_BD_FLAGS_PACKET_END | bnxt_lhint_arr[len >> 9];
|
||||
txbd->tx_bd_len_flags_type = cpu_to_le32(flags);
|
||||
txbd->tx_bd_opaque = prod;
|
||||
txbd->tx_bd_haddr = cpu_to_le64(mapping);
|
||||
|
||||
prod = NEXT_TX(prod);
|
||||
txbd1 = (struct tx_bd_ext *)
|
||||
&txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
|
||||
|
||||
txbd1->tx_bd_hsize_lflags = cpu_to_le32(0);
|
||||
txbd1->tx_bd_mss = cpu_to_le32(0);
|
||||
txbd1->tx_bd_cfa_action = cpu_to_le32(0);
|
||||
txbd1->tx_bd_cfa_meta = cpu_to_le32(0);
|
||||
|
||||
prod = NEXT_TX(prod);
|
||||
txr->tx_prod = prod;
|
||||
}
|
||||
@ -66,7 +55,6 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
|
||||
for (i = 0; i < nr_pkts; i++) {
|
||||
last_tx_cons = tx_cons;
|
||||
tx_cons = NEXT_TX(tx_cons);
|
||||
tx_cons = NEXT_TX(tx_cons);
|
||||
}
|
||||
txr->tx_cons = tx_cons;
|
||||
if (bnxt_tx_avail(bp, txr) == bp->tx_ring_size) {
|
||||
@ -133,7 +121,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
|
||||
return false;
|
||||
|
||||
case XDP_TX:
|
||||
if (tx_avail < 2) {
|
||||
if (tx_avail < 1) {
|
||||
trace_xdp_exception(bp->dev, xdp_prog, act);
|
||||
bnxt_reuse_rx_data(rxr, cons, page);
|
||||
return true;
|
||||
|
@ -10,6 +10,8 @@
|
||||
#ifndef BNXT_XDP_H
|
||||
#define BNXT_XDP_H
|
||||
|
||||
void bnxt_xmit_xdp(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
||||
dma_addr_t mapping, u32 len, u16 rx_prod);
|
||||
void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts);
|
||||
bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
|
||||
struct page *page, u8 **data_ptr, unsigned int *len,
|
||||
|
Loading…
Reference in New Issue
Block a user