Skip to content

Commit

Permalink
powerpc/eeh: Restore initial state in eeh_pe_reset_and_recover()
Browse files Browse the repository at this point in the history
commit 5a0cdbf upstream.

The function eeh_pe_reset_and_recover() is used to recover EEH
error when the passthrou device are transferred to guest and
backwards. The content in the device's config space will be lost
on PE reset issued in the middle of the recovery. The function
saves/restores it before/after the reset. However, config access
to some adapters like Broadcom BCM5719 at this point will causes
fenced PHB. The config space is always blocked and we save 0xFF's
that are restored at late point. The memory BARs are totally
corrupted, causing another EEH error upon access to one of the
memory BARs.

This restores the config space on those adapters like BCM5719
from the content saved to the EEH device when it's populated,
to resolve above issue.

Fixes: 5cfb20b ("powerpc/eeh: Emulate EEH recovery for VFIO devices")
Signed-off-by: Gavin Shan <[email protected]>
Reviewed-by: Russell Currey <[email protected]>
Signed-off-by: Michael Ellerman <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Gavin Shan authored and gregkh committed Jun 8, 2016
1 parent 2a86408 commit 2b3448c
Showing 1 changed file with 23 additions and 0 deletions.
23 changes: 23 additions & 0 deletions arch/powerpc/kernel/eeh_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ static void *eeh_dev_save_state(void *data, void *userdata)
if (!edev)
return NULL;

/*
* We cannot access the config space on some adapters.
* Otherwise, it will cause fenced PHB. We don't save
* the content in their config space and will restore
* from the initial config space saved when the EEH
* device is created.
*/
if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED))
return NULL;

pdev = eeh_dev_to_pci_dev(edev);
if (!pdev)
return NULL;
Expand Down Expand Up @@ -312,6 +322,19 @@ static void *eeh_dev_restore_state(void *data, void *userdata)
if (!edev)
return NULL;

/*
* The content in the config space isn't saved because
* the blocked config space on some adapters. We have
* to restore the initial saved config space when the
* EEH device is created.
*/
if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) {
if (list_is_last(&edev->list, &edev->pe->edevs))
eeh_pe_restore_bars(edev->pe);

return NULL;
}

pdev = eeh_dev_to_pci_dev(edev);
if (!pdev)
return NULL;
Expand Down

0 comments on commit 2b3448c

Please sign in to comment.