Commit cf0e5c44 authored by David S. Miller's avatar David S. Miller

Merge branch 'bnxt_en-next'

Michael Chan says:

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

This series includes firmware interface update, some optimizations,
some new PCI IDs, new MTU checks, ethtool reset method, interrupt coalescing
code cleanup, and TC flower offload for vxlan encap/decap from Sathya
Perla.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e324615b cd66358e
This diff is collapsed.
......@@ -944,6 +944,22 @@ struct bnxt_test_info {
#define BNXT_CAG_REG_LEGACY_INT_STATUS 0x4014
#define BNXT_CAG_REG_BASE 0x300000
struct bnxt_coal {
u16 coal_ticks;
u16 coal_ticks_irq;
u16 coal_bufs;
u16 coal_bufs_irq;
/* RING_IDLE enabled when coal ticks < idle_thresh */
u16 idle_thresh;
u8 bufs_per_record;
u8 budget;
};
struct bnxt_tc_flow_stats {
u64 packets;
u64 bytes;
};
struct bnxt_tc_info {
bool enabled;
......@@ -954,12 +970,29 @@ struct bnxt_tc_info {
/* hash table to store L2 keys of TC flows */
struct rhashtable l2_table;
struct rhashtable_params l2_ht_params;
/* hash table to store L2 keys for TC tunnel decap */
struct rhashtable decap_l2_table;
struct rhashtable_params decap_l2_ht_params;
/* hash table to store tunnel decap entries */
struct rhashtable decap_table;
struct rhashtable_params decap_ht_params;
/* hash table to store tunnel encap entries */
struct rhashtable encap_table;
struct rhashtable_params encap_ht_params;
/* lock to atomically add/del an l2 node when a flow is
* added or deleted.
*/
struct mutex lock;
/* Fields used for batching stats query */
struct rhashtable_iter iter;
#define BNXT_FLOW_STATS_BATCH_MAX 10
struct bnxt_tc_stats_batch {
void *flow_node;
struct bnxt_tc_flow_stats hw_stats;
} stats_batch[BNXT_FLOW_STATS_BATCH_MAX];
/* Stat counter mask (width) */
u64 bytes_mask;
u64 packets_mask;
......@@ -1013,6 +1046,7 @@ struct bnxt {
#define CHIP_NUM_5745X 0xd730
#define CHIP_NUM_58802 0xd802
#define CHIP_NUM_58804 0xd804
#define CHIP_NUM_58808 0xd808
#define BNXT_CHIP_NUM_5730X(chip_num) \
......@@ -1048,6 +1082,7 @@ struct bnxt {
#define BNXT_CHIP_NUM_588XX(chip_num) \
((chip_num) == CHIP_NUM_58802 || \
(chip_num) == CHIP_NUM_58804 || \
(chip_num) == CHIP_NUM_58808)
struct net_device *dev;
......@@ -1170,6 +1205,7 @@ struct bnxt {
int nr_vnics;
u32 rss_hash_cfg;
u16 max_mtu;
u8 max_tc;
u8 max_lltc; /* lossless TCs */
struct bnxt_queue_info q_info[BNXT_MAX_QUEUE];
......@@ -1232,14 +1268,8 @@ struct bnxt {
u8 port_count;
u16 br_mode;
u16 rx_coal_ticks;
u16 rx_coal_ticks_irq;
u16 rx_coal_bufs;
u16 rx_coal_bufs_irq;
u16 tx_coal_ticks;
u16 tx_coal_ticks_irq;
u16 tx_coal_bufs;
u16 tx_coal_bufs_irq;
struct bnxt_coal rx_coal;
struct bnxt_coal tx_coal;
#define BNXT_USEC_TO_COAL_TIMER(x) ((x) * 25 / 2)
......@@ -1265,6 +1295,7 @@ struct bnxt {
#define BNXT_GENEVE_ADD_PORT_SP_EVENT 12
#define BNXT_GENEVE_DEL_PORT_SP_EVENT 13
#define BNXT_LINK_SPEED_CHNG_SP_EVENT 14
#define BNXT_FLOW_STATS_SP_EVENT 15
struct bnxt_pf_info pf;
#ifdef CONFIG_BNXT_SRIOV
......@@ -1315,7 +1346,7 @@ struct bnxt {
enum devlink_eswitch_mode eswitch_mode;
struct bnxt_vf_rep **vf_reps; /* array of vf-rep ptrs */
u16 *cfa_code_map; /* cfa_code -> vf_idx map */
struct bnxt_tc_info tc_info;
struct bnxt_tc_info *tc_info;
};
#define BNXT_RX_STATS_OFFSET(counter) \
......
......@@ -29,7 +29,7 @@ int bnxt_dl_register(struct bnxt *bp)
if (!pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV))
return 0;
if (bp->hwrm_spec_code < 0x10800) {
if (bp->hwrm_spec_code < 0x10803) {
netdev_warn(bp->dev, "Firmware does not support SR-IOV E-Switch SWITCHDEV mode.\n");
return -ENOTSUPP;
}
......
......@@ -26,8 +26,6 @@
#define FLASH_PACKAGE_TIMEOUT ((HWRM_CMD_TIMEOUT) * 200)
#define INSTALL_PACKAGE_TIMEOUT ((HWRM_CMD_TIMEOUT) * 200)
static char *bnxt_get_pkgver(struct net_device *dev, char *buf, size_t buflen);
static u32 bnxt_get_msglevel(struct net_device *dev)
{
struct bnxt *bp = netdev_priv(dev);
......@@ -46,19 +44,24 @@ static int bnxt_get_coalesce(struct net_device *dev,
struct ethtool_coalesce *coal)
{
struct bnxt *bp = netdev_priv(dev);
struct bnxt_coal *hw_coal;
u16 mult;
memset(coal, 0, sizeof(*coal));
coal->rx_coalesce_usecs = bp->rx_coal_ticks;
/* 2 completion records per rx packet */
coal->rx_max_coalesced_frames = bp->rx_coal_bufs / 2;
coal->rx_coalesce_usecs_irq = bp->rx_coal_ticks_irq;
coal->rx_max_coalesced_frames_irq = bp->rx_coal_bufs_irq / 2;
hw_coal = &bp->rx_coal;
mult = hw_coal->bufs_per_record;
coal->rx_coalesce_usecs = hw_coal->coal_ticks;
coal->rx_max_coalesced_frames = hw_coal->coal_bufs / mult;
coal->rx_coalesce_usecs_irq = hw_coal->coal_ticks_irq;
coal->rx_max_coalesced_frames_irq = hw_coal->coal_bufs_irq / mult;
coal->tx_coalesce_usecs = bp->tx_coal_ticks;
coal->tx_max_coalesced_frames = bp->tx_coal_bufs;
coal->tx_coalesce_usecs_irq = bp->tx_coal_ticks_irq;
coal->tx_max_coalesced_frames_irq = bp->tx_coal_bufs_irq;
hw_coal = &bp->tx_coal;
mult = hw_coal->bufs_per_record;
coal->tx_coalesce_usecs = hw_coal->coal_ticks;
coal->tx_max_coalesced_frames = hw_coal->coal_bufs / mult;
coal->tx_coalesce_usecs_irq = hw_coal->coal_ticks_irq;
coal->tx_max_coalesced_frames_irq = hw_coal->coal_bufs_irq / mult;
coal->stats_block_coalesce_usecs = bp->stats_coal_ticks;
......@@ -70,18 +73,23 @@ static int bnxt_set_coalesce(struct net_device *dev,
{
struct bnxt *bp = netdev_priv(dev);
bool update_stats = false;
struct bnxt_coal *hw_coal;
int rc = 0;
bp->rx_coal_ticks = coal->rx_coalesce_usecs;
/* 2 completion records per rx packet */
bp->rx_coal_bufs = coal->rx_max_coalesced_frames * 2;
bp->rx_coal_ticks_irq = coal->rx_coalesce_usecs_irq;
bp->rx_coal_bufs_irq = coal->rx_max_coalesced_frames_irq * 2;
bp->tx_coal_ticks = coal->tx_coalesce_usecs;
bp->tx_coal_bufs = coal->tx_max_coalesced_frames;
bp->tx_coal_ticks_irq = coal->tx_coalesce_usecs_irq;
bp->tx_coal_bufs_irq = coal->tx_max_coalesced_frames_irq;
u16 mult;
hw_coal = &bp->rx_coal;
mult = hw_coal->bufs_per_record;
hw_coal->coal_ticks = coal->rx_coalesce_usecs;
hw_coal->coal_bufs = coal->rx_max_coalesced_frames * mult;
hw_coal->coal_ticks_irq = coal->rx_coalesce_usecs_irq;
hw_coal->coal_bufs_irq = coal->rx_max_coalesced_frames_irq * mult;
hw_coal = &bp->rx_coal;
mult = hw_coal->bufs_per_record;
hw_coal->coal_ticks = coal->tx_coalesce_usecs;
hw_coal->coal_bufs = coal->tx_max_coalesced_frames * mult;
hw_coal->coal_ticks_irq = coal->tx_coalesce_usecs_irq;
hw_coal->coal_bufs_irq = coal->tx_max_coalesced_frames_irq * mult;
if (bp->stats_coal_ticks != coal->stats_block_coalesce_usecs) {
u32 stats_ticks = coal->stats_block_coalesce_usecs;
......@@ -822,20 +830,10 @@ static void bnxt_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
struct bnxt *bp = netdev_priv(dev);
char *pkglog;
char *pkgver = NULL;
pkglog = kmalloc(BNX_PKG_LOG_MAX_LENGTH, GFP_KERNEL);
if (pkglog)
pkgver = bnxt_get_pkgver(dev, pkglog, BNX_PKG_LOG_MAX_LENGTH);
strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
if (pkgver && *pkgver != 0 && isdigit(*pkgver))
snprintf(info->fw_version, sizeof(info->fw_version) - 1,
"%s pkg %s", bp->fw_ver_str, pkgver);
else
strlcpy(info->fw_version, bp->fw_ver_str,
sizeof(info->fw_version));
strlcpy(info->fw_version, bp->fw_ver_str, sizeof(info->fw_version));
strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
info->n_stats = bnxt_get_num_stats(bp);
info->testinfo_len = bp->num_tests;
......@@ -843,7 +841,6 @@ static void bnxt_get_drvinfo(struct net_device *dev,
info->eedump_len = 0;
/* TODO CHIMP FW: reg dump details */
info->regdump_len = 0;
kfree(pkglog);
}
static void bnxt_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
......@@ -1350,7 +1347,6 @@ static int bnxt_firmware_reset(struct net_device *dev,
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FW_RESET, -1, -1);
/* TODO: Support ASAP ChiMP self-reset (e.g. upon PF driver unload) */
/* TODO: Address self-reset of APE/KONG/BONO/TANG or ungraceful reset */
/* (e.g. when firmware isn't already running) */
switch (dir_type) {
......@@ -1376,6 +1372,10 @@ static int bnxt_firmware_reset(struct net_device *dev,
case BNX_DIR_TYPE_BONO_PATCH:
req.embedded_proc_type = FW_RESET_REQ_EMBEDDED_PROC_TYPE_ROCE;
break;
case BNXT_FW_RESET_CHIP:
req.embedded_proc_type = FW_RESET_REQ_EMBEDDED_PROC_TYPE_CHIP;
req.selfrst_status = FW_RESET_REQ_SELFRST_STATUS_SELFRSTASAP;
break;
default:
return -EINVAL;
}
......@@ -1773,6 +1773,9 @@ static int bnxt_get_nvram_item(struct net_device *dev, u32 index, u32 offset,
dma_addr_t dma_handle;
struct hwrm_nvm_read_input req = {0};
if (!length)
return -EINVAL;
buf = dma_alloc_coherent(&bp->pdev->dev, length, &dma_handle,
GFP_KERNEL);
if (!buf) {
......@@ -2495,13 +2498,59 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
}
}
static int bnxt_reset(struct net_device *dev, u32 *flags)
{
struct bnxt *bp = netdev_priv(dev);
int rc = 0;
if (!BNXT_PF(bp)) {
netdev_err(dev, "Reset is not supported from a VF\n");
return -EOPNOTSUPP;
}
if (pci_vfs_assigned(bp->pdev)) {
netdev_err(dev,
"Reset not allowed when VFs are assigned to VMs\n");
return -EBUSY;
}
if (*flags == ETH_RESET_ALL) {
/* This feature is not supported in older firmware versions */
if (bp->hwrm_spec_code < 0x10803)
return -EOPNOTSUPP;
rc = bnxt_firmware_reset(dev, BNXT_FW_RESET_CHIP);
if (!rc)
netdev_info(dev, "Reset request successful. Reload driver to complete reset\n");
} else {
rc = -EINVAL;
}
return rc;
}
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;
struct net_device *dev = bp->dev;
char *pkglog;
int i, rc;
pkglog = kzalloc(BNX_PKG_LOG_MAX_LENGTH, GFP_KERNEL);
if (pkglog) {
char *pkgver;
int len;
pkgver = bnxt_get_pkgver(dev, pkglog, BNX_PKG_LOG_MAX_LENGTH);
if (pkgver && *pkgver != 0 && isdigit(*pkgver)) {
len = strlen(bp->fw_ver_str);
snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
"/pkg %s", pkgver);
}
kfree(pkglog);
}
if (bp->hwrm_spec_code < 0x10704 || !BNXT_SINGLE_PF(bp))
return;
......@@ -2592,4 +2641,5 @@ const struct ethtool_ops bnxt_ethtool_ops = {
.nway_reset = bnxt_nway_reset,
.set_phys_id = bnxt_set_phys_id,
.self_test = bnxt_self_test,
.reset = bnxt_reset,
};
......@@ -34,6 +34,8 @@ struct bnxt_led_cfg {
#define BNXT_LED_DFLT_ENABLES(x) \
cpu_to_le32(BNXT_LED_DFLT_ENA << (BNXT_LED_DFLT_ENA_SHIFT * (x)))
#define BNXT_FW_RESET_CHIP 0xffff
extern const struct ethtool_ops bnxt_ethtool_ops;
u32 _bnxt_fw_to_ethtool_adv_spds(u16, u8);
......
......@@ -12,6 +12,8 @@
#ifdef CONFIG_BNXT_FLOWER_OFFLOAD
#include <net/ip_tunnels.h>
/* Structs used for storing the filter/actions of the TC cmd.
*/
struct bnxt_tc_l2_key {
......@@ -50,6 +52,13 @@ struct bnxt_tc_l4_key {
};
};
struct bnxt_tc_tunnel_key {
struct bnxt_tc_l2_key l2;
struct bnxt_tc_l3_key l3;
struct bnxt_tc_l4_key l4;
__be32 id;
};
struct bnxt_tc_actions {
u32 flags;
#define BNXT_TC_ACTION_FLAG_FWD BIT(0)
......@@ -57,16 +66,16 @@ struct bnxt_tc_actions {
#define BNXT_TC_ACTION_FLAG_PUSH_VLAN BIT(3)
#define BNXT_TC_ACTION_FLAG_POP_VLAN BIT(4)
#define BNXT_TC_ACTION_FLAG_DROP BIT(5)
#define BNXT_TC_ACTION_FLAG_TUNNEL_ENCAP BIT(6)
#define BNXT_TC_ACTION_FLAG_TUNNEL_DECAP BIT(7)
u16 dst_fid;
struct net_device *dst_dev;
__be16 push_vlan_tpid;
__be16 push_vlan_tci;
};
struct bnxt_tc_flow_stats {
u64 packets;
u64 bytes;
/* tunnel encap */
struct ip_tunnel_key tun_encap_key;
};
struct bnxt_tc_flow {
......@@ -76,6 +85,16 @@ struct bnxt_tc_flow {
#define BNXT_TC_FLOW_FLAGS_IPV6_ADDRS BIT(3)
#define BNXT_TC_FLOW_FLAGS_PORTS BIT(4)
#define BNXT_TC_FLOW_FLAGS_ICMP BIT(5)
#define BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS BIT(6)
#define BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS BIT(7)
#define BNXT_TC_FLOW_FLAGS_TUNL_IPV6_ADDRS BIT(8)
#define BNXT_TC_FLOW_FLAGS_TUNL_PORTS BIT(9)
#define BNXT_TC_FLOW_FLAGS_TUNL_ID BIT(10)
#define BNXT_TC_FLOW_FLAGS_TUNNEL (BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS | \
BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS | \
BNXT_TC_FLOW_FLAGS_TUNL_IPV6_ADDRS |\
BNXT_TC_FLOW_FLAGS_TUNL_PORTS |\
BNXT_TC_FLOW_FLAGS_TUNL_ID)
/* flow applicable to pkts ingressing on this fid */
u16 src_fid;
......@@ -85,6 +104,8 @@ struct bnxt_tc_flow {
struct bnxt_tc_l3_key l3_mask;
struct bnxt_tc_l4_key l4_key;
struct bnxt_tc_l4_key l4_mask;
struct ip_tunnel_key tun_key;
struct ip_tunnel_key tun_mask;
struct bnxt_tc_actions actions;
......@@ -93,13 +114,39 @@ struct bnxt_tc_flow {
/* previous snap-shot of stats */
struct bnxt_tc_flow_stats prev_stats;
unsigned long lastused; /* jiffies */
/* for calculating delta from prev_stats and
* updating prev_stats atomically.
*/
spinlock_t stats_lock;
};
/* Tunnel encap/decap hash table
* This table is used to maintain a list of flows that use
* the same tunnel encap/decap params (ip_daddrs, vni, udp_dport)
* and the FW returned handle.
* A separate table is maintained for encap and decap
*/
struct bnxt_tc_tunnel_node {
struct ip_tunnel_key key;
struct rhash_head node;
/* tunnel l2 info */
struct bnxt_tc_l2_key l2_info;
#define INVALID_TUNNEL_HANDLE cpu_to_le32(0xffffffff)
/* tunnel handle returned by FW */
__le32 tunnel_handle;
u32 refcount;
struct rcu_head rcu;
};
/* L2 hash table
* This data-struct is used for L2-flow table.
* The L2 part of a flow is stored in a hash table.
* The same data-struct is used for L2-flow table and L2-tunnel table.
* The L2 part of a flow or tunnel is stored in a hash table.
* A flow that shares the same L2 key/mask with an
* already existing flow must refer to it's flow handle.
* already existing flow/tunnel must refer to it's flow handle or
* decap_filter_id respectively.
*/
struct bnxt_tc_l2_node {
/* hash key: first 16b of key */
......@@ -110,7 +157,7 @@ struct bnxt_tc_l2_node {
/* a linked list of flows that share the same l2 key */
struct list_head common_l2_flows;
/* number of flows sharing the l2 key */
/* number of flows/tunnels sharing the l2 key */
u16 refcount;
struct rcu_head rcu;
......@@ -130,6 +177,16 @@ struct bnxt_tc_flow_node {
/* for the shared_flows list maintained in l2_node */
struct list_head l2_list_node;
/* tunnel encap related */
struct bnxt_tc_tunnel_node *encap_node;
/* tunnel decap related */
struct bnxt_tc_tunnel_node *decap_node;
/* L2 node in tunnel-l2 hashtable that shares flow's tunnel l2 key */
struct bnxt_tc_l2_node *decap_l2_node;
/* for the shared_flows list maintained in tunnel decap l2_node */
struct list_head decap_l2_list_node;
struct rcu_head rcu;
};
......@@ -137,6 +194,12 @@ int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
struct tc_cls_flower_offload *cls_flower);
int bnxt_init_tc(struct bnxt *bp);
void bnxt_shutdown_tc(struct bnxt *bp);
void bnxt_tc_flow_stats_work(struct bnxt *bp);
static inline bool bnxt_tc_flower_enabled(struct bnxt *bp)
{
return bp->tc_info && bp->tc_info->enabled;
}
#else /* CONFIG_BNXT_FLOWER_OFFLOAD */
......@@ -154,5 +217,14 @@ static inline int bnxt_init_tc(struct bnxt *bp)
static inline void bnxt_shutdown_tc(struct bnxt *bp)
{
}
static inline void bnxt_tc_flow_stats_work(struct bnxt *bp)
{
}
static inline bool bnxt_tc_flower_enabled(struct bnxt *bp)
{
return false;
}
#endif /* CONFIG_BNXT_FLOWER_OFFLOAD */
#endif /* BNXT_TC_H */
......@@ -124,6 +124,9 @@ static int bnxt_vf_rep_setup_tc_block_cb(enum tc_setup_type type,
struct bnxt *bp = vf_rep->bp;
int vf_fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;
if (!bnxt_tc_flower_enabled(vf_rep->bp))
return -EOPNOTSUPP;
switch (type) {
case TC_SETUP_CLSFLOWER:
return bnxt_tc_setup_flower(bp, vf_fid, type_data);
......
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