Commit 117ce394 authored by David S. Miller's avatar David S. Miller

Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2015-12-01

This series contains updates to i40e and i40evf only.

Helin adds new fields to i40e_vsi to store user configured RSS config data
and the code to use it.  Also renamed RSS items to clarify functionality
and scope to users.  Fixed a confusing kernel message of enabling RSS size
by reporting it together with the hardware maximum RSS size.

Anjali fixes the issue of forcing writeback too often causing us to not
benefit from NAPI.

Jesse adds a prefetch for data early in the transmit path to help immensely
for pktgen and forwarding workloads.  Fixed the i40e driver that was
possibly sleeping inside critical section of code.

Carolyn fixes an issue where adminq init failures always provided a message
that NVM was newer than expected, when this is not always the case for
init_adminq failures.  Fixed by adding a check for that specific error
condition and a different helpful message otherwise.

Mitch fixes error message by telling the user which VF is being naughty,
rather than making them guess.  Updated the queue_vector array from a
statically-sized member of the adapter structure, to a dynamically-allocated
and -sized array.  This reduces the size of the adapter structure and allows
us to support any number of queue vectors in the future without changing the
code.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6cc56834 17652c63
...@@ -266,7 +266,7 @@ struct i40e_pf { ...@@ -266,7 +266,7 @@ struct i40e_pf {
u16 num_lan_qps; /* num lan queues this PF has set up */ u16 num_lan_qps; /* num lan queues this PF has set up */
u16 num_lan_msix; /* num queue vectors for the base PF vsi */ u16 num_lan_msix; /* num queue vectors for the base PF vsi */
int queues_left; /* queues left unclaimed */ int queues_left; /* queues left unclaimed */
u16 rss_size; /* num queues in the RSS array */ u16 alloc_rss_size; /* allocated RSS queues */
u16 rss_size_max; /* HW defined max RSS queues */ u16 rss_size_max; /* HW defined max RSS queues */
u16 fdir_pf_filter_count; /* num of guaranteed filters for this PF */ u16 fdir_pf_filter_count; /* num of guaranteed filters for this PF */
u16 num_alloc_vsi; /* num VSIs this driver supports */ u16 num_alloc_vsi; /* num VSIs this driver supports */
...@@ -413,7 +413,7 @@ struct i40e_pf { ...@@ -413,7 +413,7 @@ struct i40e_pf {
u32 rx_hwtstamp_cleared; u32 rx_hwtstamp_cleared;
bool ptp_tx; bool ptp_tx;
bool ptp_rx; bool ptp_rx;
u16 rss_table_size; u16 rss_table_size; /* HW RSS table size */
/* These are only valid in NPAR modes */ /* These are only valid in NPAR modes */
u32 npar_max_bw; u32 npar_max_bw;
u32 npar_min_bw; u32 npar_min_bw;
...@@ -506,8 +506,10 @@ struct i40e_vsi { ...@@ -506,8 +506,10 @@ struct i40e_vsi {
u16 tx_itr_setting; u16 tx_itr_setting;
u16 int_rate_limit; /* value in usecs */ u16 int_rate_limit; /* value in usecs */
u16 rss_table_size; u16 rss_table_size; /* HW RSS table size */
u16 rss_size; u16 rss_size; /* Allocated RSS queues */
u8 *rss_hkey_user; /* User configured hash keys */
u8 *rss_lut_user; /* User configured lookup table entries */
u16 max_frame; u16 max_frame;
u16 rx_hdr_len; u16 rx_hdr_len;
...@@ -695,7 +697,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, ...@@ -695,7 +697,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
bool is_vf, bool is_netdev); bool is_vf, bool is_netdev);
void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan, void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan,
bool is_vf, bool is_netdev); bool is_vf, bool is_netdev);
int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl); int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
u16 uplink, u32 param1); u16 uplink, u32 param1);
int i40e_vsi_release(struct i40e_vsi *vsi); int i40e_vsi_release(struct i40e_vsi *vsi);
......
...@@ -1138,7 +1138,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, ...@@ -1138,7 +1138,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
spin_lock_bh(&vsi->mac_filter_list_lock); spin_lock_bh(&vsi->mac_filter_list_lock);
f = i40e_add_filter(vsi, ma, vlan, false, false); f = i40e_add_filter(vsi, ma, vlan, false, false);
spin_unlock_bh(&vsi->mac_filter_list_lock); spin_unlock_bh(&vsi->mac_filter_list_lock);
ret = i40e_sync_vsi_filters(vsi, true); ret = i40e_sync_vsi_filters(vsi);
if (f && !ret) if (f && !ret)
dev_info(&pf->pdev->dev, dev_info(&pf->pdev->dev,
"add macaddr: %pM vlan=%d added to VSI %d\n", "add macaddr: %pM vlan=%d added to VSI %d\n",
...@@ -1177,7 +1177,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, ...@@ -1177,7 +1177,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
spin_lock_bh(&vsi->mac_filter_list_lock); spin_lock_bh(&vsi->mac_filter_list_lock);
i40e_del_filter(vsi, ma, vlan, false, false); i40e_del_filter(vsi, ma, vlan, false, false);
spin_unlock_bh(&vsi->mac_filter_list_lock); spin_unlock_bh(&vsi->mac_filter_list_lock);
ret = i40e_sync_vsi_filters(vsi, true); ret = i40e_sync_vsi_filters(vsi);
if (!ret) if (!ret)
dev_info(&pf->pdev->dev, dev_info(&pf->pdev->dev,
"del macaddr: %pM vlan=%d removed from VSI %d\n", "del macaddr: %pM vlan=%d removed from VSI %d\n",
......
...@@ -2651,10 +2651,8 @@ static int i40e_set_rxfh(struct net_device *netdev, const u32 *indir, ...@@ -2651,10 +2651,8 @@ static int i40e_set_rxfh(struct net_device *netdev, const u32 *indir,
{ {
struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi; struct i40e_vsi *vsi = np->vsi;
u8 seed_def[I40E_HKEY_ARRAY_SIZE]; u8 *seed = NULL;
u8 *lut, *seed = NULL;
u16 i; u16 i;
int ret;
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -2663,18 +2661,27 @@ static int i40e_set_rxfh(struct net_device *netdev, const u32 *indir, ...@@ -2663,18 +2661,27 @@ static int i40e_set_rxfh(struct net_device *netdev, const u32 *indir,
return 0; return 0;
if (key) { if (key) {
memcpy(seed_def, key, I40E_HKEY_ARRAY_SIZE); if (!vsi->rss_hkey_user) {
seed = seed_def; vsi->rss_hkey_user = kzalloc(I40E_HKEY_ARRAY_SIZE,
GFP_KERNEL);
if (!vsi->rss_hkey_user)
return -ENOMEM;
}
memcpy(vsi->rss_hkey_user, key, I40E_HKEY_ARRAY_SIZE);
seed = vsi->rss_hkey_user;
} }
lut = kzalloc(I40E_HLUT_ARRAY_SIZE, GFP_KERNEL); if (!vsi->rss_lut_user) {
if (!lut) vsi->rss_lut_user = kzalloc(I40E_HLUT_ARRAY_SIZE, GFP_KERNEL);
return -ENOMEM; if (!vsi->rss_lut_user)
return -ENOMEM;
}
/* Each 32 bits pointed by 'indir' is stored with a lut entry */
for (i = 0; i < I40E_HLUT_ARRAY_SIZE; i++) for (i = 0; i < I40E_HLUT_ARRAY_SIZE; i++)
lut[i] = (u8)(indir[i]); vsi->rss_lut_user[i] = (u8)(indir[i]);
ret = i40e_config_rss(vsi, seed, lut, I40E_HLUT_ARRAY_SIZE);
kfree(lut);
return ret; return i40e_config_rss(vsi, seed, vsi->rss_lut_user,
I40E_HLUT_ARRAY_SIZE);
} }
/** /**
......
This diff is collapsed.
...@@ -2806,6 +2806,9 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, ...@@ -2806,6 +2806,9 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
int tsyn; int tsyn;
int tso; int tso;
/* prefetch the data, we'll need it later */
prefetch(skb->data);
if (0 == i40e_xmit_descriptor_count(skb, tx_ring)) if (0 == i40e_xmit_descriptor_count(skb, tx_ring))
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
......
...@@ -565,7 +565,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) ...@@ -565,7 +565,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
} }
/* program mac filter */ /* program mac filter */
ret = i40e_sync_vsi_filters(vsi, false); ret = i40e_sync_vsi_filters(vsi);
if (ret) if (ret)
dev_err(&pf->pdev->dev, "Unable to program ucast filters\n"); dev_err(&pf->pdev->dev, "Unable to program ucast filters\n");
...@@ -1094,8 +1094,8 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode, ...@@ -1094,8 +1094,8 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
/* single place to detect unsuccessful return values */ /* single place to detect unsuccessful return values */
if (v_retval) { if (v_retval) {
vf->num_invalid_msgs++; vf->num_invalid_msgs++;
dev_err(&pf->pdev->dev, "Failed opcode %d Error: %d\n", dev_err(&pf->pdev->dev, "VF %d failed opcode %d, error: %d\n",
v_opcode, v_retval); vf->vf_id, v_opcode, v_retval);
if (vf->num_invalid_msgs > if (vf->num_invalid_msgs >
I40E_DEFAULT_NUM_INVALID_MSGS_ALLOWED) { I40E_DEFAULT_NUM_INVALID_MSGS_ALLOWED) {
dev_err(&pf->pdev->dev, dev_err(&pf->pdev->dev,
...@@ -1633,7 +1633,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) ...@@ -1633,7 +1633,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
spin_unlock_bh(&vsi->mac_filter_list_lock); spin_unlock_bh(&vsi->mac_filter_list_lock);
/* program the updated filter list */ /* program the updated filter list */
if (i40e_sync_vsi_filters(vsi, false)) if (i40e_sync_vsi_filters(vsi))
dev_err(&pf->pdev->dev, "Unable to program VF %d MAC filters\n", dev_err(&pf->pdev->dev, "Unable to program VF %d MAC filters\n",
vf->vf_id); vf->vf_id);
...@@ -1687,7 +1687,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) ...@@ -1687,7 +1687,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
spin_unlock_bh(&vsi->mac_filter_list_lock); spin_unlock_bh(&vsi->mac_filter_list_lock);
/* program the updated filter list */ /* program the updated filter list */
if (i40e_sync_vsi_filters(vsi, false)) if (i40e_sync_vsi_filters(vsi))
dev_err(&pf->pdev->dev, "Unable to program VF %d MAC filters\n", dev_err(&pf->pdev->dev, "Unable to program VF %d MAC filters\n",
vf->vf_id); vf->vf_id);
...@@ -2102,7 +2102,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) ...@@ -2102,7 +2102,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf_id); dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf_id);
/* program mac filter */ /* program mac filter */
if (i40e_sync_vsi_filters(vsi, false)) { if (i40e_sync_vsi_filters(vsi)) {
dev_err(&pf->pdev->dev, "Unable to program ucast filters\n"); dev_err(&pf->pdev->dev, "Unable to program ucast filters\n");
ret = -EIO; ret = -EIO;
goto error_param; goto error_param;
......
...@@ -245,16 +245,6 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) ...@@ -245,16 +245,6 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
tx_ring->q_vector->tx.total_bytes += total_bytes; tx_ring->q_vector->tx.total_bytes += total_bytes;
tx_ring->q_vector->tx.total_packets += total_packets; tx_ring->q_vector->tx.total_packets += total_packets;
/* check to see if there are any non-cache aligned descriptors
* waiting to be written back, and kick the hardware to force
* them to be written back in case of napi polling
*/
if (budget &&
!((i & WB_STRIDE) == WB_STRIDE) &&
!test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&
(I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
tx_ring->arm_wb = true;
netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev,
tx_ring->queue_index), tx_ring->queue_index),
total_packets, total_bytes); total_packets, total_bytes);
...@@ -1770,6 +1760,9 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -1770,6 +1760,9 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
u32 td_tag = 0; u32 td_tag = 0;
dma_addr_t dma; dma_addr_t dma;
u16 gso_segs; u16 gso_segs;
u16 desc_count = 0;
bool tail_bump = true;
bool do_rs = false;
if (tx_flags & I40E_TX_FLAGS_HW_VLAN) { if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
td_cmd |= I40E_TX_DESC_CMD_IL2TAG1; td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
...@@ -1810,6 +1803,8 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -1810,6 +1803,8 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_desc++; tx_desc++;
i++; i++;
desc_count++;
if (i == tx_ring->count) { if (i == tx_ring->count) {
tx_desc = I40E_TX_DESC(tx_ring, 0); tx_desc = I40E_TX_DESC(tx_ring, 0);
i = 0; i = 0;
...@@ -1829,6 +1824,8 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -1829,6 +1824,8 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_desc++; tx_desc++;
i++; i++;
desc_count++;
if (i == tx_ring->count) { if (i == tx_ring->count) {
tx_desc = I40E_TX_DESC(tx_ring, 0); tx_desc = I40E_TX_DESC(tx_ring, 0);
i = 0; i = 0;
...@@ -1843,35 +1840,7 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -1843,35 +1840,7 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_bi = &tx_ring->tx_bi[i]; tx_bi = &tx_ring->tx_bi[i];
} }
/* Place RS bit on last descriptor of any packet that spans across the
* 4th descriptor (WB_STRIDE aka 0x3) in a 64B cacheline.
*/
#define WB_STRIDE 0x3 #define WB_STRIDE 0x3
if (((i & WB_STRIDE) != WB_STRIDE) &&
(first <= &tx_ring->tx_bi[i]) &&
(first >= &tx_ring->tx_bi[i & ~WB_STRIDE])) {
tx_desc->cmd_type_offset_bsz =
build_ctob(td_cmd, td_offset, size, td_tag) |
cpu_to_le64((u64)I40E_TX_DESC_CMD_EOP <<
I40E_TXD_QW1_CMD_SHIFT);
} else {
tx_desc->cmd_type_offset_bsz =
build_ctob(td_cmd, td_offset, size, td_tag) |
cpu_to_le64((u64)I40E_TXD_CMD <<
I40E_TXD_QW1_CMD_SHIFT);
}
netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev,
tx_ring->queue_index),
first->bytecount);
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
* such as IA-64).
*/
wmb();
/* set next_to_watch value indicating a packet is present */ /* set next_to_watch value indicating a packet is present */
first->next_to_watch = tx_desc; first->next_to_watch = tx_desc;
...@@ -1881,15 +1850,78 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, ...@@ -1881,15 +1850,78 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_ring->next_to_use = i; tx_ring->next_to_use = i;
netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev,
tx_ring->queue_index),
first->bytecount);
i40evf_maybe_stop_tx(tx_ring, DESC_NEEDED); i40evf_maybe_stop_tx(tx_ring, DESC_NEEDED);
/* Algorithm to optimize tail and RS bit setting:
* if xmit_more is supported
* if xmit_more is true
* do not update tail and do not mark RS bit.
* if xmit_more is false and last xmit_more was false
* if every packet spanned less than 4 desc
* then set RS bit on 4th packet and update tail
* on every packet
* else
* update tail and set RS bit on every packet.
* if xmit_more is false and last_xmit_more was true
* update tail and set RS bit.
* else (kernel < 3.18)
* if every packet spanned less than 4 desc
* then set RS bit on 4th packet and update tail
* on every packet
* else
* set RS bit on EOP for every packet and update tail
*
* Optimization: wmb to be issued only in case of tail update.
* Also optimize the Descriptor WB path for RS bit with the same
* algorithm.
*
* Note: If there are less than 4 packets
* pending and interrupts were disabled the service task will
* trigger a force WB.
*/
if (skb->xmit_more &&
!netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
tx_ring->queue_index))) {
tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
tail_bump = false;
} else if (!skb->xmit_more &&
!netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
tx_ring->queue_index)) &&
(!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) &&
(tx_ring->packet_stride < WB_STRIDE) &&
(desc_count < WB_STRIDE)) {
tx_ring->packet_stride++;
} else {
tx_ring->packet_stride = 0;
tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
do_rs = true;
}
if (do_rs)
tx_ring->packet_stride = 0;
tx_desc->cmd_type_offset_bsz =
build_ctob(td_cmd, td_offset, size, td_tag) |
cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD :
I40E_TX_DESC_CMD_EOP) <<
I40E_TXD_QW1_CMD_SHIFT);
/* notify HW of packet */ /* notify HW of packet */
if (!skb->xmit_more || if (!tail_bump)
netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
tx_ring->queue_index)))
writel(i, tx_ring->tail);
else
prefetchw(tx_desc + 1); prefetchw(tx_desc + 1);
if (tail_bump) {
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
* such as IA-64).
*/
wmb();
writel(i, tx_ring->tail);
}
return; return;
dma_error: dma_error:
...@@ -1961,6 +1993,9 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, ...@@ -1961,6 +1993,9 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
u8 hdr_len = 0; u8 hdr_len = 0;
int tso; int tso;
/* prefetch the data, we'll need it later */
prefetch(skb->data);
if (0 == i40evf_xmit_descriptor_count(skb, tx_ring)) if (0 == i40evf_xmit_descriptor_count(skb, tx_ring))
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
...@@ -2028,7 +2063,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, ...@@ -2028,7 +2063,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
netdev_tx_t i40evf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) netdev_tx_t i40evf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{ {
struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_ring *tx_ring = adapter->tx_rings[skb->queue_mapping]; struct i40e_ring *tx_ring = &adapter->tx_rings[skb->queue_mapping];
/* hardware can't handle really short frames, hardware padding works /* hardware can't handle really short frames, hardware padding works
* beyond this point * beyond this point
......
...@@ -268,6 +268,8 @@ struct i40e_ring { ...@@ -268,6 +268,8 @@ struct i40e_ring {
bool ring_active; /* is ring online or not */ bool ring_active; /* is ring online or not */
bool arm_wb; /* do something to arm write back */ bool arm_wb; /* do something to arm write back */
u8 packet_stride;
#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)
u16 flags; u16 flags;
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0) #define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
......
...@@ -67,6 +67,8 @@ struct i40e_vsi { ...@@ -67,6 +67,8 @@ struct i40e_vsi {
u16 rx_itr_setting; u16 rx_itr_setting;
u16 tx_itr_setting; u16 tx_itr_setting;
u16 qs_handle; u16 qs_handle;
u8 *rss_hkey_user; /* User configured hash keys */
u8 *rss_lut_user; /* User configured lookup table entries */
}; };
/* How many Rx Buffers do we bundle into one write to the hardware ? */ /* How many Rx Buffers do we bundle into one write to the hardware ? */
...@@ -99,6 +101,7 @@ struct i40e_vsi { ...@@ -99,6 +101,7 @@ struct i40e_vsi {
#define MAX_TX_QUEUES MAX_RX_QUEUES #define MAX_TX_QUEUES MAX_RX_QUEUES
#define I40EVF_HKEY_ARRAY_SIZE ((I40E_VFQF_HKEY_MAX_INDEX + 1) * 4) #define I40EVF_HKEY_ARRAY_SIZE ((I40E_VFQF_HKEY_MAX_INDEX + 1) * 4)
#define I40EVF_HLUT_ARRAY_SIZE ((I40E_VFQF_HLUT_MAX_INDEX + 1) * 4)
/* MAX_MSIX_Q_VECTORS of these are allocated, /* MAX_MSIX_Q_VECTORS of these are allocated,
* but we only use one per queue-specific vector. * but we only use one per queue-specific vector.
...@@ -142,9 +145,6 @@ struct i40e_q_vector { ...@@ -142,9 +145,6 @@ struct i40e_q_vector {
#define OTHER_VECTOR 1 #define OTHER_VECTOR 1
#define NONQ_VECS (OTHER_VECTOR) #define NONQ_VECS (OTHER_VECTOR)
#define MAX_MSIX_Q_VECTORS 4
#define MAX_MSIX_COUNT 5
#define MIN_MSIX_Q_VECTORS 1 #define MIN_MSIX_Q_VECTORS 1
#define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NONQ_VECS) #define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NONQ_VECS)
...@@ -190,19 +190,19 @@ struct i40evf_adapter { ...@@ -190,19 +190,19 @@ struct i40evf_adapter {
struct work_struct reset_task; struct work_struct reset_task;
struct work_struct adminq_task; struct work_struct adminq_task;
struct delayed_work init_task; struct delayed_work init_task;
struct i40e_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; struct i40e_q_vector *q_vectors;
struct list_head vlan_filter_list; struct list_head vlan_filter_list;
char misc_vector_name[IFNAMSIZ + 9]; char misc_vector_name[IFNAMSIZ + 9];
int num_active_queues; int num_active_queues;
/* TX */ /* TX */
struct i40e_ring *tx_rings[I40E_MAX_VSI_QP]; struct i40e_ring *tx_rings;
u32 tx_timeout_count; u32 tx_timeout_count;
struct list_head mac_filter_list; struct list_head mac_filter_list;
u32 tx_desc_count; u32 tx_desc_count;
/* RX */ /* RX */
struct i40e_ring *rx_rings[I40E_MAX_VSI_QP]; struct i40e_ring *rx_rings;
u64 hw_csum_rx_error; u64 hw_csum_rx_error;
u32 rx_desc_count; u32 rx_desc_count;
int num_msix_vectors; int num_msix_vectors;
...@@ -313,4 +313,8 @@ void i40evf_request_reset(struct i40evf_adapter *adapter); ...@@ -313,4 +313,8 @@ void i40evf_request_reset(struct i40evf_adapter *adapter);
void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
enum i40e_virtchnl_ops v_opcode, enum i40e_virtchnl_ops v_opcode,
i40e_status v_retval, u8 *msg, u16 msglen); i40e_status v_retval, u8 *msg, u16 msglen);
int i40evf_config_rss(struct i40e_vsi *vsi, const u8 *seed, u8 *lut,
u16 lut_size);
int i40evf_get_rss(struct i40e_vsi *vsi, const u8 *seed, u8 *lut,
u16 lut_size);
#endif /* _I40EVF_H_ */ #endif /* _I40EVF_H_ */
...@@ -121,12 +121,12 @@ static void i40evf_get_ethtool_stats(struct net_device *netdev, ...@@ -121,12 +121,12 @@ static void i40evf_get_ethtool_stats(struct net_device *netdev,
data[i] = *(u64 *)p; data[i] = *(u64 *)p;
} }
for (j = 0; j < adapter->num_active_queues; j++) { for (j = 0; j < adapter->num_active_queues; j++) {
data[i++] = adapter->tx_rings[j]->stats.packets; data[i++] = adapter->tx_rings[j].stats.packets;
data[i++] = adapter->tx_rings[j]->stats.bytes; data[i++] = adapter->tx_rings[j].stats.bytes;
} }
for (j = 0; j < adapter->num_active_queues; j++) { for (j = 0; j < adapter->num_active_queues; j++) {
data[i++] = adapter->rx_rings[j]->stats.packets; data[i++] = adapter->rx_rings[j].stats.packets;
data[i++] = adapter->rx_rings[j]->stats.bytes; data[i++] = adapter->rx_rings[j].stats.bytes;
} }
} }
...@@ -351,7 +351,7 @@ static int i40evf_set_coalesce(struct net_device *netdev, ...@@ -351,7 +351,7 @@ static int i40evf_set_coalesce(struct net_device *netdev,
vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC; vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC;
for (i = 0; i < adapter->num_msix_vectors - NONQ_VECS; i++) { for (i = 0; i < adapter->num_msix_vectors - NONQ_VECS; i++) {
q_vector = adapter->q_vector[i]; q_vector = &adapter->q_vectors[i];
q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting); q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
wr32(hw, I40E_VFINT_ITRN1(0, i), q_vector->rx.itr); wr32(hw, I40E_VFINT_ITRN1(0, i), q_vector->rx.itr);
q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting); q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting);
...@@ -634,25 +634,34 @@ static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, ...@@ -634,25 +634,34 @@ static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
u8 *hfunc) u8 *hfunc)
{ {
struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_hw *hw = &adapter->hw; struct i40e_vsi *vsi = &adapter->vsi;
u32 hlut_val; u8 *seed = NULL, *lut;
int i, j; int ret;
u16 i;
if (hfunc) if (hfunc)
*hfunc = ETH_RSS_HASH_TOP; *hfunc = ETH_RSS_HASH_TOP;
if (!indir) if (!indir)
return 0; return 0;
if (indir) { seed = key;
for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) {
hlut_val = rd32(hw, I40E_VFQF_HLUT(i)); lut = kzalloc(I40EVF_HLUT_ARRAY_SIZE, GFP_KERNEL);
indir[j++] = hlut_val & 0xff; if (!lut)
indir[j++] = (hlut_val >> 8) & 0xff; return -ENOMEM;
indir[j++] = (hlut_val >> 16) & 0xff;
indir[j++] = (hlut_val >> 24) & 0xff; ret = i40evf_get_rss(vsi, seed, lut, I40EVF_HLUT_ARRAY_SIZE);
} if (ret)
} goto out;
return 0;
/* Each 32 bits pointed by 'indir' is stored with a lut entry */
for (i = 0; i < I40EVF_HLUT_ARRAY_SIZE; i++)
indir[i] = (u32)lut[i];
out:
kfree(lut);
return ret;
} }
/** /**
...@@ -668,9 +677,9 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir, ...@@ -668,9 +677,9 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
const u8 *key, const u8 hfunc) const u8 *key, const u8 hfunc)
{ {
struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_hw *hw = &adapter->hw; struct i40e_vsi *vsi = &adapter->vsi;
u32 hlut_val; u8 *seed = NULL;
int i, j; u16 i;
/* We do not allow change in unsupported parameters */ /* We do not allow change in unsupported parameters */
if (key || if (key ||
...@@ -679,15 +688,29 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir, ...@@ -679,15 +688,29 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
if (!indir) if (!indir)
return 0; return 0;
for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) { if (key) {
hlut_val = indir[j++]; if (!vsi->rss_hkey_user) {
hlut_val |= indir[j++] << 8; vsi->rss_hkey_user = kzalloc(I40EVF_HKEY_ARRAY_SIZE,
hlut_val |= indir[j++] << 16; GFP_KERNEL);
hlut_val |= indir[j++] << 24; if (!vsi->rss_hkey_user)
wr32(hw, I40E_VFQF_HLUT(i), hlut_val); return -ENOMEM;
}
memcpy(vsi->rss_hkey_user, key, I40EVF_HKEY_ARRAY_SIZE);
seed = vsi->rss_hkey_user;
}
if (!vsi->rss_lut_user) {
vsi->rss_lut_user = kzalloc(I40EVF_HLUT_ARRAY_SIZE,
GFP_KERNEL);
if (!vsi->rss_lut_user)
return -ENOMEM;
} }
return 0; /* Each 32 bits pointed by 'indir' is stored with a lut entry */
for (i = 0; i < I40EVF_HLUT_ARRAY_SIZE; i++)
vsi->rss_lut_user[i] = (u8)(indir[i]);
return i40evf_config_rss(vsi, seed, vsi->rss_lut_user,
I40EVF_HLUT_ARRAY_SIZE);
} }
static const struct ethtool_ops i40evf_ethtool_ops = { static const struct ethtool_ops i40evf_ethtool_ops = {
......
...@@ -255,19 +255,19 @@ void i40evf_configure_queues(struct i40evf_adapter *adapter) ...@@ -255,19 +255,19 @@ void i40evf_configure_queues(struct i40evf_adapter *adapter)
for (i = 0; i < pairs; i++) { for (i = 0; i < pairs; i++) {
vqpi->txq.vsi_id = vqci->vsi_id; vqpi->txq.vsi_id = vqci->vsi_id;
vqpi->txq.queue_id = i; vqpi->txq.queue_id = i;
vqpi->txq.ring_len = adapter->tx_rings[i]->count; vqpi->txq.ring_len = adapter->tx_rings[i].count;
vqpi->txq.dma_ring_addr = adapter->tx_rings[i]->dma; vqpi->txq.dma_ring_addr = adapter->tx_rings[i].dma;
vqpi->txq.headwb_enabled = 1; vqpi->txq.headwb_enabled = 1;
vqpi->txq.dma_headwb_addr = vqpi->txq.dma_ring_addr + vqpi->txq.dma_headwb_addr = vqpi->txq.dma_ring_addr +
(vqpi->txq.ring_len * sizeof(struct i40e_tx_desc)); (vqpi->txq.ring_len * sizeof(struct i40e_tx_desc));
vqpi->rxq.vsi_id = vqci->vsi_id; vqpi->rxq.vsi_id = vqci->vsi_id;
vqpi->rxq.queue_id = i; vqpi->rxq.queue_id = i;
vqpi->rxq.ring_len = adapter->rx_rings[i]->count; vqpi->rxq.ring_len = adapter->rx_rings[i].count;
vqpi->rxq.dma_ring_addr = adapter->rx_rings[i]->dma; vqpi->rxq.dma_ring_addr = adapter->rx_rings[i].dma;
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;
vqpi++; vqpi++;
} }
...@@ -360,7 +360,7 @@ void i40evf_map_queues(struct i40evf_adapter *adapter) ...@@ -360,7 +360,7 @@ void i40evf_map_queues(struct i40evf_adapter *adapter)
vimi->num_vectors = adapter->num_msix_vectors; vimi->num_vectors = adapter->num_msix_vectors;
/* Queue vectors first */ /* Queue vectors first */
for (v_idx = 0; v_idx < q_vectors; v_idx++) { for (v_idx = 0; v_idx < q_vectors; v_idx++) {
q_vector = adapter->q_vector[v_idx]; q_vector = adapter->q_vectors + v_idx;
vimi->vecmap[v_idx].vsi_id = adapter->vsi_res->vsi_id; vimi->vecmap[v_idx].vsi_id = adapter->vsi_res->vsi_id;
vimi->vecmap[v_idx].vector_id = v_idx + NONQ_VECS; vimi->vecmap[v_idx].vector_id = v_idx + NONQ_VECS;
vimi->vecmap[v_idx].txq_map = q_vector->ring_mask; vimi->vecmap[v_idx].txq_map = q_vector->ring_mask;
......
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