From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:58
This series contains fixes for i40e and i40evf only.
Alexey Khoroshilov found a possible leak of 'cmd_buf' when copy_from_user()
failed in i40e_dbg_command_write(), so resolved by calling kfree().
Shannon provides a fix to ensure the shift and bitwise precedences do not
work backwards for us by adding parans. Fixed the driver by preventing
the driver from allowing stray interrupts or causing system logs from
un-handled interrupts by combining the ICR0 shutdown with the standard
interrupt shutdown and add the interrupt clearing to the PCI shutdown
path. Fixed an issue where a NVM write times out before a transaction
can complete, so Shannon added logic to make another attempt by
reacquiring the semaphore, then retry the write, if the one retry fails,
we will then give up. Adds checks to pointers before their use to ensure
we do not try to dereference NULL pointers when returning values from the
AdminQ calls.
Akeem adds a check to bail out if the device is already down when checking
for Tx hang subtask.
Anjali fixes TSO with more than 8 frags per segment issue. The hardware
has some limitations which the driver needs to adhere to:
1) no more than 8 descriptors per packet on the wire
2) no header can span more than 3 descriptors
If one of these events happens, the hardware will generate an internal
error and freeze the Tx queue, so Anjali fixes this by linearizes the skb
to avoid these situations. Fixed an issue where the per Traffic Class
queue count was higher than queues enabled, which will fix a warning
with multiple function mode where systems regularly have more cores than
vectors. Fixed TCP/IPv6 over VXLAN Tx checksum offload, where we were
checking the outer protocol flags and deciding the flow for the inner
header.
Jesse fixes a race condition in the transmit hang detection. Before we
were having issues of false Tx hang detection, no the driver makes more
direct with the checks for progress forward by directly checking the head
write back address and tail register when determining progress. This
avoids Tx hangs where the software gets behind, because we are directly
checking hardware state when determining a hang state.
Neerav fixes the transmit ring Qset handle when DCB reconfigures. The issue
was when DCB is reconfigured to a single traffic class (TC) and the driver
did not reset the Tx ring Qset handle to correct the mapping, which caused
the Tx queue to disable timeouts. Also as part of DCB reconfiguration flow
if the Tx queue disable times out, then issue a PF reset to do some level
of recovery.
Mitch stops flow director on shutdown because, in some cases, the hardware
would continue to try to access the FDIR ring after entering D3Hot state,
which would cause either PCIe errors or NMIs, depending upon the system
configuration.
* NOTE * I have verified that this series of patches for net will not cause
any merge issues when you sync up your net tree with your net-next tree.
The following are changes since commit 31639b94cadc03727d0ae1f048e9688dd508883f:
MAINTAINERS: update my email address
and are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net master
Akeem G Abodunrin (1):
i40e: Don't check for Tx hang when PF down
Alexey Khoroshilov (1):
i40e: Fix memory leak at failure path in i40e_dbg_command_write()
Anjali Singhai (3):
i40e: Fix TSO with more than 8 frags per segment issue
i40e: Fix the case where per TC queue count was higher than queues
enabled
i40evf: TCP/IPv6 over Vxlan Tx checksum offload fix
Jesse Brandeburg (1):
i40e: fix race in hang check
Mitch A Williams (1):
i40e: stop flow director on shutdown
Parikh, Neerav (2):
i40e: Fix the Tx ring qset handle when DCB reconfigures
i40e: Issue a PF reset if Tx queue disable timeout
Shannon Nelson (4):
i40e: fix shift precedence issue
i40e: disconnect irqs on shutdown
i40e: catch NVM write semaphore timeout and retry
i40e: check pointers before use
drivers/net/ethernet/intel/i40e/i40e_common.c | 7 +-
drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c | 2 +-
drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 44 ++++++--
drivers/net/ethernet/intel/i40e/i40e_nvm.c | 35 ++++++
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 119 +++++++++++++++-----
drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 +
drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 143 ++++++++++++++++++-------
drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 1 +
9 files changed, 280 insertions(+), 76 deletions(-)
--
1.9.3
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:54
From: Anjali Singhai <redacted>
The hardware has some limitations the driver needs to adhere to,
that we found in extended testing.
1) no more than 8 descriptors per packet on the wire
2) no header can span more than 3 descriptors
If one of these events occurs, the hardware will generate an internal
error and freeze the Tx queue.
This patch linearizes the skb to avoid these situations.
Change-ID: I37dab7d3966e14895a9663ec4d0aaa8eb0d9e115
Signed-off-by: Anjali Singhai Jain <redacted>
Tested-by: Jim Young <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 65 +++++++++++++++++++++++++++
drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 +
drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 65 +++++++++++++++++++++++++++
drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 1 +
4 files changed, 132 insertions(+)
@@ -2140,6 +2140,67 @@ static int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)}/**+*i40e_chk_linearize-Checkiftherearemorethan8fragmentsperpacket+*@skb:sendbuffer+*@tx_flags:collectedsendinformation+*@hdr_len:sizeofthepacketheader+*+*Note:OurHWcan'tscatter-gathermorethan8fragmentstobuild+*apacketonthewireandsoweneedtofigureoutthecaseswherewe+*needtolinearizetheskb.+**/+staticbooli40e_chk_linearize(structsk_buff*skb,u32tx_flags,+constu8hdr_len)+{+structskb_frag_struct*frag;+boollinearize=false;+unsignedintsize=0;+u16num_frags;+u16gso_segs;++num_frags=skb_shinfo(skb)->nr_frags;+gso_segs=skb_shinfo(skb)->gso_segs;++if(tx_flags&(I40E_TX_FLAGS_TSO|I40E_TX_FLAGS_FSO)){+u16j=1;++if(num_frags<(I40E_MAX_BUFFER_TXD))+gotolinearize_chk_done;+/* try the simple math, if we have too many frags per segment */+if(DIV_ROUND_UP((num_frags+gso_segs),gso_segs)>+I40E_MAX_BUFFER_TXD){+linearize=true;+gotolinearize_chk_done;+}+frag=&skb_shinfo(skb)->frags[0];+size=hdr_len;+/* we might still have more fragments per segment */+do{+size+=skb_frag_size(frag);+frag++;j++;+if(j==I40E_MAX_BUFFER_TXD){+if(size<skb_shinfo(skb)->gso_size){+linearize=true;+break;+}+j=1;+size-=skb_shinfo(skb)->gso_size;+if(size)+j++;+size+=hdr_len;+}+num_frags--;+}while(num_frags);+}else{+if(num_frags>=I40E_MAX_BUFFER_TXD)+linearize=true;+}++linearize_chk_done:+returnlinearize;+}++/***i40e_tx_map-BuildtheTxdescriptor*@tx_ring:ringtosendbufferon*@skb:sendbuffer
@@ -1380,6 +1380,67 @@ static void i40e_create_tx_ctx(struct i40e_ring *tx_ring,context_desc->type_cmd_tso_mss=cpu_to_le64(cd_type_cmd_tso_mss);}+/**+*i40e_chk_linearize-Checkiftherearemorethan8fragmentsperpacket+*@skb:sendbuffer+*@tx_flags:collectedsendinformation+*@hdr_len:sizeofthepacketheader+*+*Note:OurHWcan'tscatter-gathermorethan8fragmentstobuild+*apacketonthewireandsoweneedtofigureoutthecaseswherewe+*needtolinearizetheskb.+**/+staticbooli40e_chk_linearize(structsk_buff*skb,u32tx_flags,+constu8hdr_len)+{+structskb_frag_struct*frag;+boollinearize=false;+unsignedintsize=0;+u16num_frags;+u16gso_segs;++num_frags=skb_shinfo(skb)->nr_frags;+gso_segs=skb_shinfo(skb)->gso_segs;++if(tx_flags&(I40E_TX_FLAGS_TSO|I40E_TX_FLAGS_FSO)){+u16j=1;++if(num_frags<(I40E_MAX_BUFFER_TXD))+gotolinearize_chk_done;+/* try the simple math, if we have too many frags per segment */+if(DIV_ROUND_UP((num_frags+gso_segs),gso_segs)>+I40E_MAX_BUFFER_TXD){+linearize=true;+gotolinearize_chk_done;+}+frag=&skb_shinfo(skb)->frags[0];+size=hdr_len;+/* we might still have more fragments per segment */+do{+size+=skb_frag_size(frag);+frag++;j++;+if(j==I40E_MAX_BUFFER_TXD){+if(size<skb_shinfo(skb)->gso_size){+linearize=true;+break;+}+j=1;+size-=skb_shinfo(skb)->gso_size;+if(size)+j++;+size+=hdr_len;+}+num_frags--;+}while(num_frags);+}else{+if(num_frags>=I40E_MAX_BUFFER_TXD)+linearize=true;+}++linearize_chk_done:+returnlinearize;+}+/***i40e_tx_map-BuildtheTxdescriptor*@tx_ring:ringtosendbufferon
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:56
From: Anjali Singhai <redacted>
When the driver or hardware gets less interrupt vectors than the actual
number of CPU cores, limit the queue count for the priority queue
traffic class (TC) queues.
This will fix a warning with multiple function mode where systems
regularly have more cores than vectors.
Also add extra comment for readability.
Change-ID: I4f02226263aa3995e1f5ee5503eac0cd6ee12fbd
Signed-off-by: Anjali Singhai Jain <redacted>
Tested-by: Jim Young <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
@@ -1512,7 +1512,12 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,vsi->tc_config.numtc=numtc;vsi->tc_config.enabled_tc=enabled_tc?enabled_tc:1;/* Number of queues per enabled TC */-num_tc_qps=vsi->alloc_queue_pairs/numtc;+/* In MFP case we can have a much lower count of MSIx+*vectorsavailableandsoweneedtolowertheused+*qcount.+*/+qcount=min_t(int,vsi->alloc_queue_pairs,pf->num_lan_msix);+num_tc_qps=qcount/numtc;num_tc_qps=min_t(int,num_tc_qps,I40E_MAX_QUEUES_PER_TC);/* Setup queue offset/count for all TCs for given VSI */
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:57
From: Anjali Singhai <redacted>
We were checking the outer Protocol flags and deciding the flow for
inner header. This patch fixes that.
This fixes the Tx checksum offload for TCP/IPv6 over vxlan.
Change-ID: I837aaea921d34f71b24c2bc32aaadea5001ddf78
Signed-off-by: Anjali Singhai Jain <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:57
From: "Parikh, Neerav" <redacted>
When DCB is reconfigured to single TC the driver did not reset the
Tx ring Qset handle to the correct mapping; which caused Tx queue
disable timeouts.
Change-ID: I4da5915ec92a83c281b478d653fae6ef1b72edfe
Signed-off-by: Neerav Parikh <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:57
From: "Parikh, Neerav" <redacted>
As part of DCB reconfiguration flow if the Tx queue disable times out
then issue a PF reset to do some level of recovery.
Change-ID: I7550021c55bff355351c0365e61e1f05fcaff46d
Signed-off-by: Neerav Parikh <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
@@ -5266,8 +5266,14 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,/* Wait for the PF's Tx queues to be disabled */ret=i40e_pf_wait_txq_disabled(pf);-if(!ret)+if(ret){+/* Schedule PF reset to recover */+set_bit(__I40E_PF_RESET_REQUESTED,&pf->state);+i40e_service_event_schedule(pf);+}else{i40e_pf_unquiesce_all_vsi(pf);+}+exit:returnret;}
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:58
From: Mitch A Williams <redacted>
In some cases, the hardware would continue to try to access the FDIR
ring after entering D3Hot state, which would cause either PCIe errors or
NMIs, depending upon system configuration.
Explicitly stop FDIR in our shutdown routine to eliminate this
possibility.
Change-ID: I1bd9fc7fd8f151fe24cad132ac9adddab923e3af
Signed-off-by: Mitch Williams <redacted>
Tested-by: Jim Young <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 1 +
1 file changed, 1 insertion(+)
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:58
From: Shannon Nelson <redacted>
In some circumstances, a multi-write transaction takes longer than the
default 3 minute timeout on the write semaphore. If the write failed with
an EBUSY status, this is likely the problem, so here we try to reacquire
the semaphore then retry the write. We only do one retry, then give up.
Change-ID: I1c8be60688acc2f39573839579baf601207c4a36
Signed-off-by: Shannon Nelson <redacted>
Tested-by: Jim Young <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_nvm.c | 35 ++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:58
From: Shannon Nelson <redacted>
Combine the ICR0 shutdown with the standard interrupt shutdown, and
add the interrupt clearing to the PCI shutdown path.
This prevents the driver from allowing stray interrupts or causing
system logs from un-handled interrupts.
Change-ID: I48f6ab95cad7f8ca77c1f26c92a51cc1034ced43
Signed-off-by: Shannon Nelson <redacted>
Tested-by: Jim Young <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:59
From: Alexey Khoroshilov <redacted>
The patch fixes a leak of 'cmd_buf' when copy_from_user() failed
in i40e_dbg_command_write().
Found by Linux Driver Verification project (linuxtesting.org).
Signed-off-by: Alexey Khoroshilov <redacted>
Tested-by: Jim Young <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:03:59
From: Shannon Nelson <redacted>
Make sure we don't try to dereference NULL pointers when returning values
from the AdminQ calls.
Change-ID: Ia6694f2f415d50acf0aba063c863568742799aff
Signed-off-by: Shannon Nelson <redacted>
Tested-by: Jim Young <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_common.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:04:00
From: Shannon Nelson <redacted>
Add parens to make sure the shift and bitwise precedences don't work backwards
for us.
Change-ID: I60c10ef4fad6bc654522b9d8a53da2e270a0f268
Reported-by: Joe Perches <joe@perches.com>
Signed-off-by: Shannon Nelson <redacted>
Tested-by: Jim Young <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_common.c | 5 +++--
drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:04:00
From: Jesse Brandeburg <redacted>
The driver was having some issues with false Tx hang detection. This
makes the driver a little more direct with the checks for progress
forward by directly checking the head write back address and tail register
when determining progress. This avoids Tx hangs where the software
gets behind, because we are directly checking hardware state when
determining hang state.
Change-ID: I774f0e861c9e8ab5ccb213634100fe15440ae24a
Signed-off-by: Jesse Brandeburg <redacted>
Tested-by: Jim Young <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 54 +++++++++++++++------------
drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 54 +++++++++++++++------------
2 files changed, 60 insertions(+), 48 deletions(-)
@@ -623,41 +645,25 @@ static bool i40e_check_tx_hang(struct i40e_ring *tx_ring)*runthecheck_tx_hanglogicwithatransmitcompletion*pendingbutwithouttimetocompleteityet.*/-if((tx_ring->tx_stats.tx_done_old==tx_ring->stats.packets)&&-(tx_pending>=I40E_MIN_DESC_PENDING)){+if((tx_done_old==tx_done)&&tx_pending){/* make sure it is true for two checks in a row */ret=test_and_set_bit(__I40E_HANG_CHECK_ARMED,&tx_ring->state);-}elseif((tx_ring->tx_stats.tx_done_old==tx_ring->stats.packets)&&-(tx_pending<I40E_MIN_DESC_PENDING)&&-(tx_pending>0)){+}elseif(tx_done_old==tx_done&&+(tx_pending<I40E_MIN_DESC_PENDING)&&(tx_pending>0)){if(I40E_DEBUG_FLOW&pf->hw.debug_mask)dev_info(tx_ring->dev,"HW needs some more descs to do a cacheline flush. tx_pending %d, queue %d",tx_pending,tx_ring->queue_index);pf->tx_sluggish_count++;}else{/* update completed stats and disarm the hang check */-tx_ring->tx_stats.tx_done_old=tx_ring->stats.packets;+tx_ring->tx_stats.tx_done_old=tx_done;clear_bit(__I40E_HANG_CHECK_ARMED,&tx_ring->state);}returnret;}-/**-*i40e_get_head-Retrieveheadfromheadwriteback-*@tx_ring:txringtofetchheadof-*-*ReturnsvalueofTxringheadbasedonvaluestored-*inheadwrite-backlocation-**/-staticinlineu32i40e_get_head(structi40e_ring*tx_ring)-{-void*head=(structi40e_tx_desc*)tx_ring->desc+tx_ring->count;--returnle32_to_cpu(*(volatile__le32*)head);-}-#define WB_STRIDE 0x3/**
@@ -162,36 +184,20 @@ static bool i40e_check_tx_hang(struct i40e_ring *tx_ring)*runthecheck_tx_hanglogicwithatransmitcompletion*pendingbutwithouttimetocompleteityet.*/-if((tx_ring->tx_stats.tx_done_old==tx_ring->stats.packets)&&-(tx_pending>=I40E_MIN_DESC_PENDING)){+if((tx_done_old==tx_done)&&tx_pending){/* make sure it is true for two checks in a row */ret=test_and_set_bit(__I40E_HANG_CHECK_ARMED,&tx_ring->state);-}elseif(!(tx_ring->tx_stats.tx_done_old==tx_ring->stats.packets)||-!(tx_pending<I40E_MIN_DESC_PENDING)||-!(tx_pending>0)){+}elseif(tx_done_old==tx_done&&+(tx_pending<I40E_MIN_DESC_PENDING)&&(tx_pending>0)){/* update completed stats and disarm the hang check */-tx_ring->tx_stats.tx_done_old=tx_ring->stats.packets;+tx_ring->tx_stats.tx_done_old=tx_done;clear_bit(__I40E_HANG_CHECK_ARMED,&tx_ring->state);}returnret;}-/**-*i40e_get_head-Retrieveheadfromheadwriteback-*@tx_ring:txringtofetchheadof-*-*ReturnsvalueofTxringheadbasedonvaluestored-*inheadwrite-backlocation-**/-staticinlineu32i40e_get_head(structi40e_ring*tx_ring)-{-void*head=(structi40e_tx_desc*)tx_ring->desc+tx_ring->count;--returnle32_to_cpu(*(volatile__le32*)head);-}-#define WB_STRIDE 0x3/**
From: Jeff Kirsher <hidden> Date: 2015-02-26 15:04:00
From: Akeem G Abodunrin <redacted>
This patch adds check to bail out if device is already down when checking
for Tx hang subtask.
Change-ID: I3853fb7a6d11cb9a4c349b687cb25c15b19977a0
Signed-off-by: Akeem G Abodunrin <redacted>
Tested-by: Jim Young <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
@@ -5587,7 +5587,8 @@ static void i40e_check_hang_subtask(struct i40e_pf *pf)inti,v;/* If we're down or resetting, just bail */-if(test_bit(__I40E_CONFIG_BUSY,&pf->state))+if(test_bit(__I40E_DOWN,&pf->state)||+test_bit(__I40E_CONFIG_BUSY,&pf->state))return;/* for each VSI/netdev