Commit 5749d6af authored by David S. Miller's avatar David S. Miller

Merge branch 'bnxt_en-next'

Michael Chan says:

====================
bnxt_en: Update for net-next.

Misc. updates including updated firmware interface, some additional
port statistics, a new IRQ assignment scheme for the RDMA driver, support
for VF trust, and other changes and improvements for SRIOV.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents eeb0a2a5 ec86f14e
This diff is collapsed.
...@@ -12,11 +12,11 @@ ...@@ -12,11 +12,11 @@
#define BNXT_H #define BNXT_H
#define DRV_MODULE_NAME "bnxt_en" #define DRV_MODULE_NAME "bnxt_en"
#define DRV_MODULE_VERSION "1.9.0" #define DRV_MODULE_VERSION "1.9.1"
#define DRV_VER_MAJ 1 #define DRV_VER_MAJ 1
#define DRV_VER_MIN 9 #define DRV_VER_MIN 9
#define DRV_VER_UPD 0 #define DRV_VER_UPD 1
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/rhashtable.h> #include <linux/rhashtable.h>
...@@ -573,6 +573,10 @@ struct bnxt_ring_struct { ...@@ -573,6 +573,10 @@ struct bnxt_ring_struct {
void **vmem; void **vmem;
u16 fw_ring_id; /* Ring id filled by Chimp FW */ u16 fw_ring_id; /* Ring id filled by Chimp FW */
union {
u16 grp_idx;
u16 map_idx; /* Used by cmpl rings */
};
u8 queue_id; u8 queue_id;
}; };
...@@ -786,6 +790,7 @@ struct bnxt_hw_resc { ...@@ -786,6 +790,7 @@ struct bnxt_hw_resc {
u16 min_tx_rings; u16 min_tx_rings;
u16 max_tx_rings; u16 max_tx_rings;
u16 resv_tx_rings; u16 resv_tx_rings;
u16 max_tx_sch_inputs;
u16 min_rx_rings; u16 min_rx_rings;
u16 max_rx_rings; u16 max_rx_rings;
u16 resv_rx_rings; u16 resv_rx_rings;
...@@ -815,6 +820,7 @@ struct bnxt_vf_info { ...@@ -815,6 +820,7 @@ struct bnxt_vf_info {
#define BNXT_VF_SPOOFCHK 0x2 #define BNXT_VF_SPOOFCHK 0x2
#define BNXT_VF_LINK_FORCED 0x4 #define BNXT_VF_LINK_FORCED 0x4
#define BNXT_VF_LINK_UP 0x8 #define BNXT_VF_LINK_UP 0x8
#define BNXT_VF_TRUST 0x10
u32 func_flags; /* func cfg flags */ u32 func_flags; /* func cfg flags */
u32 min_tx_rate; u32 min_tx_rate;
u32 max_tx_rate; u32 max_tx_rate;
...@@ -1151,7 +1157,9 @@ struct bnxt { ...@@ -1151,7 +1157,9 @@ struct bnxt {
#define BNXT_FLAG_FW_DCBX_AGENT 0x800000 #define BNXT_FLAG_FW_DCBX_AGENT 0x800000
#define BNXT_FLAG_CHIP_NITRO_A0 0x1000000 #define BNXT_FLAG_CHIP_NITRO_A0 0x1000000
#define BNXT_FLAG_DIM 0x2000000 #define BNXT_FLAG_DIM 0x2000000
#define BNXT_FLAG_ROCE_MIRROR_CAP 0x4000000
#define BNXT_FLAG_NEW_RM 0x8000000 #define BNXT_FLAG_NEW_RM 0x8000000
#define BNXT_FLAG_PORT_STATS_EXT 0x10000000
#define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA | \ #define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA | \
BNXT_FLAG_RFS | \ BNXT_FLAG_RFS | \
...@@ -1271,8 +1279,10 @@ struct bnxt { ...@@ -1271,8 +1279,10 @@ struct bnxt {
struct rx_port_stats *hw_rx_port_stats; struct rx_port_stats *hw_rx_port_stats;
struct tx_port_stats *hw_tx_port_stats; struct tx_port_stats *hw_tx_port_stats;
struct rx_port_stats_ext *hw_rx_port_stats_ext;
dma_addr_t hw_rx_port_stats_map; dma_addr_t hw_rx_port_stats_map;
dma_addr_t hw_tx_port_stats_map; dma_addr_t hw_tx_port_stats_map;
dma_addr_t hw_rx_port_stats_ext_map;
int hw_port_stats_size; int hw_port_stats_size;
u16 hwrm_max_req_len; u16 hwrm_max_req_len;
...@@ -1383,6 +1393,9 @@ struct bnxt { ...@@ -1383,6 +1393,9 @@ struct bnxt {
((offsetof(struct tx_port_stats, counter) + \ ((offsetof(struct tx_port_stats, counter) + \
sizeof(struct rx_port_stats) + 512) / 8) sizeof(struct rx_port_stats) + 512) / 8)
#define BNXT_RX_STATS_EXT_OFFSET(counter) \
(offsetof(struct rx_port_stats_ext, counter) / 8)
#define I2C_DEV_ADDR_A0 0xa0 #define I2C_DEV_ADDR_A0 0xa0
#define I2C_DEV_ADDR_A2 0xa2 #define I2C_DEV_ADDR_A2 0xa2
#define SFP_EEPROM_SFF_8472_COMP_ADDR 0x5e #define SFP_EEPROM_SFF_8472_COMP_ADDR 0x5e
...@@ -1441,13 +1454,17 @@ unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp); ...@@ -1441,13 +1454,17 @@ unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp);
void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max); void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max);
unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp); unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp);
void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max); void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max);
unsigned int bnxt_get_max_func_irqs(struct bnxt *bp);
void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max); void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max);
int bnxt_get_avail_msix(struct bnxt *bp, int num);
int bnxt_reserve_rings(struct bnxt *bp);
void bnxt_tx_disable(struct bnxt *bp); void bnxt_tx_disable(struct bnxt *bp);
void bnxt_tx_enable(struct bnxt *bp); void bnxt_tx_enable(struct bnxt *bp);
int bnxt_hwrm_set_pause(struct bnxt *); int bnxt_hwrm_set_pause(struct bnxt *);
int bnxt_hwrm_set_link_setting(struct bnxt *, bool, bool); int bnxt_hwrm_set_link_setting(struct bnxt *, bool, bool);
int bnxt_hwrm_alloc_wol_fltr(struct bnxt *bp); int bnxt_hwrm_alloc_wol_fltr(struct bnxt *bp);
int bnxt_hwrm_free_wol_fltr(struct bnxt *bp); int bnxt_hwrm_free_wol_fltr(struct bnxt *bp);
int bnxt_hwrm_func_resc_qcaps(struct bnxt *bp, bool all);
int bnxt_hwrm_fw_set_time(struct bnxt *); int bnxt_hwrm_fw_set_time(struct bnxt *);
int bnxt_open_nic(struct bnxt *, bool, bool); int bnxt_open_nic(struct bnxt *, bool, bool);
int bnxt_half_open_nic(struct bnxt *bp); int bnxt_half_open_nic(struct bnxt *bp);
......
/* Broadcom NetXtreme-C/E network driver. /* Broadcom NetXtreme-C/E network driver.
* *
* Copyright (c) 2014-2016 Broadcom Corporation * Copyright (c) 2014-2016 Broadcom Corporation
* Copyright (c) 2016-2017 Broadcom Limited * Copyright (c) 2016-2018 Broadcom Limited
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -34,7 +34,8 @@ struct bnxt_cos2bw_cfg { ...@@ -34,7 +34,8 @@ struct bnxt_cos2bw_cfg {
}; };
#define BNXT_LLQ(q_profile) \ #define BNXT_LLQ(q_profile) \
((q_profile) == QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS) ((q_profile) == \
QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS_ROCE)
#define HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL 0x0300 #define HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL 0x0300
......
...@@ -137,6 +137,9 @@ static int bnxt_set_coalesce(struct net_device *dev, ...@@ -137,6 +137,9 @@ static int bnxt_set_coalesce(struct net_device *dev,
#define BNXT_TX_STATS_ENTRY(counter) \ #define BNXT_TX_STATS_ENTRY(counter) \
{ BNXT_TX_STATS_OFFSET(counter), __stringify(counter) } { BNXT_TX_STATS_OFFSET(counter), __stringify(counter) }
#define BNXT_RX_STATS_EXT_ENTRY(counter) \
{ BNXT_RX_STATS_EXT_OFFSET(counter), __stringify(counter) }
static const struct { static const struct {
long offset; long offset;
char string[ETH_GSTRING_LEN]; char string[ETH_GSTRING_LEN];
...@@ -181,6 +184,8 @@ static const struct { ...@@ -181,6 +184,8 @@ static const struct {
BNXT_RX_STATS_ENTRY(rx_bytes), BNXT_RX_STATS_ENTRY(rx_bytes),
BNXT_RX_STATS_ENTRY(rx_runt_bytes), BNXT_RX_STATS_ENTRY(rx_runt_bytes),
BNXT_RX_STATS_ENTRY(rx_runt_frames), BNXT_RX_STATS_ENTRY(rx_runt_frames),
BNXT_RX_STATS_ENTRY(rx_stat_discard),
BNXT_RX_STATS_ENTRY(rx_stat_err),
BNXT_TX_STATS_ENTRY(tx_64b_frames), BNXT_TX_STATS_ENTRY(tx_64b_frames),
BNXT_TX_STATS_ENTRY(tx_65b_127b_frames), BNXT_TX_STATS_ENTRY(tx_65b_127b_frames),
...@@ -216,9 +221,24 @@ static const struct { ...@@ -216,9 +221,24 @@ static const struct {
BNXT_TX_STATS_ENTRY(tx_eee_lpi_duration), BNXT_TX_STATS_ENTRY(tx_eee_lpi_duration),
BNXT_TX_STATS_ENTRY(tx_total_collisions), BNXT_TX_STATS_ENTRY(tx_total_collisions),
BNXT_TX_STATS_ENTRY(tx_bytes), BNXT_TX_STATS_ENTRY(tx_bytes),
BNXT_TX_STATS_ENTRY(tx_xthol_frames),
BNXT_TX_STATS_ENTRY(tx_stat_discard),
BNXT_TX_STATS_ENTRY(tx_stat_error),
};
static const struct {
long offset;
char string[ETH_GSTRING_LEN];
} bnxt_port_stats_ext_arr[] = {
BNXT_RX_STATS_EXT_ENTRY(link_down_events),
BNXT_RX_STATS_EXT_ENTRY(continuous_pause_events),
BNXT_RX_STATS_EXT_ENTRY(resume_pause_events),
BNXT_RX_STATS_EXT_ENTRY(continuous_roce_pause_events),
BNXT_RX_STATS_EXT_ENTRY(resume_roce_pause_events),
}; };
#define BNXT_NUM_PORT_STATS ARRAY_SIZE(bnxt_port_stats_arr) #define BNXT_NUM_PORT_STATS ARRAY_SIZE(bnxt_port_stats_arr)
#define BNXT_NUM_PORT_STATS_EXT ARRAY_SIZE(bnxt_port_stats_ext_arr)
static int bnxt_get_num_stats(struct bnxt *bp) static int bnxt_get_num_stats(struct bnxt *bp)
{ {
...@@ -227,6 +247,9 @@ static int bnxt_get_num_stats(struct bnxt *bp) ...@@ -227,6 +247,9 @@ static int bnxt_get_num_stats(struct bnxt *bp)
if (bp->flags & BNXT_FLAG_PORT_STATS) if (bp->flags & BNXT_FLAG_PORT_STATS)
num_stats += BNXT_NUM_PORT_STATS; num_stats += BNXT_NUM_PORT_STATS;
if (bp->flags & BNXT_FLAG_PORT_STATS_EXT)
num_stats += BNXT_NUM_PORT_STATS_EXT;
return num_stats; return num_stats;
} }
...@@ -274,6 +297,14 @@ static void bnxt_get_ethtool_stats(struct net_device *dev, ...@@ -274,6 +297,14 @@ static void bnxt_get_ethtool_stats(struct net_device *dev,
bnxt_port_stats_arr[i].offset)); bnxt_port_stats_arr[i].offset));
} }
} }
if (bp->flags & BNXT_FLAG_PORT_STATS_EXT) {
__le64 *port_stats_ext = (__le64 *)bp->hw_rx_port_stats_ext;
for (i = 0; i < BNXT_NUM_PORT_STATS_EXT; i++, j++) {
buf[j] = le64_to_cpu(*(port_stats_ext +
bnxt_port_stats_ext_arr[i].offset));
}
}
} }
static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf) static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
...@@ -334,6 +365,12 @@ static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf) ...@@ -334,6 +365,12 @@ static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
buf += ETH_GSTRING_LEN; buf += ETH_GSTRING_LEN;
} }
} }
if (bp->flags & BNXT_FLAG_PORT_STATS_EXT) {
for (i = 0; i < BNXT_NUM_PORT_STATS_EXT; i++) {
strcpy(buf, bnxt_port_stats_ext_arr[i].string);
buf += ETH_GSTRING_LEN;
}
}
break; break;
case ETH_SS_TEST: case ETH_SS_TEST:
if (bp->num_tests) if (bp->num_tests)
...@@ -388,15 +425,26 @@ static void bnxt_get_channels(struct net_device *dev, ...@@ -388,15 +425,26 @@ static void bnxt_get_channels(struct net_device *dev,
struct ethtool_channels *channel) struct ethtool_channels *channel)
{ {
struct bnxt *bp = netdev_priv(dev); struct bnxt *bp = netdev_priv(dev);
struct bnxt_hw_resc *hw_resc = &bp->hw_resc;
int max_rx_rings, max_tx_rings, tcs; int max_rx_rings, max_tx_rings, tcs;
int max_tx_sch_inputs;
/* Get the most up-to-date max_tx_sch_inputs. */
if (bp->flags & BNXT_FLAG_NEW_RM)
bnxt_hwrm_func_resc_qcaps(bp, false);
max_tx_sch_inputs = hw_resc->max_tx_sch_inputs;
bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, true); bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, true);
if (max_tx_sch_inputs)
max_tx_rings = min_t(int, max_tx_rings, max_tx_sch_inputs);
channel->max_combined = min_t(int, max_rx_rings, max_tx_rings); channel->max_combined = min_t(int, max_rx_rings, max_tx_rings);
if (bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, false)) { if (bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, false)) {
max_rx_rings = 0; max_rx_rings = 0;
max_tx_rings = 0; max_tx_rings = 0;
} }
if (max_tx_sch_inputs)
max_tx_rings = min_t(int, max_tx_rings, max_tx_sch_inputs);
tcs = netdev_get_num_tc(dev); tcs = netdev_get_num_tc(dev);
if (tcs > 1) if (tcs > 1)
...@@ -2535,16 +2583,20 @@ static int bnxt_reset(struct net_device *dev, u32 *flags) ...@@ -2535,16 +2583,20 @@ static int bnxt_reset(struct net_device *dev, u32 *flags)
return -EOPNOTSUPP; return -EOPNOTSUPP;
rc = bnxt_firmware_reset(dev, BNXT_FW_RESET_CHIP); rc = bnxt_firmware_reset(dev, BNXT_FW_RESET_CHIP);
if (!rc) if (!rc) {
netdev_info(dev, "Reset request successful. Reload driver to complete reset\n"); netdev_info(dev, "Reset request successful. Reload driver to complete reset\n");
*flags = 0;
}
} else if (*flags == ETH_RESET_AP) { } else if (*flags == ETH_RESET_AP) {
/* This feature is not supported in older firmware versions */ /* This feature is not supported in older firmware versions */
if (bp->hwrm_spec_code < 0x10803) if (bp->hwrm_spec_code < 0x10803)
return -EOPNOTSUPP; return -EOPNOTSUPP;
rc = bnxt_firmware_reset(dev, BNXT_FW_RESET_AP); rc = bnxt_firmware_reset(dev, BNXT_FW_RESET_AP);
if (!rc) if (!rc) {
netdev_info(dev, "Reset Application Processor request successful.\n"); netdev_info(dev, "Reset Application Processor request successful.\n");
*flags = 0;
}
} else { } else {
rc = -EINVAL; rc = -EINVAL;
} }
......
/* Broadcom NetXtreme-C/E network driver. /* Broadcom NetXtreme-C/E network driver.
* *
* Copyright (c) 2014-2016 Broadcom Corporation * Copyright (c) 2014-2016 Broadcom Corporation
* Copyright (c) 2016-2017 Broadcom Limited * Copyright (c) 2016-2018 Broadcom Limited
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -121,6 +121,23 @@ int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting) ...@@ -121,6 +121,23 @@ int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting)
return rc; return rc;
} }
int bnxt_set_vf_trust(struct net_device *dev, int vf_id, bool trusted)
{
struct bnxt *bp = netdev_priv(dev);
struct bnxt_vf_info *vf;
if (bnxt_vf_ndo_prep(bp, vf_id))
return -EINVAL;
vf = &bp->pf.vf[vf_id];
if (trusted)
vf->flags |= BNXT_VF_TRUST;
else
vf->flags &= ~BNXT_VF_TRUST;
return 0;
}
int bnxt_get_vf_config(struct net_device *dev, int vf_id, int bnxt_get_vf_config(struct net_device *dev, int vf_id,
struct ifla_vf_info *ivi) struct ifla_vf_info *ivi)
{ {
...@@ -147,6 +164,7 @@ int bnxt_get_vf_config(struct net_device *dev, int vf_id, ...@@ -147,6 +164,7 @@ int bnxt_get_vf_config(struct net_device *dev, int vf_id,
else else
ivi->qos = 0; ivi->qos = 0;
ivi->spoofchk = !!(vf->flags & BNXT_VF_SPOOFCHK); ivi->spoofchk = !!(vf->flags & BNXT_VF_SPOOFCHK);
ivi->trusted = !!(vf->flags & BNXT_VF_TRUST);
if (!(vf->flags & BNXT_VF_LINK_FORCED)) if (!(vf->flags & BNXT_VF_LINK_FORCED))
ivi->linkstate = IFLA_VF_LINK_STATE_AUTO; ivi->linkstate = IFLA_VF_LINK_STATE_AUTO;
else if (vf->flags & BNXT_VF_LINK_UP) else if (vf->flags & BNXT_VF_LINK_UP)
...@@ -492,18 +510,16 @@ static int bnxt_hwrm_func_vf_resc_cfg(struct bnxt *bp, int num_vfs) ...@@ -492,18 +510,16 @@ static int bnxt_hwrm_func_vf_resc_cfg(struct bnxt *bp, int num_vfs)
} }
mutex_unlock(&bp->hwrm_cmd_lock); mutex_unlock(&bp->hwrm_cmd_lock);
if (pf->active_vfs) { if (pf->active_vfs) {
u16 n = 1; u16 n = pf->active_vfs;
if (pf->vf_resv_strategy != BNXT_VF_RESV_STRATEGY_MINIMAL) hw_resc->max_tx_rings -= le16_to_cpu(req.min_tx_rings) * n;
n = pf->active_vfs; hw_resc->max_rx_rings -= le16_to_cpu(req.min_rx_rings) * n;
hw_resc->max_hw_ring_grps -= le16_to_cpu(req.min_hw_ring_grps) *
hw_resc->max_tx_rings -= vf_tx_rings * n; n;
hw_resc->max_rx_rings -= vf_rx_rings * n; hw_resc->max_cp_rings -= le16_to_cpu(req.min_cmpl_rings) * n;
hw_resc->max_hw_ring_grps -= vf_ring_grps * n;
hw_resc->max_cp_rings -= vf_cp_rings * n;
hw_resc->max_rsscos_ctxs -= pf->active_vfs; hw_resc->max_rsscos_ctxs -= pf->active_vfs;
hw_resc->max_stat_ctxs -= vf_stat_ctx * n; hw_resc->max_stat_ctxs -= le16_to_cpu(req.min_stat_ctx) * n;
hw_resc->max_vnics -= vf_vnics * n; hw_resc->max_vnics -= le16_to_cpu(req.min_vnics) * n;
rc = pf->active_vfs; rc = pf->active_vfs;
} }
...@@ -886,18 +902,19 @@ static int bnxt_hwrm_exec_fwd_resp(struct bnxt *bp, struct bnxt_vf_info *vf, ...@@ -886,18 +902,19 @@ static int bnxt_hwrm_exec_fwd_resp(struct bnxt *bp, struct bnxt_vf_info *vf,
return rc; return rc;
} }
static int bnxt_vf_store_mac(struct bnxt *bp, struct bnxt_vf_info *vf) static int bnxt_vf_configure_mac(struct bnxt *bp, struct bnxt_vf_info *vf)
{ {
u32 msg_size = sizeof(struct hwrm_func_vf_cfg_input); u32 msg_size = sizeof(struct hwrm_func_vf_cfg_input);
struct hwrm_func_vf_cfg_input *req = struct hwrm_func_vf_cfg_input *req =
(struct hwrm_func_vf_cfg_input *)vf->hwrm_cmd_req_addr; (struct hwrm_func_vf_cfg_input *)vf->hwrm_cmd_req_addr;
/* Only allow VF to set a valid MAC address if the PF assigned MAC /* Allow VF to set a valid MAC address, if trust is set to on or
* address is zero * if the PF assigned MAC address is zero
*/ */
if (req->enables & cpu_to_le32(FUNC_VF_CFG_REQ_ENABLES_DFLT_MAC_ADDR)) { if (req->enables & cpu_to_le32(FUNC_VF_CFG_REQ_ENABLES_DFLT_MAC_ADDR)) {
if (is_valid_ether_addr(req->dflt_mac_addr) && if (is_valid_ether_addr(req->dflt_mac_addr) &&
!is_valid_ether_addr(vf->mac_addr)) { ((vf->flags & BNXT_VF_TRUST) ||
(!is_valid_ether_addr(vf->mac_addr)))) {
ether_addr_copy(vf->vf_mac_addr, req->dflt_mac_addr); ether_addr_copy(vf->vf_mac_addr, req->dflt_mac_addr);
return bnxt_hwrm_exec_fwd_resp(bp, vf, msg_size); return bnxt_hwrm_exec_fwd_resp(bp, vf, msg_size);
} }
...@@ -913,11 +930,17 @@ static int bnxt_vf_validate_set_mac(struct bnxt *bp, struct bnxt_vf_info *vf) ...@@ -913,11 +930,17 @@ static int bnxt_vf_validate_set_mac(struct bnxt *bp, struct bnxt_vf_info *vf)
(struct hwrm_cfa_l2_filter_alloc_input *)vf->hwrm_cmd_req_addr; (struct hwrm_cfa_l2_filter_alloc_input *)vf->hwrm_cmd_req_addr;
bool mac_ok = false; bool mac_ok = false;
/* VF MAC address must first match PF MAC address, if it is valid. if (!is_valid_ether_addr((const u8 *)req->l2_addr))
return bnxt_hwrm_fwd_err_resp(bp, vf, msg_size);
/* Allow VF to set a valid MAC address, if trust is set to on.
* Or VF MAC address must first match MAC address in PF's context.
* Otherwise, it must match the VF MAC address if firmware spec >= * Otherwise, it must match the VF MAC address if firmware spec >=
* 1.2.2 * 1.2.2
*/ */
if (is_valid_ether_addr(vf->mac_addr)) { if (vf->flags & BNXT_VF_TRUST) {
mac_ok = true;
} else if (is_valid_ether_addr(vf->mac_addr)) {
if (ether_addr_equal((const u8 *)req->l2_addr, vf->mac_addr)) if (ether_addr_equal((const u8 *)req->l2_addr, vf->mac_addr))
mac_ok = true; mac_ok = true;
} else if (is_valid_ether_addr(vf->vf_mac_addr)) { } else if (is_valid_ether_addr(vf->vf_mac_addr)) {
...@@ -951,7 +974,9 @@ static int bnxt_vf_set_link(struct bnxt *bp, struct bnxt_vf_info *vf) ...@@ -951,7 +974,9 @@ static int bnxt_vf_set_link(struct bnxt *bp, struct bnxt_vf_info *vf)
memcpy(&phy_qcfg_resp, &bp->link_info.phy_qcfg_resp, memcpy(&phy_qcfg_resp, &bp->link_info.phy_qcfg_resp,
sizeof(phy_qcfg_resp)); sizeof(phy_qcfg_resp));
mutex_unlock(&bp->hwrm_cmd_lock); mutex_unlock(&bp->hwrm_cmd_lock);
phy_qcfg_resp.resp_len = cpu_to_le16(sizeof(phy_qcfg_resp));
phy_qcfg_resp.seq_id = phy_qcfg_req->seq_id; phy_qcfg_resp.seq_id = phy_qcfg_req->seq_id;
phy_qcfg_resp.valid = 1;
if (vf->flags & BNXT_VF_LINK_UP) { if (vf->flags & BNXT_VF_LINK_UP) {
/* if physical link is down, force link up on VF */ /* if physical link is down, force link up on VF */
...@@ -993,7 +1018,7 @@ static int bnxt_vf_req_validate_snd(struct bnxt *bp, struct bnxt_vf_info *vf) ...@@ -993,7 +1018,7 @@ static int bnxt_vf_req_validate_snd(struct bnxt *bp, struct bnxt_vf_info *vf)
switch (req_type) { switch (req_type) {
case HWRM_FUNC_VF_CFG: case HWRM_FUNC_VF_CFG:
rc = bnxt_vf_store_mac(bp, vf); rc = bnxt_vf_configure_mac(bp, vf);
break; break;
case HWRM_CFA_L2_FILTER_ALLOC: case HWRM_CFA_L2_FILTER_ALLOC:
rc = bnxt_vf_validate_set_mac(bp, vf); rc = bnxt_vf_validate_set_mac(bp, vf);
......
/* Broadcom NetXtreme-C/E network driver. /* Broadcom NetXtreme-C/E network driver.
* *
* Copyright (c) 2014-2016 Broadcom Corporation * Copyright (c) 2014-2016 Broadcom Corporation
* Copyright (c) 2016-2017 Broadcom Limited * Copyright (c) 2016-2018 Broadcom Limited
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -17,6 +17,7 @@ int bnxt_set_vf_vlan(struct net_device *, int, u16, u8, __be16); ...@@ -17,6 +17,7 @@ int bnxt_set_vf_vlan(struct net_device *, int, u16, u8, __be16);
int bnxt_set_vf_bw(struct net_device *, int, int, int); int bnxt_set_vf_bw(struct net_device *, int, int, int);
int bnxt_set_vf_link_state(struct net_device *, int, int); int bnxt_set_vf_link_state(struct net_device *, int, int);
int bnxt_set_vf_spoofchk(struct net_device *, int, bool); int bnxt_set_vf_spoofchk(struct net_device *, int, bool);
int bnxt_set_vf_trust(struct net_device *dev, int vf_id, bool trust);
int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs); int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs);
void bnxt_sriov_disable(struct bnxt *); void bnxt_sriov_disable(struct bnxt *);
void bnxt_hwrm_exec_fwd_req(struct bnxt *); void bnxt_hwrm_exec_fwd_req(struct bnxt *);
......
/* Broadcom NetXtreme-C/E network driver. /* Broadcom NetXtreme-C/E network driver.
* *
* Copyright (c) 2016 Broadcom Limited * Copyright (c) 2016-2018 Broadcom Limited
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -101,13 +101,28 @@ static int bnxt_unregister_dev(struct bnxt_en_dev *edev, int ulp_id) ...@@ -101,13 +101,28 @@ static int bnxt_unregister_dev(struct bnxt_en_dev *edev, int ulp_id)
return 0; return 0;
} }
static void bnxt_fill_msix_vecs(struct bnxt *bp, struct bnxt_msix_entry *ent)
{
struct bnxt_en_dev *edev = bp->edev;
int num_msix, idx, i;
num_msix = edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested;
idx = edev->ulp_tbl[BNXT_ROCE_ULP].msix_base;
for (i = 0; i < num_msix; i++) {
ent[i].vector = bp->irq_tbl[idx + i].vector;
ent[i].ring_idx = idx + i;
ent[i].db_offset = (idx + i) * 0x80;
}
}
static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id, static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
struct bnxt_msix_entry *ent, int num_msix) struct bnxt_msix_entry *ent, int num_msix)
{ {
struct net_device *dev = edev->net; struct net_device *dev = edev->net;
struct bnxt *bp = netdev_priv(dev); struct bnxt *bp = netdev_priv(dev);
int max_idx, max_cp_rings; int max_idx, max_cp_rings;
int avail_msix, i, idx; int avail_msix, idx;
int rc = 0;
ASSERT_RTNL(); ASSERT_RTNL();
if (ulp_id != BNXT_ROCE_ULP) if (ulp_id != BNXT_ROCE_ULP)
...@@ -116,23 +131,47 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id, ...@@ -116,23 +131,47 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
if (!(bp->flags & BNXT_FLAG_USING_MSIX)) if (!(bp->flags & BNXT_FLAG_USING_MSIX))
return -ENODEV; return -ENODEV;
if (edev->ulp_tbl[ulp_id].msix_requested)
return -EAGAIN;
max_cp_rings = bnxt_get_max_func_cp_rings(bp); max_cp_rings = bnxt_get_max_func_cp_rings(bp);
max_idx = min_t(int, bp->total_irqs, max_cp_rings); avail_msix = bnxt_get_avail_msix(bp, num_msix);
avail_msix = max_idx - bp->cp_nr_rings;
if (!avail_msix) if (!avail_msix)
return -ENOMEM; return -ENOMEM;
if (avail_msix > num_msix) if (avail_msix > num_msix)
avail_msix = num_msix; avail_msix = num_msix;
idx = max_idx - avail_msix; if (bp->flags & BNXT_FLAG_NEW_RM) {
for (i = 0; i < avail_msix; i++) { idx = bp->cp_nr_rings;
ent[i].vector = bp->irq_tbl[idx + i].vector; } else {
ent[i].ring_idx = idx + i; max_idx = min_t(int, bp->total_irqs, max_cp_rings);
ent[i].db_offset = (idx + i) * 0x80; idx = max_idx - avail_msix;
} }
bnxt_set_max_func_irqs(bp, max_idx - avail_msix); edev->ulp_tbl[ulp_id].msix_base = idx;
bnxt_set_max_func_cp_rings(bp, max_cp_rings - avail_msix);
edev->ulp_tbl[ulp_id].msix_requested = avail_msix; edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
if (bp->total_irqs < (idx + avail_msix)) {
if (netif_running(dev)) {
bnxt_close_nic(bp, true, false);
rc = bnxt_open_nic(bp, true, false);
} else {
rc = bnxt_reserve_rings(bp);
}
}
if (rc) {
edev->ulp_tbl[ulp_id].msix_requested = 0;
return -EAGAIN;
}
if (bp->flags & BNXT_FLAG_NEW_RM) {
struct bnxt_hw_resc *hw_resc = &bp->hw_resc;
avail_msix = hw_resc->resv_cp_rings - bp->cp_nr_rings;
edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
}
bnxt_fill_msix_vecs(bp, ent);
bnxt_set_max_func_irqs(bp, bnxt_get_max_func_irqs(bp) - avail_msix);
bnxt_set_max_func_cp_rings(bp, max_cp_rings - avail_msix);
edev->flags |= BNXT_EN_FLAG_MSIX_REQUESTED;
return avail_msix; return avail_msix;
} }
...@@ -146,11 +185,40 @@ static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id) ...@@ -146,11 +185,40 @@ static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id)
if (ulp_id != BNXT_ROCE_ULP) if (ulp_id != BNXT_ROCE_ULP)
return -EINVAL; return -EINVAL;
if (!(edev->flags & BNXT_EN_FLAG_MSIX_REQUESTED))
return 0;
max_cp_rings = bnxt_get_max_func_cp_rings(bp); max_cp_rings = bnxt_get_max_func_cp_rings(bp);
msix_requested = edev->ulp_tbl[ulp_id].msix_requested; msix_requested = edev->ulp_tbl[ulp_id].msix_requested;
bnxt_set_max_func_cp_rings(bp, max_cp_rings + msix_requested); bnxt_set_max_func_cp_rings(bp, max_cp_rings + msix_requested);
edev->ulp_tbl[ulp_id].msix_requested = 0; edev->ulp_tbl[ulp_id].msix_requested = 0;
bnxt_set_max_func_irqs(bp, bp->total_irqs); bnxt_set_max_func_irqs(bp, bnxt_get_max_func_irqs(bp) + msix_requested);
edev->flags &= ~BNXT_EN_FLAG_MSIX_REQUESTED;
if (netif_running(dev)) {
bnxt_close_nic(bp, true, false);
bnxt_open_nic(bp, true, false);
}
return 0;
}
int bnxt_get_ulp_msix_num(struct bnxt *bp)
{
if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) {
struct bnxt_en_dev *edev = bp->edev;
return edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested;
}
return 0;
}
int bnxt_get_ulp_msix_base(struct bnxt *bp)
{
if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) {
struct bnxt_en_dev *edev = bp->edev;
if (edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested)
return edev->ulp_tbl[BNXT_ROCE_ULP].msix_base;
}
return 0; return 0;
} }
...@@ -287,6 +355,58 @@ void bnxt_ulp_shutdown(struct bnxt *bp) ...@@ -287,6 +355,58 @@ void bnxt_ulp_shutdown(struct bnxt *bp)
} }
} }
void bnxt_ulp_irq_stop(struct bnxt *bp)
{
struct bnxt_en_dev *edev = bp->edev;
struct bnxt_ulp_ops *ops;
if (!edev || !(edev->flags & BNXT_EN_FLAG_MSIX_REQUESTED))
return;
if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) {
struct bnxt_ulp *ulp = &edev->ulp_tbl[BNXT_ROCE_ULP];
if (!ulp->msix_requested)
return;
ops = rtnl_dereference(ulp->ulp_ops);
if (!ops || !ops->ulp_irq_stop)
return;
ops->ulp_irq_stop(ulp->handle);
}
}
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))
return;
if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) {
struct bnxt_ulp *ulp = &edev->ulp_tbl[BNXT_ROCE_ULP];
struct bnxt_msix_entry *ent = NULL;
if (!ulp->msix_requested)
return;
ops = rtnl_dereference(ulp->ulp_ops);
if (!ops || !ops->ulp_irq_restart)
return;
if (!err) {
ent = kcalloc(ulp->msix_requested, sizeof(*ent),
GFP_KERNEL);
if (!ent)
return;
bnxt_fill_msix_vecs(bp, ent);
}
ops->ulp_irq_restart(ulp->handle, ent);
kfree(ent);
}
}
void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl) void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl)
{ {
u16 event_id = le16_to_cpu(cmpl->event_id); u16 event_id = le16_to_cpu(cmpl->event_id);
......
/* Broadcom NetXtreme-C/E network driver. /* Broadcom NetXtreme-C/E network driver.
* *
* Copyright (c) 2016 Broadcom Limited * Copyright (c) 2016-2018 Broadcom Limited
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -20,6 +20,12 @@ ...@@ -20,6 +20,12 @@
struct hwrm_async_event_cmpl; struct hwrm_async_event_cmpl;
struct bnxt; struct bnxt;
struct bnxt_msix_entry {
u32 vector;
u32 ring_idx;
u32 db_offset;
};
struct bnxt_ulp_ops { struct bnxt_ulp_ops {
/* async_notifier() cannot sleep (in BH context) */ /* async_notifier() cannot sleep (in BH context) */
void (*ulp_async_notifier)(void *, struct hwrm_async_event_cmpl *); void (*ulp_async_notifier)(void *, struct hwrm_async_event_cmpl *);
...@@ -27,12 +33,8 @@ struct bnxt_ulp_ops { ...@@ -27,12 +33,8 @@ struct bnxt_ulp_ops {
void (*ulp_start)(void *); void (*ulp_start)(void *);
void (*ulp_sriov_config)(void *, int); void (*ulp_sriov_config)(void *, int);
void (*ulp_shutdown)(void *); void (*ulp_shutdown)(void *);
}; void (*ulp_irq_stop)(void *);
void (*ulp_irq_restart)(void *, struct bnxt_msix_entry *);
struct bnxt_msix_entry {
u32 vector;
u32 ring_idx;
u32 db_offset;
}; };
struct bnxt_fw_msg { struct bnxt_fw_msg {
...@@ -49,6 +51,7 @@ struct bnxt_ulp { ...@@ -49,6 +51,7 @@ struct bnxt_ulp {
unsigned long *async_events_bmap; unsigned long *async_events_bmap;
u16 max_async_event_id; u16 max_async_event_id;
u16 msix_requested; u16 msix_requested;
u16 msix_base;
atomic_t ref_count; atomic_t ref_count;
}; };
...@@ -60,6 +63,7 @@ struct bnxt_en_dev { ...@@ -60,6 +63,7 @@ struct bnxt_en_dev {
#define BNXT_EN_FLAG_ROCEV2_CAP 0x2 #define BNXT_EN_FLAG_ROCEV2_CAP 0x2
#define BNXT_EN_FLAG_ROCE_CAP (BNXT_EN_FLAG_ROCEV1_CAP | \ #define BNXT_EN_FLAG_ROCE_CAP (BNXT_EN_FLAG_ROCEV1_CAP | \
BNXT_EN_FLAG_ROCEV2_CAP) BNXT_EN_FLAG_ROCEV2_CAP)
#define BNXT_EN_FLAG_MSIX_REQUESTED 0x4
const struct bnxt_en_ops *en_ops; const struct bnxt_en_ops *en_ops;
struct bnxt_ulp ulp_tbl[BNXT_MAX_ULP]; struct bnxt_ulp ulp_tbl[BNXT_MAX_ULP];
}; };
...@@ -84,11 +88,15 @@ static inline bool bnxt_ulp_registered(struct bnxt_en_dev *edev, int ulp_id) ...@@ -84,11 +88,15 @@ static inline bool bnxt_ulp_registered(struct bnxt_en_dev *edev, int ulp_id)
return false; return false;
} }
int bnxt_get_ulp_msix_num(struct bnxt *bp);
int bnxt_get_ulp_msix_base(struct bnxt *bp);
void bnxt_subtract_ulp_resources(struct bnxt *bp, int ulp_id); void bnxt_subtract_ulp_resources(struct bnxt *bp, int ulp_id);
void bnxt_ulp_stop(struct bnxt *bp); void bnxt_ulp_stop(struct bnxt *bp);
void bnxt_ulp_start(struct bnxt *bp); void bnxt_ulp_start(struct bnxt *bp);
void bnxt_ulp_sriov_cfg(struct bnxt *bp, int num_vfs); void bnxt_ulp_sriov_cfg(struct bnxt *bp, int num_vfs);
void bnxt_ulp_shutdown(struct bnxt *bp); void bnxt_ulp_shutdown(struct bnxt *bp);
void bnxt_ulp_irq_stop(struct bnxt *bp);
void bnxt_ulp_irq_restart(struct bnxt *bp, int err);
void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl); void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl);
struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev); struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment