Skip to content

Commit

Permalink
Merge branch 'bnxt_en-WoL-selftest-XDP_TX-optimize'
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Apr 5, 2017
2 parents 2f5e9f8 + 68a946b commit 5422e5a
Show file tree
Hide file tree
Showing 9 changed files with 942 additions and 58 deletions.
207 changes: 205 additions & 2 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -7598,6 +7717,88 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
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
Expand Down Expand Up @@ -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,
Expand Down
21 changes: 19 additions & 2 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 | \
Expand Down Expand Up @@ -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];

Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 5422e5a

Please sign in to comment.