clear-pkgs-linux-iot-lts2018/0858-igb_avb-Fix-invalid-me...

196 lines
7.8 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Date: Thu, 10 Jan 2019 16:18:59 -0800
Subject: [PATCH] igb_avb: Fix invalid memory access after S3 suspend/resume
cycles
Manually (igb_avb is based on the stable igb driver, so applying the
patches from upstream was resulting in a lot of conflicts) backport
the following patches:
commit 89dbefb213a0b3e53fe1a99ec9c1a230aad5f404
From: Aaron Sierra <asierra@xes-inc.com>
Date: Thu, 31 Oct 2013 00:32:34 +0000
commit 75009b3a88cd8f56315eb4ced296ee2f060cf946
From: Peter Senna Tschudin <peter.senna@gmail.com>
Date: Thu, 20 Mar 2014 03:31:08 +0000
commit 73bf8048d7c86a20a59d427e55deb1a778e94df7
From: Jarod Wilson <jarod@redhat.com>
Date: Thu, 10 Sep 2015 15:37:50 -0400
commit 7b06a6909555ffb0140733cc4420222604140b27
From: Jarod Wilson <jarod@redhat.com>
Date: Mon, 19 Oct 2015 11:52:04 -0400
commit 629823b872402451b42462414da08dddd0e2c93d
From: Cao jin <caoj.fnst@cn.fujitsu.com>
Date: Tue, 8 Nov 2016 15:06:20 +0800
commit 69b97cf6dbce7403845a28bbc75d57f5be7b12ac
From: Guilherme G Piccoli <gpiccoli@linux.vnet.ibm.com>
Date: Thu, 10 Nov 2016 16:46:43 -0200
Also, having only one commit makes it easier to revert, if necessary.
In theory, only the last two commits were needed, but because of
changes in how PCI addresses are mapped in igb, it was best to
backport those other commits that make igb use more modern APIs when
mapping/unmapping PCI addresses.
This should fix the following crash:
[ 5271.634522] PM: Restoring platform NVS memory
[ 5271.646807] ACPI: Waking up from system sleep state S3
[ 5271.892182] intel-ipu4 0000:00:03.0: IPU in secure mode
[ 5271.893875] igb_avb 0000:02:00.0 ens4: PCIe link lost, device now detached
[ 5271.894735] [drm] HuC: Loaded firmware i915/bxt_huc_ver01_07_1398.bin (version 1.7)
[ 5271.900810] [drm] GuC: Loaded firmware i915/bxt_guc_ver9_29.bin (version 9.29)
[ 5271.906584] i915 0000:00:02.0: GuC firmware version 9.29
[ 5271.906908] i915 0000:00:02.0: GuC submission disabled
[ 5271.907204] i915 0000:00:02.0: HuC enabled
[ 5273.028933] BUG: unable to handle kernel paging request at 0000000000003818
[ 5273.032434] PGD 0 P4D 0
[ 5273.035664] Oops: 0002 [#1] PREEMPT SMP
[ 5273.038954] CPU: 0 PID: 938 Comm: kworker/u8:29 Tainted: G U WC 4.19.8-1812241100.iot-lts2018-sos #1
[ 5273.042592] Workqueue: events_unbound async_run_entry_fn
[ 5273.045932] RIP: 0010:igb_configure_tx_ring+0x13f/0x230 [igb_avb]
[ 5273.049309] Code: c2 10 38 00 00 48 98 48 01 c1 48 63 c2 49 89 4e 30 49 8b b5 58 04 00 00 48 85 f6 74 0b 48 01 f0 31 d2 89 10 49 8b 4e 30 31 c0 <89> 01 41 8b 85 6c 05 00 00 b9 14 01 04 02 83 f8 05 74 0e 83 f8 02
[ 5273.056633] RSP: 0018:ffff9d380f917cc0 EFLAGS: 00010246
[ 5273.060068] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000003818
[ 5273.063613] RDX: 0000000000003810 RSI: 0000000000000000 RDI: 00000000ffffffff
[ 5273.067080] RBP: ffff9d380f917ce8 R08: 000000000000007f R09: 000000000000007f
[ 5273.162184] R10: 0000000000005c80 R11: 0000000000000000 R12: 0000000000000000
[ 5273.165614] R13: ffff9d3a637b4940 R14: ffff9d3a5c459a40 R15: 000000027c01c000
[ 5273.169050] FS: 0000000000000000(0000) GS:ffff9d3a73a00000(0000) knlGS:0000000000000000
[ 5273.172554] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 5273.175906] CR2: 0000000000003818 CR3: 0000000003f04000 CR4: 00000000003406f0
[ 5273.179338] Call Trace:
[ 5273.182445] igb_configure+0x1ae/0x460 [igb_avb]
[ 5273.185648] __igb_open+0x7e/0x560 [igb_avb]
[ 5273.245233] igb_resume+0x10b/0x140 [igb_avb]
[ 5273.248388] pci_pm_resume+0x71/0xd0
[ 5273.254596] dpm_run_callback+0x66/0x190
[ 5273.257614] device_resume+0xc8/0x2a0
[ 5273.260570] async_resume+0x1d/0x30
[ 5273.263509] async_run_entry_fn+0x3e/0x170
Change-Id: I3c21a8cf1450e996509505a9d35bda3a4a4864d9
Tracked-on: PKT-1646
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
drivers/staging/igb_avb/igb.h | 2 ++
drivers/staging/igb_avb/igb_main.c | 25 +++++++++++++++----------
2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/staging/igb_avb/igb.h b/drivers/staging/igb_avb/igb.h
index c8bbf307f908..4482f7407955 100644
--- a/drivers/staging/igb_avb/igb.h
+++ b/drivers/staging/igb_avb/igb.h
@@ -562,6 +562,8 @@ struct igb_adapter {
u16 link_duplex;
u8 port_num;
+ u8 __iomem *io_addr; /* Mainly for iounmap use */
+
/* Interrupt Throttle Rate */
u32 rx_itr_setting;
u32 tx_itr_setting;
diff --git a/drivers/staging/igb_avb/igb_main.c b/drivers/staging/igb_avb/igb_main.c
index 8d772cfbe397..08dbf5d5a481 100644
--- a/drivers/staging/igb_avb/igb_main.c
+++ b/drivers/staging/igb_avb/igb_main.c
@@ -707,7 +707,6 @@ static void igb_configure_msix(struct igb_adapter *adapter)
static int igb_request_msix(struct igb_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- struct e1000_hw *hw = &adapter->hw;
int i, err = 0, vector = 0, free_vector = 0;
err = request_irq(adapter->msix_entries[vector].vector,
@@ -720,7 +719,7 @@ static int igb_request_msix(struct igb_adapter *adapter)
vector++;
- q_vector->itr_register = hw->hw_addr + E1000_EITR(vector);
+ q_vector->itr_register = adapter->io_addr + E1000_EITR(vector);
if (q_vector->rx.ring && q_vector->tx.ring)
sprintf(q_vector->name, "%s-TxRx-%u", netdev->name,
@@ -1198,7 +1197,7 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
q_vector->tx.work_limit = adapter->tx_work_limit;
/* initialize ITR configuration */
- q_vector->itr_register = adapter->hw.hw_addr + E1000_EITR(0);
+ q_vector->itr_register = adapter->io_addr + E1000_EITR(0);
q_vector->itr_val = IGB_START_ITR;
/* initialize pointer to rings */
@@ -2720,10 +2719,11 @@ static int igb_probe(struct pci_dev *pdev,
goto err_ioremap;
#endif
err = -EIO;
- hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (!hw->hw_addr)
+ adapter->io_addr = pci_iomap(pdev, 0, 0);
+ if (!adapter->io_addr)
goto err_ioremap;
+ /* hw->hw_addr can be altered, we'll use adapter->io_addr for unmap */
+ hw->hw_addr = adapter->io_addr;
#ifdef HAVE_NET_DEVICE_OPS
netdev->netdev_ops = &igb_netdev_ops;
@@ -3138,7 +3138,7 @@ static int igb_probe(struct pci_dev *pdev,
err_sw_init:
igb_clear_interrupt_scheme(adapter);
igb_reset_sriov_capability(adapter);
- iounmap(hw->hw_addr);
+ pci_iounmap(pdev, adapter->io_addr);
err_ioremap:
free_netdev(netdev);
err_alloc_etherdev:
@@ -3221,7 +3221,7 @@ static void igb_remove(struct pci_dev *pdev)
igb_clear_interrupt_scheme(adapter);
- iounmap(hw->hw_addr);
+ pci_iounmap(pdev, adapter->io_addr);
if (hw->flash_address)
iounmap(hw->flash_address);
pci_release_selected_regions(pdev,
@@ -3620,7 +3620,7 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
tdba & 0x00000000ffffffffULL);
E1000_WRITE_REG(hw, E1000_TDBAH(reg_idx), tdba >> 32);
- ring->tail = hw->hw_addr + E1000_TDT(reg_idx);
+ ring->tail = adapter->io_addr + E1000_TDT(reg_idx);
E1000_WRITE_REG(hw, E1000_TDH(reg_idx), 0);
writel(0, ring->tail);
@@ -4051,7 +4051,7 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
ring->count * sizeof(union e1000_adv_rx_desc));
/* initialize head and tail */
- ring->tail = hw->hw_addr + E1000_RDT(reg_idx);
+ ring->tail = adapter->io_addr + E1000_RDT(reg_idx);
E1000_WRITE_REG(hw, E1000_RDH(reg_idx), 0);
writel(0, ring->tail);
@@ -9638,6 +9638,11 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
+ /* In case of PCI error, adapter lose its HW address
+ * so we should re-assign it here.
+ */
+ hw->hw_addr = adapter->io_addr;
+
schedule_work(&adapter->reset_task);
E1000_WRITE_REG(hw, E1000_WUS, ~0);
result = PCI_ERS_RESULT_RECOVERED;
--
https://clearlinux.org