]>
Commit | Line | Data |
---|---|---|
b91494dd GKH |
1 | From 5a0cdbfd17b90a89c64a71d8aec9773ecdb20d0d Mon Sep 17 00:00:00 2001 |
2 | From: Gavin Shan <gwshan@linux.vnet.ibm.com> | |
3 | Date: Wed, 27 Apr 2016 11:14:51 +1000 | |
4 | Subject: powerpc/eeh: Restore initial state in eeh_pe_reset_and_recover() | |
5 | ||
6 | From: Gavin Shan <gwshan@linux.vnet.ibm.com> | |
7 | ||
8 | commit 5a0cdbfd17b90a89c64a71d8aec9773ecdb20d0d upstream. | |
9 | ||
10 | The function eeh_pe_reset_and_recover() is used to recover EEH | |
11 | error when the passthrou device are transferred to guest and | |
12 | backwards. The content in the device's config space will be lost | |
13 | on PE reset issued in the middle of the recovery. The function | |
14 | saves/restores it before/after the reset. However, config access | |
15 | to some adapters like Broadcom BCM5719 at this point will causes | |
16 | fenced PHB. The config space is always blocked and we save 0xFF's | |
17 | that are restored at late point. The memory BARs are totally | |
18 | corrupted, causing another EEH error upon access to one of the | |
19 | memory BARs. | |
20 | ||
21 | This restores the config space on those adapters like BCM5719 | |
22 | from the content saved to the EEH device when it's populated, | |
23 | to resolve above issue. | |
24 | ||
25 | Fixes: 5cfb20b9 ("powerpc/eeh: Emulate EEH recovery for VFIO devices") | |
26 | Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> | |
27 | Reviewed-by: Russell Currey <ruscur@russell.cc> | |
28 | Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> | |
29 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
30 | ||
31 | --- | |
32 | arch/powerpc/kernel/eeh_driver.c | 23 +++++++++++++++++++++++ | |
33 | 1 file changed, 23 insertions(+) | |
34 | ||
35 | --- a/arch/powerpc/kernel/eeh_driver.c | |
36 | +++ b/arch/powerpc/kernel/eeh_driver.c | |
37 | @@ -166,6 +166,16 @@ static void *eeh_dev_save_state(void *da | |
38 | if (!edev) | |
39 | return NULL; | |
40 | ||
41 | + /* | |
42 | + * We cannot access the config space on some adapters. | |
43 | + * Otherwise, it will cause fenced PHB. We don't save | |
44 | + * the content in their config space and will restore | |
45 | + * from the initial config space saved when the EEH | |
46 | + * device is created. | |
47 | + */ | |
48 | + if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) | |
49 | + return NULL; | |
50 | + | |
51 | pdev = eeh_dev_to_pci_dev(edev); | |
52 | if (!pdev) | |
53 | return NULL; | |
54 | @@ -305,6 +315,19 @@ static void *eeh_dev_restore_state(void | |
55 | if (!edev) | |
56 | return NULL; | |
57 | ||
58 | + /* | |
59 | + * The content in the config space isn't saved because | |
60 | + * the blocked config space on some adapters. We have | |
61 | + * to restore the initial saved config space when the | |
62 | + * EEH device is created. | |
63 | + */ | |
64 | + if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) { | |
65 | + if (list_is_last(&edev->list, &edev->pe->edevs)) | |
66 | + eeh_pe_restore_bars(edev->pe); | |
67 | + | |
68 | + return NULL; | |
69 | + } | |
70 | + | |
71 | pdev = eeh_dev_to_pci_dev(edev); | |
72 | if (!pdev) | |
73 | return NULL; |