i40evf: support packet split receive
Support packet split receive on VFs. This is off by default but can be enabled using ethtool private flags. Because we need to trigger a reset from outside of i40evf_main.c, create a new function to do so, and export it. Also update copyright year in file headers. Change-ID: I721aa5d70113d3d6d94102e5f31526f6fc57cbbb Signed-off-by: Mitch Williams <mitch.a.williams@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
cb5c260e33
commit
00e5ec4bcc
@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
|
* Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
|
||||||
* Copyright(c) 2013 - 2014 Intel Corporation.
|
* Copyright(c) 2013 - 2016 Intel Corporation.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@ -274,6 +274,9 @@ struct i40evf_adapter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Ethtool Private Flags */
|
||||||
|
#define I40EVF_PRIV_FLAGS_PS BIT(0)
|
||||||
|
|
||||||
/* needed by i40evf_ethtool.c */
|
/* needed by i40evf_ethtool.c */
|
||||||
extern char i40evf_driver_name[];
|
extern char i40evf_driver_name[];
|
||||||
extern const char i40evf_driver_version[];
|
extern const char i40evf_driver_version[];
|
||||||
@ -281,6 +284,7 @@ extern const char i40evf_driver_version[];
|
|||||||
int i40evf_up(struct i40evf_adapter *adapter);
|
int i40evf_up(struct i40evf_adapter *adapter);
|
||||||
void i40evf_down(struct i40evf_adapter *adapter);
|
void i40evf_down(struct i40evf_adapter *adapter);
|
||||||
int i40evf_process_config(struct i40evf_adapter *adapter);
|
int i40evf_process_config(struct i40evf_adapter *adapter);
|
||||||
|
void i40evf_schedule_reset(struct i40evf_adapter *adapter);
|
||||||
void i40evf_reset(struct i40evf_adapter *adapter);
|
void i40evf_reset(struct i40evf_adapter *adapter);
|
||||||
void i40evf_set_ethtool_ops(struct net_device *netdev);
|
void i40evf_set_ethtool_ops(struct net_device *netdev);
|
||||||
void i40evf_update_stats(struct i40evf_adapter *adapter);
|
void i40evf_update_stats(struct i40evf_adapter *adapter);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
|
* Intel Ethernet Controller XL710 Family Linux Virtual Function Driver
|
||||||
* Copyright(c) 2013 - 2015 Intel Corporation.
|
* Copyright(c) 2013 - 2016 Intel Corporation.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@ -63,6 +63,12 @@ static const struct i40evf_stats i40evf_gstrings_stats[] = {
|
|||||||
#define I40EVF_STATS_LEN(_dev) \
|
#define I40EVF_STATS_LEN(_dev) \
|
||||||
(I40EVF_GLOBAL_STATS_LEN + I40EVF_QUEUE_STATS_LEN(_dev))
|
(I40EVF_GLOBAL_STATS_LEN + I40EVF_QUEUE_STATS_LEN(_dev))
|
||||||
|
|
||||||
|
static const char i40evf_priv_flags_strings[][ETH_GSTRING_LEN] = {
|
||||||
|
"packet-split",
|
||||||
|
};
|
||||||
|
|
||||||
|
#define I40EVF_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40evf_priv_flags_strings)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i40evf_get_settings - Get Link Speed and Duplex settings
|
* i40evf_get_settings - Get Link Speed and Duplex settings
|
||||||
* @netdev: network interface device structure
|
* @netdev: network interface device structure
|
||||||
@ -97,6 +103,8 @@ static int i40evf_get_sset_count(struct net_device *netdev, int sset)
|
|||||||
{
|
{
|
||||||
if (sset == ETH_SS_STATS)
|
if (sset == ETH_SS_STATS)
|
||||||
return I40EVF_STATS_LEN(netdev);
|
return I40EVF_STATS_LEN(netdev);
|
||||||
|
else if (sset == ETH_SS_PRIV_FLAGS)
|
||||||
|
return I40EVF_PRIV_FLAGS_STR_LEN;
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -162,6 +170,12 @@ static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
|
|||||||
snprintf(p, ETH_GSTRING_LEN, "rx-%u.bytes", i);
|
snprintf(p, ETH_GSTRING_LEN, "rx-%u.bytes", i);
|
||||||
p += ETH_GSTRING_LEN;
|
p += ETH_GSTRING_LEN;
|
||||||
}
|
}
|
||||||
|
} else if (sset == ETH_SS_PRIV_FLAGS) {
|
||||||
|
for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
|
||||||
|
memcpy(data, i40evf_priv_flags_strings[i],
|
||||||
|
ETH_GSTRING_LEN);
|
||||||
|
data += ETH_GSTRING_LEN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +225,7 @@ static void i40evf_get_drvinfo(struct net_device *netdev,
|
|||||||
strlcpy(drvinfo->version, i40evf_driver_version, 32);
|
strlcpy(drvinfo->version, i40evf_driver_version, 32);
|
||||||
strlcpy(drvinfo->fw_version, "N/A", 4);
|
strlcpy(drvinfo->fw_version, "N/A", 4);
|
||||||
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
|
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
|
||||||
|
drvinfo->n_priv_flags = I40EVF_PRIV_FLAGS_STR_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -710,6 +725,54 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
|
|||||||
I40EVF_HLUT_ARRAY_SIZE);
|
I40EVF_HLUT_ARRAY_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i40evf_get_priv_flags - report device private flags
|
||||||
|
* @dev: network interface device structure
|
||||||
|
*
|
||||||
|
* The get string set count and the string set should be matched for each
|
||||||
|
* flag returned. Add new strings for each flag to the i40e_priv_flags_strings
|
||||||
|
* array.
|
||||||
|
*
|
||||||
|
* Returns a u32 bitmap of flags.
|
||||||
|
**/
|
||||||
|
static u32 i40evf_get_priv_flags(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct i40evf_adapter *adapter = netdev_priv(dev);
|
||||||
|
u32 ret_flags = 0;
|
||||||
|
|
||||||
|
ret_flags |= adapter->flags & I40EVF_FLAG_RX_PS_ENABLED ?
|
||||||
|
I40EVF_PRIV_FLAGS_PS : 0;
|
||||||
|
|
||||||
|
return ret_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i40evf_set_priv_flags - set private flags
|
||||||
|
* @dev: network interface device structure
|
||||||
|
* @flags: bit flags to be set
|
||||||
|
**/
|
||||||
|
static int i40evf_set_priv_flags(struct net_device *dev, u32 flags)
|
||||||
|
{
|
||||||
|
struct i40evf_adapter *adapter = netdev_priv(dev);
|
||||||
|
bool reset_required = false;
|
||||||
|
|
||||||
|
if ((flags & I40EVF_PRIV_FLAGS_PS) &&
|
||||||
|
!(adapter->flags & I40EVF_FLAG_RX_PS_ENABLED)) {
|
||||||
|
adapter->flags |= I40EVF_FLAG_RX_PS_ENABLED;
|
||||||
|
reset_required = true;
|
||||||
|
} else if (!(flags & I40EVF_PRIV_FLAGS_PS) &&
|
||||||
|
(adapter->flags & I40EVF_FLAG_RX_PS_ENABLED)) {
|
||||||
|
adapter->flags &= ~I40EVF_FLAG_RX_PS_ENABLED;
|
||||||
|
reset_required = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if needed, issue reset to cause things to take effect */
|
||||||
|
if (reset_required)
|
||||||
|
i40evf_schedule_reset(adapter);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct ethtool_ops i40evf_ethtool_ops = {
|
static const struct ethtool_ops i40evf_ethtool_ops = {
|
||||||
.get_settings = i40evf_get_settings,
|
.get_settings = i40evf_get_settings,
|
||||||
.get_drvinfo = i40evf_get_drvinfo,
|
.get_drvinfo = i40evf_get_drvinfo,
|
||||||
@ -719,6 +782,8 @@ static const struct ethtool_ops i40evf_ethtool_ops = {
|
|||||||
.get_strings = i40evf_get_strings,
|
.get_strings = i40evf_get_strings,
|
||||||
.get_ethtool_stats = i40evf_get_ethtool_stats,
|
.get_ethtool_stats = i40evf_get_ethtool_stats,
|
||||||
.get_sset_count = i40evf_get_sset_count,
|
.get_sset_count = i40evf_get_sset_count,
|
||||||
|
.get_priv_flags = i40evf_get_priv_flags,
|
||||||
|
.set_priv_flags = i40evf_set_priv_flags,
|
||||||
.get_msglevel = i40evf_get_msglevel,
|
.get_msglevel = i40evf_get_msglevel,
|
||||||
.set_msglevel = i40evf_set_msglevel,
|
.set_msglevel = i40evf_set_msglevel,
|
||||||
.get_coalesce = i40evf_get_coalesce,
|
.get_coalesce = i40evf_get_coalesce,
|
||||||
|
@ -172,6 +172,19 @@ void i40evf_debug_d(void *hw, u32 mask, char *fmt_str, ...)
|
|||||||
pr_info("%s", buf);
|
pr_info("%s", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i40evf_schedule_reset - Set the flags and schedule a reset event
|
||||||
|
* @adapter: board private structure
|
||||||
|
**/
|
||||||
|
void i40evf_schedule_reset(struct i40evf_adapter *adapter)
|
||||||
|
{
|
||||||
|
if (!(adapter->flags &
|
||||||
|
(I40EVF_FLAG_RESET_PENDING | I40EVF_FLAG_RESET_NEEDED))) {
|
||||||
|
adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
|
||||||
|
schedule_work(&adapter->reset_task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i40evf_tx_timeout - Respond to a Tx Hang
|
* i40evf_tx_timeout - Respond to a Tx Hang
|
||||||
* @netdev: network interface device structure
|
* @netdev: network interface device structure
|
||||||
@ -181,11 +194,7 @@ static void i40evf_tx_timeout(struct net_device *netdev)
|
|||||||
struct i40evf_adapter *adapter = netdev_priv(netdev);
|
struct i40evf_adapter *adapter = netdev_priv(netdev);
|
||||||
|
|
||||||
adapter->tx_timeout_count++;
|
adapter->tx_timeout_count++;
|
||||||
if (!(adapter->flags & (I40EVF_FLAG_RESET_PENDING |
|
i40evf_schedule_reset(adapter);
|
||||||
I40EVF_FLAG_RESET_NEEDED))) {
|
|
||||||
adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
|
|
||||||
queue_work(i40evf_wq, &adapter->reset_task);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -638,35 +647,22 @@ static void i40evf_configure_rx(struct i40evf_adapter *adapter)
|
|||||||
int rx_buf_len;
|
int rx_buf_len;
|
||||||
|
|
||||||
|
|
||||||
adapter->flags &= ~I40EVF_FLAG_RX_PS_CAPABLE;
|
|
||||||
adapter->flags |= I40EVF_FLAG_RX_1BUF_CAPABLE;
|
|
||||||
|
|
||||||
/* Decide whether to use packet split mode or not */
|
|
||||||
if (netdev->mtu > ETH_DATA_LEN) {
|
|
||||||
if (adapter->flags & I40EVF_FLAG_RX_PS_CAPABLE)
|
|
||||||
adapter->flags |= I40EVF_FLAG_RX_PS_ENABLED;
|
|
||||||
else
|
|
||||||
adapter->flags &= ~I40EVF_FLAG_RX_PS_ENABLED;
|
|
||||||
} else {
|
|
||||||
if (adapter->flags & I40EVF_FLAG_RX_1BUF_CAPABLE)
|
|
||||||
adapter->flags &= ~I40EVF_FLAG_RX_PS_ENABLED;
|
|
||||||
else
|
|
||||||
adapter->flags |= I40EVF_FLAG_RX_PS_ENABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the RX buffer length according to the mode */
|
/* Set the RX buffer length according to the mode */
|
||||||
if (adapter->flags & I40EVF_FLAG_RX_PS_ENABLED) {
|
if (adapter->flags & I40EVF_FLAG_RX_PS_ENABLED ||
|
||||||
rx_buf_len = I40E_RX_HDR_SIZE;
|
netdev->mtu <= ETH_DATA_LEN)
|
||||||
} else {
|
|
||||||
if (netdev->mtu <= ETH_DATA_LEN)
|
|
||||||
rx_buf_len = I40EVF_RXBUFFER_2048;
|
rx_buf_len = I40EVF_RXBUFFER_2048;
|
||||||
else
|
else
|
||||||
rx_buf_len = ALIGN(max_frame, 1024);
|
rx_buf_len = ALIGN(max_frame, 1024);
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < adapter->num_active_queues; i++) {
|
for (i = 0; i < adapter->num_active_queues; i++) {
|
||||||
adapter->rx_rings[i].tail = hw->hw_addr + I40E_QRX_TAIL1(i);
|
adapter->rx_rings[i].tail = hw->hw_addr + I40E_QRX_TAIL1(i);
|
||||||
adapter->rx_rings[i].rx_buf_len = rx_buf_len;
|
adapter->rx_rings[i].rx_buf_len = rx_buf_len;
|
||||||
|
if (adapter->flags & I40EVF_FLAG_RX_PS_ENABLED) {
|
||||||
|
set_ring_ps_enabled(&adapter->rx_rings[i]);
|
||||||
|
adapter->rx_rings[i].rx_hdr_len = I40E_RX_HDR_SIZE;
|
||||||
|
} else {
|
||||||
|
clear_ring_ps_enabled(&adapter->rx_rings[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1003,7 +999,12 @@ static void i40evf_configure(struct i40evf_adapter *adapter)
|
|||||||
for (i = 0; i < adapter->num_active_queues; i++) {
|
for (i = 0; i < adapter->num_active_queues; i++) {
|
||||||
struct i40e_ring *ring = &adapter->rx_rings[i];
|
struct i40e_ring *ring = &adapter->rx_rings[i];
|
||||||
|
|
||||||
|
if (adapter->flags & I40EVF_FLAG_RX_PS_ENABLED) {
|
||||||
|
i40evf_alloc_rx_headers(ring);
|
||||||
|
i40evf_alloc_rx_buffers_ps(ring, ring->count);
|
||||||
|
} else {
|
||||||
i40evf_alloc_rx_buffers_1buf(ring, ring->count);
|
i40evf_alloc_rx_buffers_1buf(ring, ring->count);
|
||||||
|
}
|
||||||
ring->next_to_use = ring->count - 1;
|
ring->next_to_use = ring->count - 1;
|
||||||
writel(ring->next_to_use, ring->tail);
|
writel(ring->next_to_use, ring->tail);
|
||||||
}
|
}
|
||||||
@ -2481,6 +2482,11 @@ static void i40evf_init_task(struct work_struct *work)
|
|||||||
adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
|
adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
|
||||||
|
|
||||||
adapter->flags |= I40EVF_FLAG_RX_CSUM_ENABLED;
|
adapter->flags |= I40EVF_FLAG_RX_CSUM_ENABLED;
|
||||||
|
adapter->flags |= I40EVF_FLAG_RX_1BUF_CAPABLE;
|
||||||
|
adapter->flags |= I40EVF_FLAG_RX_PS_CAPABLE;
|
||||||
|
|
||||||
|
/* Default to single buffer rx, can be changed through ethtool. */
|
||||||
|
adapter->flags &= ~I40EVF_FLAG_RX_PS_ENABLED;
|
||||||
|
|
||||||
netdev->netdev_ops = &i40evf_netdev_ops;
|
netdev->netdev_ops = &i40evf_netdev_ops;
|
||||||
i40evf_set_ethtool_ops(netdev);
|
i40evf_set_ethtool_ops(netdev);
|
||||||
|
@ -270,6 +270,10 @@ void i40evf_configure_queues(struct i40evf_adapter *adapter)
|
|||||||
vqpi->rxq.max_pkt_size = adapter->netdev->mtu
|
vqpi->rxq.max_pkt_size = adapter->netdev->mtu
|
||||||
+ ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
|
+ ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
|
||||||
vqpi->rxq.databuffer_size = adapter->rx_rings[i].rx_buf_len;
|
vqpi->rxq.databuffer_size = adapter->rx_rings[i].rx_buf_len;
|
||||||
|
if (adapter->flags & I40EVF_FLAG_RX_PS_ENABLED) {
|
||||||
|
vqpi->rxq.splithdr_enabled = true;
|
||||||
|
vqpi->rxq.hdr_size = I40E_RX_HDR_SIZE;
|
||||||
|
}
|
||||||
vqpi++;
|
vqpi++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user