Intel Wired LAN Driver Updates 2014-11-14
Subsystems (4)
This series contains updates to i40e only.
Shannon provides a patch to clean up the driver to only warn once that PTP is not supported when linked at 100Mbps.
Mitch provides a fix for i40e where the VF interrupt processing takes a long time and it is possible that we could lose a VFLR event if it happens while processing a VFLR on another VF. To correct this situation, we enable the VFLR interrupt cause before we begin processing any pending resets.
Serey provides a fix to handle the case where a single packet with more than 8 data descriptors triggers a Malicious Driver Detect event in the device.
Neerav provides several patches to update DCB support in i40e. When there are DCB configuration changes based on DCBx, the firmware suspends the port's Tx and generates an event to the PF. The PF is then responsible to reconfigure the PF VSIs and switching topology as per the updated DCB configuration and then resume the port's Tx by calling the "Resume Port Tx" AQ command, so add this call to the flow that handles DCB re-configuration in the PF. Allow the driver to query and use DCB configuration from firmware when firmware DCBx agent is in CEE mode. Add a check whether LLDP Agent's default AdminStatus is enabled or disabled on a given port, and sets DCBx status to disabled if the status is disabled. Fix an issue when the port TC configuration changes as a result of DCBx and the driver modifies the enabled TCs for the VEBs it manages but does not update the enabled_tc value that was cached on a per VEB basis. Add a new PF state so that if a port's Tx is in suspended state the Tx queue disable flow would just put the request for the queue to be disabled and return without waiting for the queue to be actually disabled. Allows the driver to enable/disable the XPS based on the number of TCs being enabled for the given VSI.
The following are changes since commit a77f9c5dcdf8480a93332792c336fa2bf9d31229:
Revert "fast_hash: avoid indirect function calls"
and are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next master
Catherine Sullivan (1):
i40e: Bump version to 1.1.23
Mitch Williams (1):
i40e: re-enable VFLR interrupt sooner
Neerav Parikh (8):
i40e: Resume Port Tx after DCB event
i40e: Add support to firmware CEE DCBX mode
i40e: Check for LLDP AdminStatus before querying DCBX
i40e: Update VEB's enabled_tc after reconfiguration
i40e: Modify Tx disable wait flow in case of DCB reconfiguration
i40e: Do not disable/enable FCoE VSI with DCB reconfig
i40e: Prevent link flow control settings when PFC is enabled
i40e: Set XPS bit mask to zero in DCB mode
Serey Kong (1):
i40e: Handle a single mss packet with more than 8 frags
Shannon Nelson (1):
i40e: only warn once of PTP nonsupport in 100Mbit speed
drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 45 +++- drivers/net/ethernet/intel/i40e/i40e_common.c | 48 ++++ drivers/net/ethernet/intel/i40e/i40e_dcb.c | 252 ++++++++++++++++++++- drivers/net/ethernet/intel/i40e/i40e_dcb.h | 5 + drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c | 8 +- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 2 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 14 +- drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 170 ++++++++++++-- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 7 + drivers/net/ethernet/intel/i40e/i40e_ptp.c | 12 +- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 14 +- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 + drivers/net/ethernet/intel/i40e/i40e_type.h | 53 +++-- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 12 +- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 14 +- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 1 + 18 files changed, 597 insertions(+), 64 deletions(-)
Signature · 1 line
1.9.3
PATCH 1/12 i40e: only warn once of PTP nonsupport in 100Mbit speed
From: Shannon Nelson <[email protected]>
Only warn once that PTP is not supported when linked at 100Mbit.
Yes, using a static this way means that this once-only message is not port specific, but once only for the life of the driver, regardless of the number of ports. That should be plenty.
--- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_ptp.c +9 -3
@@ -382,11 +382,17 @@ void i40e_ptp_set_increment(struct i40e_pf *pf) incval =I40E_PTP_1GB_INCVAL ;break ;case I40E_LINK_SPEED_100MB : -dev_warn (&pf->pdev->dev, -"%s: 1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n" , - __func__); + { +static int warn_once; + +if (!warn_once) { +dev_warn (&pf->pdev->dev, +"1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n" ); + warn_once++; + } incval =0 ;break ; + }case I40E_LINK_SPEED_40GB :default : incval =I40E_PTP_40GB_INCVAL ;
Signature · 1 line
1.9.3
Re: [net-next 01/12] i40e: only warn once of PTP nonsupport in 100Mbit speed
Quoted 24 lines · Jeff Kirsher
From: Shannon Nelson <[email protected]>
Only warn once that PTP is not supported when linked at 100Mbit.
Yes, using a static this way means that this once-only message is not port specific, but once only for the life of the driver, regardless of the number of ports. That should be plenty.
Change-ID Ie6476530056df408452e195ef06afd4f57caa4b2Signed-off-by Shannon Nelson <[email protected]>Signed-off-by Jeff Kirsher <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)drivers/net/ethernet/intel/i40e/i40e_ptp.c +0
-1@@ -382,11 +382,17 @@ void i40e_ptp_set_increment(struct i40e_pf *pf) incval =I40E_PTP_1GB_INCVAL ;break ;case I40E_LINK_SPEED_100MB : - dev_warn(&pf->pdev->dev,
drivers/net/ethernet/intel/i40e/i40e_ptp.c void i40e_ptp_set_increment(struct i40e_pf *pf) · line 392
Quoted 10 lines
drivers/net/ethernet/intel/i40e/i40e_ptp.c +8
-2-"%s: 1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n" , - __func__); + { +static int warn_once; + +if (!warn_once) { +dev_warn (&pf->pdev->dev, +"1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n" ); + warn_once++; + }
I am sure Joe could come up with dev_warn_once() and others pretty easily. As a temporary change you could use pr_warn_once("%s: ...\n", dev_name(&pf->pdev->dev) which is almost identical?
Quoted 7 lines
drivers/net/ethernet/intel/i40e/i40e_ptp.c +1
-0incval =0 ;break ; + }case I40E_LINK_SPEED_40GB :default : incval =I40E_PTP_40GB_INCVAL ;
PATCH 1/1 device: Add dev_<level>_once variants
Add the equivalents to pr_<level>_once.
--- include/linux/device.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
include/linux/device.h +35 -0
@@ -1118,6 +1118,41 @@ do { \ })#endif +#ifdef CONFIG_PRINTK +#define dev_level_once (dev_level, dev, fmt, ...) \ +do { \ + static bool __print_once __read_mostly; \ + \ + if (!__print_once) { \ + __print_once = true; \ + dev_level(dev, fmt, ##__VA_ARGS__); \ + } \ +} while (0) +#else +#define dev_level_once (dev_level, dev, fmt, ...) \ +do { \ + if (0) \ + dev_level(dev, fmt, ##__VA_ARGS__); \ +} while (0) +#endif + +#define dev_emerg_once (dev, fmt, ...) \ + dev_level_once(dev_emerg, dev, fmt, ##__VA_ARGS__) +#define dev_alert_once (dev, fmt, ...) \ + dev_level_once(dev_alert, dev, fmt, ##__VA_ARGS__) +#define dev_crit_once (dev, fmt, ...) \ + dev_level_once(dev_crit, dev, fmt, ##__VA_ARGS__) +#define dev_err_once (dev, fmt, ...) \ + dev_level_once(dev_err, dev, fmt, ##__VA_ARGS__) +#define dev_warn_once (dev, fmt, ...) \ + dev_level_once(dev_warn, dev, fmt, ##__VA_ARGS__) +#define dev_notice_once (dev, fmt, ...) \ + dev_level_once(dev_notice, dev, fmt, ##__VA_ARGS__) +#define dev_info_once (dev, fmt, ...) \ + dev_level_once(dev_info, dev, fmt, ##__VA_ARGS__) +#define dev_dbg_once (dev, fmt, ...) \ + dev_level_once(dev_info, dev, fmt, ##__VA_ARGS__) +#define dev_level_ratelimited (dev_level, dev, fmt, ...) \ do { \ static DEFINE_RATELIMIT_STATE(_rs, \
David Miller
maintainerRe: [PATCH net-next] device: Add dev_<level>_once variants
From: Joe Perches <[email protected]>
Date: Sat, 15 Nov 2014 14:38:29 -0800
Quoted 4 lines
Add the equivalents to pr_<level>_once.
Suggested-by Florian Fainelli <[email protected]>Signed-off-by Joe Perches <[email protected]>
This probably should go via the device layer core, thanks thus Greg KH.
PATCH 1/1 netdevice: Neaten includes and forward declarations
Use the appropriate #include path for neighbour.h and add device.h which was indirectly #included by dmaengine.h
Remove unnecessary forward declaration of struct device;
Add comments for other forward struct declarations.
--- include/linux/netdevice.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
include/linux/netdevice.h +8 -8
@@ -36,6 +36,7 @@#include <linux/percpu.h> #include <linux/rculist.h> +#include <linux/device.h> #include <linux/dmaengine.h> #include <linux/workqueue.h> #include <linux/dynamic_queue_limits.h>
@@ -49,16 +50,15 @@#include <net/netprio_cgroup.h> #include <linux/netdev_features.h> -#include <linux/neighbour.h> + +#include <uapi/linux/neighbour.h> #include <uapi/linux/netdevice.h> -struct netpoll_info ; -struct device ; -struct phy_device ; -/* 802.11 specific */ -struct wireless_dev ; -/* 802.15.4 specific */ -struct wpan_dev ; +/* forward struct type declarations */ +struct netpoll_info ;/* for net_device_ops */ +struct phy_device ;/* for net_device */ +struct wireless_dev ;/* for net_device: 802.11 specific */ +struct wpan_dev ;/* for net_device: 802.15.4 specific */ void netdev_set_default_ethtool_ops (struct net_device *dev,const struct ethtool_ops *ops);
David Miller
maintainerRe: [PATCH net-next] netdevice: Neaten includes and forward declarations
From: Joe Perches <[email protected]>
Date: Sun, 16 Nov 2014 14:21:31 -0800
Quoted 8 lines
Use the appropriate #include path for
neighbour.hand adddevice.hwhich was indirectly #included bydmaengine.hRemove unnecessary forward declaration of struct device;
Add comments for other forward struct declarations.
Signed-off-by Joe Perches <[email protected]>
This no longer applies to net-next, please respin.
Thanks.
Re: [PATCH net-next] netdevice: Neaten includes and forward declarations
Quoted 8 lines · David Miller
From: Joe Perches <[email protected]>
Date: Sun, 16 Nov 2014 14:21:31 -0800Quoted 5 lines
Use the appropriate #include path for
neighbour.hand adddevice.hwhich was indirectly #included bydmaengine.hRemove unnecessary forward declaration of struct device;
Quoted 7 lines
Quoted 3 lines
Add comments for other forward struct declarations.
Signed-off-by Joe Perches <[email protected]>This no longer applies to net-next, please respin.
Thanks.
I did this against -next.
There, commit 98a18b6ffc79b
("netdevice: add ieee802154_ptr to net_device")
adds a forward reference to struct wpan_dev
So, I can do this against net-next, but it'll
just collide with that commit.
It's not at all urgent so perhaps it'd be better
to wait until the next cycle.
David Miller
maintainerRe: [PATCH net-next] netdevice: Neaten includes and forward declarations
From: Joe Perches <[email protected]>
Date: Tue, 18 Nov 2014 13:09:38 -0800
Quoted 2 lines
It's not at all urgent so perhaps it'd be better
to wait until the next cycle.
Yeah, let's just wait.
PATCH 1/1 i40e: Reduce stack in i40e_dbg_dump_desc
In reply to Florian FainelliReduce stack use by using kmemdup and not using a very large struct on stack.
In function ‘i40e_dbg_dump_desc’:
warning: the frame size of 8192 bytes is larger than 2048 bytes [-Wframe-larger-than=]
--- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 30 +++++++++++++++----------- 1 file changed, 17 insertions(+), 13 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_debugfs.c +17 -13
@@ -773,7 +773,7 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n, {struct i40e_tx_desc *txd;union i40e_rx_desc *rxd; -struct i40e_ring ring; +struct i40e_ring *ring;struct i40e_vsi *vsi;int i;
@@ -792,29 +792,32 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n, vsi_seid);return ; } -if (is_rx_ring) - ring = *vsi->rx_rings[ring_id]; -else - ring = *vsi->tx_rings[ring_id]; + + ring =kmemdup (is_rx_ring + ? vsi->rx_rings[ring_id] : vsi->tx_rings[ring_id], +sizeof (*ring),GFP_KERNEL ); +if (!ring) +return ; +if (cnt ==2 ) {dev_info (&pf->pdev->dev,"vsi = %02i %s ring = %02i\n" , vsi_seid, is_rx_ring ?"rx" :"tx" , ring_id); -for (i =0 ; i < ring.count; i++) { +for (i =0 ; i < ring->count; i++) {if (!is_rx_ring) { - txd =I40E_TX_DESC (&ring, i); + txd =I40E_TX_DESC (ring, i);dev_info (&pf->pdev->dev," d[%03i] = 0x%016llx 0x%016llx\n" , i, txd->buffer_addr, txd->cmd_type_offset_bsz); }else if (sizeof (union i40e_rx_desc ) ==sizeof (union i40e_16byte_rx_desc )) { - rxd =I40E_RX_DESC (&ring, i); + rxd =I40E_RX_DESC (ring, i);dev_info (&pf->pdev->dev," d[%03i] = 0x%016llx 0x%016llx\n" , i, rxd->read.pkt_addr, rxd->read.hdr_addr); }else { - rxd =I40E_RX_DESC (&ring, i); + rxd =I40E_RX_DESC (ring, i); dev_info(&pf->pdev->dev, " d[%03i] = 0x%016llx 0x%016llx 0x%016llx 0x%016llx\n", i, rxd->read.pkt_addr,
@@ -823,26 +826,26 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n, } } }else if (cnt ==3 ) { -if (desc_n >= ring.count || desc_n <0 ) { +if (desc_n >= ring->count || desc_n <0 ) {dev_info (&pf->pdev->dev,"descriptor %d not found\n" , desc_n);return ; }if (!is_rx_ring) { - txd =I40E_TX_DESC (&ring, desc_n); + txd =I40E_TX_DESC (ring, desc_n);dev_info (&pf->pdev->dev,"vsi = %02i tx ring = %02i d[%03i] = 0x%016llx 0x%016llx\n" , vsi_seid, ring_id, desc_n, txd->buffer_addr, txd->cmd_type_offset_bsz); }else if (sizeof (union i40e_rx_desc ) ==sizeof (union i40e_16byte_rx_desc )) { - rxd =I40E_RX_DESC (&ring, desc_n); + rxd =I40E_RX_DESC (ring, desc_n);dev_info (&pf->pdev->dev,"vsi = %02i rx ring = %02i d[%03i] = 0x%016llx 0x%016llx\n" , vsi_seid, ring_id, desc_n, rxd->read.pkt_addr, rxd->read.hdr_addr); }else { - rxd =I40E_RX_DESC (&ring, desc_n); + rxd =I40E_RX_DESC (ring, desc_n); dev_info(&pf->pdev->dev, "vsi = %02i rx ring = %02i d[%03i] = 0x%016llx 0x%016llx 0x%016llx 0x%016llx\n", vsi_seid, ring_id, desc_n,
@@ -852,6 +855,7 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n, }else {dev_info (&pf->pdev->dev,"dump desc rx/tx <vsi_seid> <ring_id> [<desc_n>]\n" ); } +kfree (ring); }/**
David Miller
maintainerRe: [PATCH net-next] i40e: Reduce stack in i40e_dbg_dump_desc
From: Joe Perches <[email protected]>
Date: Sun, 16 Nov 2014 14:12:48 -0800
Quoted 7 lines
Reduce stack use by using kmemdup and not using a very large struct on stack.
In function ‘i40e_dbg_dump_desc’:
warning: the frame size of 8192 bytes is larger than 2048 bytes [-Wframe-larger-than=]Signed-off-by Joe Perches <[email protected]>
I'll let Jeff pick this one up, thanks.
Re: [PATCH net-next] i40e: Reduce stack in i40e_dbg_dump_desc
Quoted 6 lines · David Miller
From: Joe Perches <[email protected]>
Date: Sun, 16 Nov 2014 14:12:48 -0800Quoted 3 lines
Reduce stack use by using kmemdup and not using a very large struct on stack.
Quoted 6 lines
Quoted 4 lines
In function ‘i40e_dbg_dump_desc’:
warning: the frame size of 8192 bytes is larger than 2048 bytes [-Wframe-larger-than=]Signed-off-by Joe Perches <[email protected]>I'll let Jeff pick this one up, thanks.
Consider it picked up. Sorry, trying to catch up on all the email/patches the went out this weekend.
PATCH 1/1 device: Add dev_<level>_once variants
In reply to Florian FainelliAdd the equivalents to pr_<level>_once.
--- include/linux/device.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
include/linux/device.h +35 -0
@@ -1118,6 +1118,41 @@ do { \ })#endif +#ifdef CONFIG_PRINTK +#define dev_level_once (dev_level, dev, fmt, ...) \ +do { \ + static bool __print_once __read_mostly; \ + \ + if (!__print_once) { \ + __print_once = true; \ + dev_level(dev, fmt, ##__VA_ARGS__); \ + } \ +} while (0) +#else +#define dev_level_once (dev_level, dev, fmt, ...) \ +do { \ + if (0) \ + dev_level(dev, fmt, ##__VA_ARGS__); \ +} while (0) +#endif + +#define dev_emerg_once (dev, fmt, ...) \ + dev_level_once(dev_emerg, dev, fmt, ##__VA_ARGS__) +#define dev_alert_once (dev, fmt, ...) \ + dev_level_once(dev_alert, dev, fmt, ##__VA_ARGS__) +#define dev_crit_once (dev, fmt, ...) \ + dev_level_once(dev_crit, dev, fmt, ##__VA_ARGS__) +#define dev_err_once (dev, fmt, ...) \ + dev_level_once(dev_err, dev, fmt, ##__VA_ARGS__) +#define dev_warn_once (dev, fmt, ...) \ + dev_level_once(dev_warn, dev, fmt, ##__VA_ARGS__) +#define dev_notice_once (dev, fmt, ...) \ + dev_level_once(dev_notice, dev, fmt, ##__VA_ARGS__) +#define dev_info_once (dev, fmt, ...) \ + dev_level_once(dev_info, dev, fmt, ##__VA_ARGS__) +#define dev_dbg_once (dev, fmt, ...) \ + dev_level_once(dev_info, dev, fmt, ##__VA_ARGS__) +#define dev_level_ratelimited (dev_level, dev, fmt, ...) \ do { \ static DEFINE_RATELIMIT_STATE(_rs, \
Re: [PATCH (sent originally to netdev)] device: Add dev_<level>_once variants
Quoted 4 lines · Joe Perches
Add the equivalents to pr_<level>_once.
Suggested-by Florian Fainelli <[email protected]>Signed-off-by Joe Perches <[email protected]>
Quoted 3 lines
--- include/linux/device.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
PATCH 2/12 i40e: re-enable VFLR interrupt sooner
In reply to Jeff KirsherFrom: Mitch Williams <[email protected]>
VF interrupt processing takes a looooong time, and it's possible that we could lose a VFLR event if it happens while we're processing a VFLR on another VF. This would leave the VF in a semi-permanent reset state, which would not be cleared until yet another VF experiences a VFLR.
To correct this situation, we enable the VFLR interrupt cause before we begin processing any pending resets. This means that any VFLR that occurs during reset processing will generate another interrupt and this routine will get called again.
This change may cause a spurious interrupt when multiple VFLRs occur very close together in time. If this happens, then this routine will be called again and it will detect no outstanding VFLR events and do nothing. No harm, no foul.
--- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +6 -6
@@ -1869,6 +1869,12 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf)if (!test_bit (__I40E_VFLR_EVENT_PENDING, &pf->state))return 0 ; +/* re-enable vflr interrupt cause */ + reg =rd32 (hw,I40E_PFINT_ICR0_ENA ); + reg |=I40E_PFINT_ICR0_ENA_VFLR_MASK ; +wr32 (hw,I40E_PFINT_ICR0_ENA , reg); +i40e_flush (hw); +clear_bit (__I40E_VFLR_EVENT_PENDING, &pf->state);for (vf_id =0 ; vf_id < pf->num_alloc_vfs; vf_id++) { reg_idx = (hw->func_caps.vf_base_id + vf_id) /32 ;
@@ -1885,12 +1891,6 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf) } } -/* re-enable vflr interrupt cause */ - reg =rd32 (hw,I40E_PFINT_ICR0_ENA ); - reg |=I40E_PFINT_ICR0_ENA_VFLR_MASK ; -wr32 (hw,I40E_PFINT_ICR0_ENA , reg); -i40e_flush (hw); -return 0 ; }
Signature · 1 line
1.9.3
PATCH 3/12 i40e: Handle a single mss packet with more than 8 frags
In reply to Jeff KirsherFrom: Serey Kong <[email protected]>
This handles the case where a single packet with more than 8 data descriptors triggers a Malicious Driver Detect event in the device.
--- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 14 ++++++++++---- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 14 ++++++++++---- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 1 + 4 files changed, 22 insertions(+), 8 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_txrx.c +10 -4
@@ -2113,12 +2113,12 @@ static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, const u8 hdr_len, u32 td_cmd, u32 td_offset) #endif { - unsigned int data_len = skb->data_len; - unsigned int size = skb_headlen(skb); struct skb_frag_struct *frag; struct i40e_tx_buffer *tx_bi; struct i40e_tx_desc *tx_desc; u16 i = tx_ring->next_to_use; + unsigned int data_len; + unsigned int size; u32 td_tag = 0; dma_addr_t dma; u16 gso_segs;
@@ -2129,10 +2129,16 @@ static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,I40E_TX_FLAGS_VLAN_SHIFT ; } -if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) +if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) { gso_segs =skb_shinfo (skb)->gso_segs; -else + }else { gso_segs =1 ; +if (skb_shinfo (skb)->nr_frags >=I40E_MAX_BUFFER_TXD ) +skb_linearize (skb); + } + + data_len = skb->data_len; + size =skb_headlen (skb);/* multiply data chunks by size of headers */ first->bytecount = skb->len - hdr_len + (gso_segs * hdr_len);
drivers/net/ethernet/intel/i40e/i40e_txrx.h +1 -0
@@ -112,6 +112,7 @@ enum i40e_dyn_idx_t {#define i40e_rx_desc i40e_32byte_rx_desc +#define I40E_MAX_BUFFER_TXD 8#define I40E_MIN_TX_LEN 17#define I40E_MAX_DATA_PER_TXD 8192
drivers/net/ethernet/intel/i40evf/i40e_txrx.c +10 -4
@@ -1358,12 +1358,12 @@ static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, struct i40e_tx_buffer *first, u32 tx_flags, const u8 hdr_len, u32 td_cmd, u32 td_offset) { - unsigned int data_len = skb->data_len; -unsigned int size =skb_headlen (skb); struct skb_frag_struct *frag;struct i40e_tx_buffer *tx_bi;struct i40e_tx_desc *tx_desc;u16 i = tx_ring->next_to_use; +unsigned int data_len; +unsigned int size;u32 td_tag =0 ;dma_addr_t dma;u16 gso_segs;
@@ -1374,10 +1374,16 @@ static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,I40E_TX_FLAGS_VLAN_SHIFT ; } -if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) +if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) { gso_segs =skb_shinfo (skb)->gso_segs; -else + }else { gso_segs =1 ; +if (skb_shinfo (skb)->nr_frags >=I40E_MAX_BUFFER_TXD ) +skb_linearize (skb); + } + + data_len = skb->data_len; + size =skb_headlen (skb);/* multiply data chunks by size of headers */ first->bytecount = skb->len - hdr_len + (gso_segs * hdr_len);
drivers/net/ethernet/intel/i40evf/i40e_txrx.h +1 -0
@@ -112,6 +112,7 @@ enum i40e_dyn_idx_t {#define i40e_rx_desc i40e_32byte_rx_desc +#define I40E_MAX_BUFFER_TXD 8#define I40E_MIN_TX_LEN 17#define I40E_MAX_DATA_PER_TXD 8192
Signature · 1 line
1.9.3
Re: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
Quoted 38 lines · Jeff Kirsher
From: Serey Kong <[email protected]>
This handles the case where a single packet with more than 8 data descriptors triggers a Malicious Driver Detect event in the device.
Change-ID I2bfd657fd036bed616863e121f6aa86a35d2194cSigned-off-by Serey Kong <[email protected]>Signed-off-by Shannon Nelson <[email protected]>Tested-by Jim Young <[email protected]>Signed-off-by Jeff Kirsher <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 14 ++++++++++---- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 14 ++++++++++---- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 1 + 4 files changed, 22 insertions(+), 8 deletions(-)drivers/net/ethernet/intel/i40e/i40e_txrx.c +2
-2@@ -2113,12 +2113,12 @@ static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, const u8 hdr_len, u32 td_cmd, u32 td_offset) #endif { - unsigned int data_len = skb->data_len; - unsigned int size = skb_headlen(skb); struct skb_frag_struct *frag; struct i40e_tx_buffer *tx_bi; struct i40e_tx_desc *tx_desc; u16 i = tx_ring->next_to_use; + unsigned int data_len; + unsigned int size; u32 td_tag = 0; dma_addr_t dma; u16 gso_segs;@@ -2129,10 +2129,16 @@ static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,I40E_TX_FLAGS_VLAN_SHIFT ;
drivers/net/ethernet/intel/i40e/i40e_txrx.c static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, · line 2137
Quoted 10 lines
drivers/net/ethernet/intel/i40e/i40e_txrx.c +4
-2} -if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) +if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) { gso_segs =skb_shinfo (skb)->gso_segs; -else + }else { gso_segs =1 ; +if (skb_shinfo (skb)->nr_frags >=I40E_MAX_BUFFER_TXD ) +skb_linearize (skb);
What exactly happens if skb_linearize() fails ?
Is this "Malicious Driver Detect event" fatal or simply packet is dropped without additional harm ?
RE: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
From: Eric Dumazet
Quoted 2 lines
Quoted 2 lines
This handles the case where a single packet with more than 8 data descriptors triggers a Malicious Driver Detect event in the device.
Whose bright idea was that?
Quoted 4 lines
Quoted 4 lines
drivers/net/ethernet/intel/i40e/i40e_txrx.c +0
-0@@ -2129,10 +2129,16 @@ static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,I40E_TX_FLAGS_VLAN_SHIFT ; }
Quoted 10 lines
drivers/net/ethernet/intel/i40e/i40e_txrx.c static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, · line 2137
Quoted 8 lines
drivers/net/ethernet/intel/i40e/i40e_txrx.c +4
-2-if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) +if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) { gso_segs =skb_shinfo (skb)->gso_segs; -else + }else { gso_segs =1 ; +if (skb_shinfo (skb)->nr_frags >=I40E_MAX_BUFFER_TXD ) +skb_linearize (skb);What exactly happens if
skb_linearize()fails ?
Didn't someone write a function that significantly reduces the number of fragments without actually requiring a single linear block?
David
Re: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
Quoted 2 lines · David Laight
Didn't someone write a function that significantly reduces the number of fragments without actually requiring a single linear block?
I presume you refer to alloc_skb_with_frags() : It does the allocation, but I was expecting some kind soul to continue my work and provide the companion code to do the copy.
So far nobody took care of it.
RE: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
From: Eric
Quoted 8 lines · David Laight
Quoted 3 lines
Didn't someone write a function that significantly reduces the number of fragments without actually requiring a single linear block?
I presume you refer to
alloc_skb_with_frags(): It does the allocation, but I was expecting some kind soul to continue my work and provide the companion code to do the copy.
Not that one.
IIRC is was done to reduce the number of fragments through xennet.
You really want to try to keep some of the old fragments, just adding new ones to merge short sections.
OTOH 8 fragments isn't enough if the MAC supports TSO (dunno if it does). The skb_linearize() is only likely to fail for TSO anyway.
Or rather, if it can't allocate a 4k page you are already stuffed.
David.
Re: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
Quoted 7 lines · David Laight
Not that one.
IIRC is was done to reduce the number of fragments through xennet.You really want to try to keep some of the old fragments, just adding new ones to merge short sections.
OTOH 8 fragments isn't enough if the MAC supports TSO (dunno if it does).
I40 is a 40Gb NIC, it supports TSO, obviously.
Quoted 2 lines
The
skb_linearize()is only likely to fail for TSO anyway. Or rather, if it can't allocate a 4k page you are already stuffed.
So far, nobody wrote the code for this.
Page frag are allocated from pages, so if you cannot allocate a 4k page, this function has no guarantee to succeed no matter how hard you tried.
alloc_skb_with_frags() was already _much_ better than a single allocation of order-5 page. But if you feel you can do better, why don't you provide the code ?
RE: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
In reply to Eric DumazetQuoted 10 lines
-----Original Message-----
From: Eric Dumazet [mailto:[email protected]]
Sent: Saturday, November 15, 2014 10:22 AMQuoted 5 lines · Jeff Kirsher
From: Serey Kong <[email protected]>
This handles the case where a single packet with more than 8 data descriptors triggers a Malicious Driver Detect event in the device.
[...]
Quoted 11 lines
drivers/net/ethernet/intel/i40e/i40e_txrx.c static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, · line 2137
Quoted 8 lines
drivers/net/ethernet/intel/i40e/i40e_txrx.c +4
-2-if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) +if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) { gso_segs =skb_shinfo (skb)->gso_segs; -else + }else { gso_segs =1 ; +if (skb_shinfo (skb)->nr_frags >=I40E_MAX_BUFFER_TXD ) +skb_linearize (skb);What exactly happens if
skb_linearize()fails ?
Quoted 2 lines
Is this "Malicious Driver Detect event" fatal or simply packet is dropped without additional harm ?
This typically hits when there are many little TSO packets in a single MTU size frame. The hardware doesn't like dealing with more than 8 separate buffers.
If skb_linearize() fails and we try to send the skb as is, the hardware will throw an MDD event and disable that particular queue, possibly causing a Tx hang, which will lead to a PF reset and then we continue on. It's a bit of a hit to throughput, and most folks get a little annoyed when seeing the Tx hang stack trace in their log, but it generally isn't fatal.
If we disable the MDD detection, the hardware ends up putting garbage on the wire.
It looks to me that the way for skb_linearize() to fail is with -ENOMEM, in which case we probably have other issues.
If there are some alternative suggestions for dealing with this, we'd be happy to hear about them.
Cheers,
sln
RE: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
From: Nelson, Shannon
Quoted 23 lines
Quoted 9 lines
From: Eric Dumazet [mailto:[email protected]]
Sent: Saturday, November 15, 2014 10:22 AMQuoted 5 lines · Jeff Kirsher
From: Serey Kong <[email protected]>
This handles the case where a single packet with more than 8 data descriptors triggers a Malicious Driver Detect event in the device.
[...]
Quoted 11 lines
drivers/net/ethernet/intel/i40e/i40e_txrx.c static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, · line 2137
Quoted 8 lines
drivers/net/ethernet/intel/i40e/i40e_txrx.c +4
-2-if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) +if (tx_flags & (I40E_TX_FLAGS_TSO |I40E_TX_FLAGS_FSO )) { gso_segs =skb_shinfo (skb)->gso_segs; -else + }else { gso_segs =1 ; +if (skb_shinfo (skb)->nr_frags >=I40E_MAX_BUFFER_TXD ) +skb_linearize (skb);What exactly happens if
skb_linearize()fails ?
Quoted 5 lines
Quoted 2 lines
Is this "Malicious Driver Detect event" fatal or simply packet is dropped without additional harm ?
This typically hits when there are many little TSO packets in a single MTU size frame. The hardware doesn't like dealing with more than 8 separate buffers.
Except that a TSO packet is likely to be just under 64k and comprise of a small header and 16 other fragments - most of which will be a complete 4k page.
If the hardware can't handle such packets then I suspect you can't actually use TSO - which makes the device pretty useless.
If the problem is just too many fragment boundaries within a small number of bytes then you need to detect that specific problem - probably merging the adjacent small fragments into one that is large enough.
David
Re: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
Quoted 2 lines · David Laight
Except that a TSO packet is likely to be just under 64k and comprise of a small header and 16 other fragments - most of which will be a complete 4k page.
This is the code dealing with non TSO packets.
Re: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
In reply to David LaightQuoted 3 lines · David Laight
Except that a TSO packet is likely to be just under 64k and comprise of a small header and 16 other fragments - most of which will be a complete 4k page.
This is the section of the code sending a _non_ TSO packet.
Re: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
Quoted 1 line · Eric Dumazet
This is the section of the code sending a _non_ TSO packet.
Sorry for the double post, it was non intended.
RE: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
In reply to Eric DumazetFrom: Eric Dumazet
Quoted 7 lines · David Laight
Quoted 4 lines
Except that a TSO packet is likely to be just under 64k and comprise of a small header and 16 other fragments - most of which will be a complete 4k page.
This is the section of the code sending a _non_ TSO packet.
That isn't entirely clear from the patch context.
For a non-TSO packet the skb_serialize() is less likely to fail since it doesn't need contiguous pages.
(Unless you are sending 9k jumbo frames).
Actually many of the older ethernet devices will suffer buffer underrun if given too many small fragments due to lack of bus bandwidth. The high latencies of PCIe will make that worse - especially at high speeds.
Presumably these devices use 'store and forward' when doing TSO (or maybe even when just adding a checksum) removing any real problems caused by PCIe latency?
David
Re: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
Quoted 1 line · David Laight
That isn't entirely clear from the patch context.
gso_segs = 1 was not clear ???
gso_segs = 1;
if (skb_shinfo(skb)->nr_frags >= I40E_MAX_BUFFER_TXD)
skb_linearize(skb);
Nelson, what happens if a packet has 2 segments and uses 17 fragments ? Is the hardware OK with that ?
netperf -t TCP_SENDFILE -- -m 171
I did the test and it seems fine on my host, but maybe it was pure luck.
While the following indeed froze the card :
netperf -H 7.7.7.27 -t TCP_SENDFILE -- -m 30
[3257268.702689] i40e 0000:84:00.0: requesting a pf reset [3257268.831786] i40e 0000:84:00.0: i40e_ptp_init: added PHC on eth2 [3257268.912798] i40e 0000:84:00.0 eth2: NIC Link is Up 40 Gbps Full Duplex, Flow Control: RX/TX [3257338.895753] i40e 0000:84:00.0: Detected Tx Unit Hang [3257338.895753] VSI <518> [3257338.895753] Tx Queue <16> [3257338.895753] next_to_use <17c> [3257338.895753] next_to_clean <b2> [3257338.895757] i40e 0000:84:00.0: tx_bi[next_to_clean] [3257338.895757] time_stamp <1c20f09c9> [3257338.895757] jiffies <1c20f0eac> [3257338.895759] i40e 0000:84:00.0: tx hang detected on queue 16, resetting adapter [3257338.895769] i40e 0000:84:00.0 eth2: tx_timeout recovery level 1 [3257338.895926] i40e 0000:84:00.0: i40e_vsi_control_tx: VSI seid 518 Tx ring 0 disable timeout [3257338.949922] i40e 0000:84:00.0: i40e_vsi_control_tx: VSI seid 520 Tx ring 64 disable timeout [3257339.410705] i40e 0000:84:00.0: PF reset failed, -15
Quoted 3 lines
For a non-TSO packet the
skb_serialize()is less likely to fail since it doesn't need contiguous pages.
Any memory allocation can fail, regardless of the size. We do not want a memory stress being able to crash the host, likely or not. It is not worth discussing this, really.
Re: [net-next 03/12] i40e: Handle a single mss packet with more than 8 frags
In reply to Nelson, ShannonQuoted 11 lines · Shannon
This typically hits when there are many little TSO packets in a single MTU size frame. The hardware doesn't like dealing with more than 8 separate buffers.
If
skb_linearize()fails and we try to send the skb as is, the hardware will throw an MDD event and disable that particular queue, possibly causing a Tx hang, which will lead to a PF reset and then we continue on. It's a bit of a hit to throughput, and most folks get a little annoyed when seeing the Tx hang stack trace in their log, but it generally isn't fatal.
Quoted 6 lines
If we disable the MDD detection, the hardware ends up putting garbage on the wire.
It looks to me that the way for
skb_linearize()to fail is with-ENOMEM, in which case we probably have other issues.
This kind of events happens in real workloads, trust me.
Quoted 2 lines
If there are some alternative suggestions for dealing with this, we'd be happy to hear about them.
Nelson, all you have to do is to check skb_linearize(skb) return code.
If its a failure, then drop this packet. How hard is this ?
This should hardly trigger in normal conditions.
If some customer complains, then you might implement something more complex in the future.
Lets fix the bug first in a 100% safe way.
PATCH 4/12 i40e: Bump version to 1.1.23
In reply to Jeff KirsherFrom: Catherine Sullivan <[email protected]>
Bumping minor version as this will be the second SW release and it should be 1.
--- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_main.c +2 -2
@@ -38,8 +38,8 @@ static const char i40e_driver_string[] =#define DRV_KERN "-k"#define DRV_VERSION_MAJOR 1 -#define DRV_VERSION_MINOR 0 -#define DRV_VERSION_BUILD 21 +#define DRV_VERSION_MINOR 1 +#define DRV_VERSION_BUILD 23#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN
Signature · 1 line
1.9.3
PATCH 5/12 i40e: Resume Port Tx after DCB event
In reply to Jeff KirsherFrom: Neerav Parikh <[email protected]>
When there are DCB configuration changes based on DCBX the firmware suspends the port's Tx and generates an event to the PF. The PF is then responsible to reconfigure the PF VSIs and switching topology as per the updated DCB configuration and then resume the port's Tx by calling the "Resume Port Tx" AQ command.
This patch adds this call to the flow that handles DCB re-configuration in the PF.
--- drivers/net/ethernet/intel/i40e/i40e_common.c | 20 +++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_main.c | 31 +++++++++++++++++++++++- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 2 ++ 3 files changed, 52 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/i40e/i40e_common.c +20 -0
@@ -3217,6 +3217,26 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw, }/** +* i40e_aq_resume_port_tx +* @hw: pointer to the hardware structure +* @cmd_details: pointer to command details structure or NULL +* +* Resume port's Tx traffic +**/ +i40e_status i40e_aq_resume_port_tx (struct i40e_hw *hw, +struct i40e_asq_cmd_details *cmd_details) +{ +struct i40e_aq_desc desc; +i40e_status status; + +i40e_fill_default_direct_cmd_desc (&desc, i40e_aqc_opc_resume_port_tx); + + status =i40e_asq_send_command (hw, &desc,NULL ,0 , cmd_details); + +return status; +} + +/** * i40e_set_pci_config_data - store PCI bus info * @hw: pointer to hardware structure * @link_status: the link status word from PCI config space
drivers/net/ethernet/intel/i40e/i40e_main.c +30 -1
@@ -4382,6 +4382,31 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf) }/** +* i40e_resume_port_tx - Resume port Tx +* @pf: PF struct +* +* Resume a port's Tx and issue a PF reset in case of failure to +* resume. +**/ +static int i40e_resume_port_tx (struct i40e_pf *pf) +{ +struct i40e_hw *hw = &pf->hw; +int ret; + + ret =i40e_aq_resume_port_tx (hw,NULL ); +if (ret) { +dev_info (&pf->pdev->dev, +"AQ command Resume Port Tx failed = %d\n" , + pf->hw.aq.asq_last_status); +/* Schedule PF reset to recover */ +set_bit (__I40E_PF_RESET_REQUESTED, &pf->state); +i40e_service_event_schedule (pf); + } + +return ret; +} + +/** * i40e_init_pf_dcb - Initialize DCB configuration * @pf: PF being configured *
@@ -5075,7 +5100,11 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,/* Changes in configuration update VEB/VSI */ i40e_dcb_reconfigure (pf); -i40e_pf_unquiesce_all_vsi (pf); + ret =i40e_resume_port_tx (pf); + +/* In case of error no point in resuming VSIs */ +if (!ret) +i40e_pf_unquiesce_all_vsi (pf); exit:return ret; }
drivers/net/ethernet/intel/i40e/i40e_prototype.h +2 -0
@@ -230,6 +230,8 @@ i40e_status i40e_aq_query_switch_comp_bw_config(struct i40e_hw *hw,u16 seid, struct i40e_aqc_query_switching_comp_bw_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details); +i40e_status i40e_aq_resume_port_tx (struct i40e_hw *hw, +struct i40e_asq_cmd_details *cmd_details);/* i40e_common */ i40e_status i40e_init_shared_code (struct i40e_hw *hw);i40e_status i40e_pf_reset (struct i40e_hw *hw);
Signature · 1 line
1.9.3
PATCH 6/12 i40e: Add support to firmware CEE DCBX mode
In reply to Jeff KirsherFrom: Neerav Parikh <[email protected]>
This patch allows i40e driver to query and use DCB configuration from firmware when firmware DCBX agent is in CEE mode.
--- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 45 ++++- drivers/net/ethernet/intel/i40e/i40e_common.c | 28 +++ drivers/net/ethernet/intel/i40e/i40e_dcb.c | 203 +++++++++++++++++++++- drivers/net/ethernet/intel/i40e/i40e_dcb.h | 5 + drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c | 8 +- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 2 + drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 26 ++- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 3 + drivers/net/ethernet/intel/i40e/i40e_type.h | 41 +++-- 10 files changed, 328 insertions(+), 35 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +43 -2
@@ -255,6 +255,7 @@ enum i40e_admin_queue_opc { i40e_aqc_opc_lldp_delete_tlv =0x0A04 , i40e_aqc_opc_lldp_stop =0x0A05 , i40e_aqc_opc_lldp_start =0x0A06 , + i40e_aqc_opc_get_cee_dcb_cfg =0x0A07 ,/* Tunnel commands */ i40e_aqc_opc_add_udp_tunnel = 0x0B00,
@@ -1987,10 +1988,50 @@ struct i40e_aqc_lldp_start {I40E_CHECK_CMD_LENGTH (i40e_aqc_lldp_start); -/* Apply MIB changes (0x0A07) -* uses the generic struc as it contains no data +/* Get CEE DCBX Oper Config (0x0A07) +* uses the generic descriptor struct +* returns below as indirect response */ +#define I40E_AQC_CEE_APP_FCOE_SHIFT 0x0 +#define I40E_AQC_CEE_APP_FCOE_MASK (0x7 << I40E_AQC_CEE_APP_FCOE_SHIFT) +#define I40E_AQC_CEE_APP_ISCSI_SHIFT 0x3 +#define I40E_AQC_CEE_APP_ISCSI_MASK (0x7 << I40E_AQC_CEE_APP_ISCSI_SHIFT) +#define I40E_AQC_CEE_APP_FIP_SHIFT 0x8 +#define I40E_AQC_CEE_APP_FIP_MASK (0x7 << I40E_AQC_CEE_APP_FIP_SHIFT) +#define I40E_AQC_CEE_PG_STATUS_SHIFT 0x0 +#define I40E_AQC_CEE_PG_STATUS_MASK (0x7 << I40E_AQC_CEE_PG_STATUS_SHIFT) +#define I40E_AQC_CEE_PFC_STATUS_SHIFT 0x3 +#define I40E_AQC_CEE_PFC_STATUS_MASK (0x7 << I40E_AQC_CEE_PFC_STATUS_SHIFT) +#define I40E_AQC_CEE_APP_STATUS_SHIFT 0x8 +#define I40E_AQC_CEE_APP_STATUS_MASK (0x7 << I40E_AQC_CEE_APP_STATUS_SHIFT) +struct i40e_aqc_get_cee_dcb_cfg_v1_resp { +u8 reserved1; +u8 oper_num_tc; +u8 oper_prio_tc[4 ]; +u8 reserved2; +u8 oper_tc_bw[8 ]; +u8 oper_pfc_en; +u8 reserved3; +__le16 oper_app_prio; +u8 reserved4; +__le16 tlv_status; +}; + +I40E_CHECK_STRUCT_LEN (0x18 , i40e_aqc_get_cee_dcb_cfg_v1_resp); + +struct i40e_aqc_get_cee_dcb_cfg_resp { +u8 oper_num_tc; +u8 oper_prio_tc[4 ]; +u8 oper_tc_bw[8 ]; +u8 oper_pfc_en; +__le16 oper_app_prio; +__le32 tlv_status; +u8 reserved[12 ]; +}; + +I40E_CHECK_STRUCT_LEN (0x20 , i40e_aqc_get_cee_dcb_cfg_resp); +/* Add Udp Tunnel command and completion (direct 0x0B00) */ struct i40e_aqc_add_udp_tunnel {__le16 udp_port;
drivers/net/ethernet/intel/i40e/i40e_common.c +28 -0
@@ -2660,6 +2660,34 @@ i40e_status i40e_aq_start_lldp(struct i40e_hw *hw, }/** +* i40e_aq_get_cee_dcb_config +* @hw: pointer to the hw struct +* @buff: response buffer that stores CEE operational configuration +* @buff_size: size of the buffer passed +* @cmd_details: pointer to command details structure or NULL +* +* Get CEE DCBX mode operational configuration from firmware +**/ +i40e_status i40e_aq_get_cee_dcb_config (struct i40e_hw *hw, +void *buff,u16 buff_size, +struct i40e_asq_cmd_details *cmd_details) +{ +struct i40e_aq_desc desc; +i40e_status status; + +if (buff_size ==0 || !buff) +return I40E_ERR_PARAM ; + +i40e_fill_default_direct_cmd_desc (&desc, i40e_aqc_opc_get_cee_dcb_cfg); + + desc.flags |=cpu_to_le16 ((u16 )I40E_AQ_FLAG_BUF ); + status =i40e_asq_send_command (hw, &desc, (void *)buff, buff_size, + cmd_details); + +return status; +} + +/** * i40e_aq_add_udp_tunnel * @hw: pointer to the hw struct * @udp_port: the UDP port to add
drivers/net/ethernet/intel/i40e/i40e_dcb.c +202 -1
228 lines not on this page · raw message
drivers/net/ethernet/intel/i40e/i40e_dcb.h +5 -0
@@ -65,6 +65,11 @@#define I40E_IEEE_ETS_PRIO_0_MASK (0x7 << I40E_IEEE_ETS_PRIO_0_SHIFT)#define I40E_IEEE_ETS_PRIO_1_SHIFT 4#define I40E_IEEE_ETS_PRIO_1_MASK (0x7 << I40E_IEEE_ETS_PRIO_1_SHIFT) +#define I40E_CEE_PGID_PRIO_0_SHIFT 0 +#define I40E_CEE_PGID_PRIO_0_MASK (0xF << I40E_CEE_PGID_PRIO_0_SHIFT) +#define I40E_CEE_PGID_PRIO_1_SHIFT 4 +#define I40E_CEE_PGID_PRIO_1_MASK (0xF << I40E_CEE_PGID_PRIO_1_SHIFT) +#define I40E_CEE_PGID_STRICT 15/* Defines for IEEE TSA types */ #define I40E_IEEE_TSA_STRICT 0
drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c +4 -4
@@ -207,7 +207,7 @@ void i40e_dcbnl_set_all(struct i40e_vsi *vsi)* VSI **/ static int i40e_dcbnl_vsi_del_app (struct i40e_vsi *vsi, -struct i40e_ieee_app_priority_table *app) +struct i40e_dcb_app_priority_table *app) {struct net_device *dev = vsi->netdev;struct dcb_app sapp;
@@ -229,7 +229,7 @@ static int i40e_dcbnl_vsi_del_app(struct i40e_vsi *vsi,* Delete given APP from all the VSIs for given PF **/ static void i40e_dcbnl_del_app (struct i40e_pf *pf, -struct i40e_ieee_app_priority_table *app) +struct i40e_dcb_app_priority_table *app) {int v, err;for (v =0 ; v < pf->num_alloc_vsi; v++) {
@@ -252,7 +252,7 @@ static void i40e_dcbnl_del_app(struct i40e_pf *pf,* Find given APP in the DCB configuration **/ static bool i40e_dcbnl_find_app (struct i40e_dcbx_config *cfg, -struct i40e_ieee_app_priority_table *app) +struct i40e_dcb_app_priority_table *app) {int i;
@@ -277,7 +277,7 @@ static bool i40e_dcbnl_find_app(struct i40e_dcbx_config *cfg,void i40e_dcbnl_flush_apps (struct i40e_pf *pf,struct i40e_dcbx_config *new_cfg) { -struct i40e_ieee_app_priority_table app; +struct i40e_dcb_app_priority_table app;struct i40e_dcbx_config *dcbxcfg;struct i40e_hw *hw = &pf->hw;int i;
drivers/net/ethernet/intel/i40e/i40e_debugfs.c +2 -0
@@ -1313,6 +1313,8 @@ static ssize_t i40e_dbg_command_write(struct file *filp, bw_data =NULL ;dev_info (&pf->pdev->dev, +"port dcbx_mode=%d\n" , cfg->dcbx_mode); +dev_info (&pf->pdev->dev,"port ets_cfg: willing=%d cbs=%d, maxtcs=%d\n" , cfg->etscfg.willing, cfg->etscfg.cbs, cfg->etscfg.maxtcs);
drivers/net/ethernet/intel/i40e/i40e_fcoe.c +1 -1
@@ -343,7 +343,7 @@ int i40e_init_pf_fcoe(struct i40e_pf *pf)**/ u8 i40e_get_fcoe_tc_map (struct i40e_pf *pf) { -struct i40e_ieee_app_priority_table app; +struct i40e_dcb_app_priority_table app;struct i40e_hw *hw = &pf->hw;u8 enabled_tc =0 ;u8 tc, i;
drivers/net/ethernet/intel/i40e/i40e_main.c +17 -9
@@ -4442,6 +4442,8 @@ static int i40e_init_pf_dcb(struct i40e_pf *pf)/* Enable DCB tagging only when more than one TC */ if (i40e_dcb_get_num_tc (&hw->local_dcbx_config) >1 ) pf->flags |=I40E_FLAG_DCB_ENABLED ; +dev_dbg (&pf->pdev->dev, +"DCBX offload is supported for this PF.\n" ); } }else { dev_info(&pf->pdev->dev, "AQ Querying DCB configuration failed: %d\n",
@@ -5023,6 +5025,8 @@ bool i40e_dcb_need_reconfig(struct i40e_pf *pf,dev_dbg (&pf->pdev->dev,"APP Table change detected.\n" ); } +dev_dbg (&pf->pdev->dev,"%s: need_reconfig=%d\n" , __func__, + need_reconfig);return need_reconfig; }
@@ -5050,11 +5054,16 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,/* Ignore if event is not for Nearest Bridge */ type = ((mib->type >>I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT ) &I40E_AQ_LLDP_BRIDGE_TYPE_MASK ); +dev_dbg (&pf->pdev->dev, +"%s: LLDP event mib bridge type 0x%x\n" , __func__, type);if (type !=I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE )return ret;/* Check MIB Type and return if event for Remote MIB update */ type = mib->type &I40E_AQ_LLDP_MIB_TYPE_MASK ; +dev_dbg (&pf->pdev->dev, +"%s: LLDP event mib type %s\n" , __func__, + type ?"remote" :"local" );if (type ==I40E_AQ_LLDP_MIB_REMOTE ) {/* Update the remote cached instance and return */ ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
@@ -5063,12 +5072,14 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, goto exit; } -/* Convert/store the DCBX data from LLDPDU temporarily */ memset (&tmp_dcbx_cfg,0 ,sizeof (tmp_dcbx_cfg)); - ret =i40e_lldp_to_dcb_config (e->msg_buf, &tmp_dcbx_cfg); +/* Store the old configuration */ + tmp_dcbx_cfg = *dcbx_cfg; + +/* Get updated DCBX data from firmware */ + ret =i40e_get_dcb_config (&pf->hw);if (ret) { -/* Error in LLDPDU parsing return */ -dev_info (&pf->pdev->dev,"Failed parsing LLDPDU from event buffer\n" ); +dev_info (&pf->pdev->dev,"Failed querying DCB configuration data from firmware.\n" ); goto exit; }
@@ -5078,12 +5089,9 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, goto exit; } - need_reconfig =i40e_dcb_need_reconfig (pf, dcbx_cfg, &tmp_dcbx_cfg); - -i40e_dcbnl_flush_apps (pf, &tmp_dcbx_cfg); + need_reconfig =i40e_dcb_need_reconfig (pf, &tmp_dcbx_cfg, dcbx_cfg); -/* Overwrite the new configuration */ - *dcbx_cfg = tmp_dcbx_cfg; +i40e_dcbnl_flush_apps (pf, dcbx_cfg);if (!need_reconfig) goto exit;
drivers/net/ethernet/intel/i40e/i40e_prototype.h +3 -0
@@ -175,6 +175,9 @@ i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent, struct i40e_asq_cmd_details *cmd_details);i40e_status i40e_aq_start_lldp (struct i40e_hw *hw,struct i40e_asq_cmd_details *cmd_details); +i40e_status i40e_aq_get_cee_dcb_config (struct i40e_hw *hw, +void *buff,u16 buff_size, +struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_add_udp_tunnel(struct i40e_hw *hw, u16 udp_port, u8 protocol_index, u8 *filter_index,
drivers/net/ethernet/intel/i40e/i40e_type.h +23 -18
66 lines not on this page · raw message
Signature · 1 line
1.9.3
PATCH 7/12 i40e: Check for LLDP AdminStatus before querying DCBX
In reply to Jeff KirsherFrom: Neerav Parikh <[email protected]>
This patch adds a check whether LLDP Agent's default AdminStatus is enabled or disabled on a given port. If it is disabled then it sets the DCBX status to disabled as well; and would not query firmware for any DCBX configuration data.
--- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 49 ++++++++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_prototype.h | 2 + drivers/net/ethernet/intel/i40e/i40e_type.h | 12 ++++++ 3 files changed, 63 insertions(+)
drivers/net/ethernet/intel/i40e/i40e_dcb.c +49 -0
@@ -640,10 +640,27 @@ out:i40e_status i40e_init_dcb (struct i40e_hw *hw) {i40e_status ret =0 ; +struct i40e_lldp_variables lldp_cfg; +u8 adminstatus =0 ;if (!hw->func_caps.dcb)return ret; +/* Read LLDP NVM area */ + ret =i40e_read_lldp_cfg (hw, &lldp_cfg); +if (ret) +return ret; + +/* Get the LLDP AdminStatus for the current port */ + adminstatus = lldp_cfg.adminstatus >> (hw->port *4 ); + adminstatus &=0xF ; + +/* LLDP agent disabled */ +if (!adminstatus) { + hw->dcbx_status =I40E_DCBX_STATUS_DISABLED ; +return ret; + } +/* Get DCBX status */ ret =i40e_get_dcbx_status (hw, &hw->dcbx_status);if (ret)
@@ -655,6 +672,8 @@ i40e_status i40e_init_dcb(struct i40e_hw *hw)case I40E_DCBX_STATUS_IN_PROGRESS :/* Get current DCBX configuration */ ret =i40e_get_dcb_config (hw); +if (ret) +return ret;break ;case I40E_DCBX_STATUS_DISABLED :return ret;
@@ -671,3 +690,33 @@ i40e_status i40e_init_dcb(struct i40e_hw *hw)return ret; } + +/** +* i40e_read_lldp_cfg - read LLDP Configuration data from NVM +* @hw: pointer to the HW structure +* @lldp_cfg: pointer to hold lldp configuration variables +* +* Reads the LLDP configuration data from NVM +**/ +i40e_status i40e_read_lldp_cfg (struct i40e_hw *hw, +struct i40e_lldp_variables *lldp_cfg) +{ +i40e_status ret =0 ; +u32 offset = (2 *I40E_NVM_LLDP_CFG_PTR ); + +if (!lldp_cfg) +return I40E_ERR_PARAM ; + + ret =i40e_acquire_nvm (hw,I40E_RESOURCE_READ ); +if (ret) + goto err_lldp_cfg; + + ret =i40e_aq_read_nvm (hw,I40E_SR_EMP_MODULE_PTR , offset, +sizeof (struct i40e_lldp_variables ), + (u8 *)lldp_cfg, + true,NULL ); +i40e_release_nvm (hw); + +err_lldp_cfg: +return ret; +}
drivers/net/ethernet/intel/i40e/i40e_prototype.h +2 -0
@@ -235,6 +235,8 @@ i40e_status i40e_aq_query_switch_comp_bw_config(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details);i40e_status i40e_aq_resume_port_tx (struct i40e_hw *hw,struct i40e_asq_cmd_details *cmd_details); +i40e_status i40e_read_lldp_cfg (struct i40e_hw *hw, +struct i40e_lldp_variables *lldp_cfg);/* i40e_common */ i40e_status i40e_init_shared_code (struct i40e_hw *hw);i40e_status i40e_pf_reset (struct i40e_hw *hw);
drivers/net/ethernet/intel/i40e/i40e_type.h +12 -0
@@ -1377,6 +1377,18 @@ enum i40e_reset_type { I40E_RESET_EMPR = 3, }; +/* IEEE 802.1AB LLDP Agent Variables from NVM */ +#define I40E_NVM_LLDP_CFG_PTR 0xD +struct i40e_lldp_variables { +u16 length; +u16 adminstatus; +u16 msgfasttx; +u16 msgtxinterval; +u16 txparams; +u16 timers; +u16 crc8; +}; +/* RSS Hash Table Size */ #define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000#endif /* _I40E_TYPE_H_ */
Signature · 1 line
1.9.3
PATCH 8/12 i40e: Update VEB's enabled_tc after reconfiguration
In reply to Jeff KirsherFrom: Neerav Parikh <[email protected]>
When the port TC configuration changes as a result of DCBx the driver modifies the enabled TCs for the VEBs it manages. But, in the process it did not update the enabled_tc value that it caches on a per VEB basis.
So, when the next reconfiguration event occurs where the number of TC value is same as the value cached in enabled_tc for a given VEB; driver does not modify it's TC configuration by calling appropriate AQ command believing it is running with the same configuration as requested. Now, as the VEB is not actually enabled for the TCs that are there any TC configuration command for VSI attached to that VEB with TCs that are not enabled for the VEB fails.
This patch fixes this issue.
--- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/intel/i40e/i40e_main.c +1 -0
@@ -8283,6 +8283,7 @@ static int i40e_veb_get_bw_info(struct i40e_veb *veb) veb->bw_limit =le16_to_cpu (ets_data.port_bw_limit); veb->bw_max_quanta = ets_data.tc_bw_max; veb->is_abs_credits = bw_data.absolute_credits_enable; + veb->enabled_tc = ets_data.tc_valid_bits; tc_bw_max =le16_to_cpu (bw_data.tc_bw_max[0 ]) | (le16_to_cpu (bw_data.tc_bw_max[1 ]) <<16 );for (i =0 ; i <I40E_MAX_TRAFFIC_CLASS ; i++) {
Signature · 1 line
1.9.3
PATCH 9/12 i40e: Modify Tx disable wait flow in case of DCB reconfiguration
In reply to Jeff KirsherFrom: Neerav Parikh <[email protected]>
When DCB TC configuration changes the firmware suspends the port's Tx. Now, as DCB TCs may have changed the PF driver tries to reconfigure the TC configuration of the VSIs it manages. As part of this process it disables the VSI queues but the Tx queue disable will not complete as the port's Tx has been suspended. So, waiting for Tx queues to go to disable state in this flow may lead to detection of Tx queue disable timeout errors.
Hence, this patch adds a new PF state so that if a port's Tx is in suspended state the Tx queue disable flow would just put the request for the queue to be disabled and return without waiting for the queue to be actually disabled.
Once the VSI(s) TC reconfiguration has been done and driver has called firmware AQC "Resume PF Traffic" the driver checks the Tx queues requested to be disabled are actually disabled before re-enabling them again.
--- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 60 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+)
drivers/net/ethernet/intel/i40e/i40e.h +1 -0
@@ -146,6 +146,7 @@ enum i40e_state_t { __I40E_DOWN_REQUESTED, __I40E_FD_FLUSH_REQUESTED, __I40E_RESET_FAILED, + __I40E_PORT_TX_SUSPENDED, }; enum i40e_interrupt_policy {
drivers/net/ethernet/intel/i40e/i40e_main.c +60 -0
85 lines not on this page · raw message
Signature · 1 line
1.9.3
PATCH 10/12 i40e: Do not disable/enable FCoE VSI with DCB reconfig
In reply to Jeff KirsherFrom: Neerav Parikh <[email protected]>
FCoE VSI Tx queue disable times out when reconfiguring as a result of DCB TC configuration change event.
The hardware allows us to skip disabling and enabling of Tx queues for VSIs with single TC enabled. As FCoE VSI is configured to have only single TC we skip it from disable/enable flow.
--- drivers/net/ethernet/intel/i40e/i40e_main.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/i40e/i40e_main.c +11 -1
@@ -3862,6 +3862,15 @@ static void i40e_quiesce_vsi(struct i40e_vsi *vsi)if (test_bit (__I40E_DOWN, &vsi->state))return ; +/* No need to disable FCoE VSI when Tx suspended */ +if ((test_bit (__I40E_PORT_TX_SUSPENDED, &vsi->back->state)) && + vsi->type ==I40E_VSI_FCOE ) { +dev_dbg (&vsi->back->pdev->dev, +"%s: VSI seid %d skipping FCoE VSI disable\n" , + __func__, vsi->seid); +return ; + } +set_bit (__I40E_NEEDS_RESTART, &vsi->state);if (vsi->netdev &&netif_running (vsi->netdev)) { vsi->netdev->netdev_ops->ndo_stop (vsi->netdev);
@@ -3953,7 +3962,8 @@ static int i40e_pf_wait_txq_disabled(struct i40e_pf *pf)int v, ret =0 ;for (v =0 ; v < pf->hw.func_caps.num_vsis; v++) { -if (pf->vsi[v]) { +/* No need to wait for FCoE VSI queues */ +if (pf->vsi[v] && pf->vsi[v]->type !=I40E_VSI_FCOE ) { ret =i40e_vsi_wait_txq_disabled (pf->vsi[v]);if (ret)break ;
Signature · 1 line
1.9.3
PATCH 11/12 i40e: Prevent link flow control settings when PFC is enabled
In reply to Jeff KirsherFrom: Neerav Parikh <[email protected]>
When PFC is enabled we should not proceed with setting the link flow control parameters. Also, always report the link flow Tx/Rx settings as off when PFC is enabled.
--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_ethtool.c +12 -2
@@ -644,11 +644,19 @@ static void i40e_get_pauseparam(struct net_device *netdev,struct i40e_pf *pf = np->vsi->back;struct i40e_hw *hw = &pf->hw;struct i40e_link_status *hw_link_info = &hw->phy.link_info; +struct i40e_dcbx_config *dcbx_cfg = &hw->local_dcbx_config; pause->autoneg = ((hw_link_info->an_info &I40E_AQ_AN_COMPLETED ) ?AUTONEG_ENABLE :AUTONEG_DISABLE ); +/* PFC enabled so report LFC as off */ +if (dcbx_cfg->pfc.pfcenable) { + pause->rx_pause =0 ; + pause->tx_pause =0 ; +return ; + } +if (hw->fc.current_mode ==I40E_FC_RX_PAUSE ) { pause->rx_pause =1 ; }else if (hw->fc.current_mode ==I40E_FC_TX_PAUSE ) {
@@ -672,6 +680,7 @@ static int i40e_set_pauseparam(struct net_device *netdev,struct i40e_vsi *vsi = np->vsi;struct i40e_hw *hw = &pf->hw;struct i40e_link_status *hw_link_info = &hw->phy.link_info; +struct i40e_dcbx_config *dcbx_cfg = &hw->local_dcbx_config;bool link_up = hw_link_info->link_info &I40E_AQ_LINK_UP ;i40e_status status;u8 aq_failures;
@@ -693,8 +702,9 @@ static int i40e_set_pauseparam(struct net_device *netdev,netdev_info (netdev,"Autoneg did not complete so changing settings may not result in an actual change.\n" ); } -if (hw->fc.current_mode ==I40E_FC_PFC ) { -netdev_info (netdev,"Priority flow control enabled. Cannot set link flow control.\n" ); +if (dcbx_cfg->pfc.pfcenable) { +netdev_info (netdev, +"Priority flow control enabled. Cannot set link flow control.\n" );return -EOPNOTSUPP ; }
Signature · 1 line
1.9.3
PATCH 12/12 i40e: Set XPS bit mask to zero in DCB mode
In reply to Jeff KirsherFrom: Neerav Parikh <[email protected]>
Due to DCBX configuration change if the VSI needs to use more than 1 TC; it needs to disable the XPS maps that were set when operating in 1 TC mode. Without disabling XPS the netdev layer will select queues based on those settings and not use the TC queue mapping to make the queue selection.
This patch allows the driver to enable/disable the XPS based on the number of TCs being enabled for the given VSI.
--- drivers/net/ethernet/intel/i40e/i40e_main.c | 38 +++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 7 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_main.c +31 -7
@@ -2382,6 +2382,35 @@ static void i40e_vsi_free_rx_resources(struct i40e_vsi *vsi) }/** +* i40e_config_xps_tx_ring - Configure XPS for a Tx ring +* @ring: The Tx ring to configure +* +* This enables/disables XPS for a given Tx descriptor ring +* based on the TCs enabled for the VSI that ring belongs to. +**/ +static void i40e_config_xps_tx_ring (struct i40e_ring *ring) +{ +struct i40e_vsi *vsi = ring->vsi; +cpumask_var_t mask; + +if (ring->q_vector && ring->netdev) { +/* Single TC mode enable XPS */ +if (vsi->tc_config.numtc <=1 && + !test_and_set_bit (__I40E_TX_XPS_INIT_DONE, &ring->state)) { +netif_set_xps_queue (ring->netdev, + &ring->q_vector->affinity_mask, + ring->queue_index); + }else if (alloc_cpumask_var (&mask,GFP_KERNEL )) { +/* Disable XPS to allow selection based on TC */ +bitmap_zero (cpumask_bits (mask), nr_cpumask_bits); +netif_set_xps_queue (ring->netdev, mask, + ring->queue_index); +free_cpumask_var (mask); + } + } +} + +/** * i40e_configure_tx_ring - Configure a transmit ring context and rest * @ring: The Tx ring to configure *
@@ -2404,13 +2433,8 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring) ring->atr_sample_rate =0 ; } -/* initialize XPS */ -if (ring->q_vector && ring->netdev && - vsi->tc_config.numtc <=1 && - !test_and_set_bit (__I40E_TX_XPS_INIT_DONE, &ring->state)) -netif_set_xps_queue (ring->netdev, - &ring->q_vector->affinity_mask, - ring->queue_index); +/* configure XPS */ +i40e_config_xps_tx_ring (ring);/* clear the context structure first */ memset (&tx_ctx,0 ,sizeof (tx_ctx));
Signature · 1 line
1.9.3
David Miller
maintainerFrom: Jeff Kirsher <[email protected]>
Date: Fri, 14 Nov 2014 22:08:23 -0800
Quoted 1 line
This series contains updates to i40e only.
Patch #3 needs to be updated to do error handling for the case where skb_linearize() fails, as pointed out by Eric Dumazet.