Commit b87b9cf4 authored by Sam Bobroff's avatar Sam Bobroff Committed by Michael Ellerman

powerpc/pseries: fix EEH recovery of some IOV devices

EEH recovery currently fails on pSeries for some IOV capable PCI
devices, if CONFIG_PCI_IOV is on and the hypervisor doesn't provide
certain device tree properties for the device. (Found on an IOV
capable device using the ipr driver.)

Recovery fails in pci_enable_resources() at the check on r->parent,
because r->flags is set and r->parent is not.  This state is due to
sriov_init() setting the start, end and flags members of the IOV BARs
but the parent not being set later in
pseries_pci_fixup_iov_resources(), because the
"ibm,open-sriov-vf-bar-info" property is missing.

Correct this by zeroing the resource flags for IOV BARs when they
can't be configured (this is the same method used by sriov_init() and
__pci_read_base()).

VFs cleared this way can't be enabled later, because that requires
another device tree property, "ibm,number-of-configurable-vfs" as well
as support for the RTAS function "ibm_map_pes". These are all part of
hypervisor support for IOV and it seems unlikely that a hypervisor
would ever partially, but not fully, support it. (None are currently
provided by QEMU/KVM.)
Signed-off-by: default avatarSam Bobroff <sbobroff@linux.ibm.com>
Reviewed-by: default avatarBryant G. Ly <bryantly@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent e0da9912
...@@ -647,6 +647,15 @@ void of_pci_parse_iov_addrs(struct pci_dev *dev, const int *indexes) ...@@ -647,6 +647,15 @@ void of_pci_parse_iov_addrs(struct pci_dev *dev, const int *indexes)
} }
} }
static void pseries_disable_sriov_resources(struct pci_dev *pdev)
{
int i;
pci_warn(pdev, "No hypervisor support for SR-IOV on this device, IOV BARs disabled.\n");
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++)
pdev->resource[i + PCI_IOV_RESOURCES].flags = 0;
}
static void pseries_pci_fixup_resources(struct pci_dev *pdev) static void pseries_pci_fixup_resources(struct pci_dev *pdev)
{ {
const int *indexes; const int *indexes;
...@@ -654,10 +663,10 @@ static void pseries_pci_fixup_resources(struct pci_dev *pdev) ...@@ -654,10 +663,10 @@ static void pseries_pci_fixup_resources(struct pci_dev *pdev)
/*Firmware must support open sriov otherwise dont configure*/ /*Firmware must support open sriov otherwise dont configure*/
indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL); indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL);
if (!indexes) if (indexes)
return; of_pci_set_vf_bar_size(pdev, indexes);
/* Assign the addresses from device tree*/ else
of_pci_set_vf_bar_size(pdev, indexes); pseries_disable_sriov_resources(pdev);
} }
static void pseries_pci_fixup_iov_resources(struct pci_dev *pdev) static void pseries_pci_fixup_iov_resources(struct pci_dev *pdev)
...@@ -669,10 +678,10 @@ static void pseries_pci_fixup_iov_resources(struct pci_dev *pdev) ...@@ -669,10 +678,10 @@ static void pseries_pci_fixup_iov_resources(struct pci_dev *pdev)
return; return;
/*Firmware must support open sriov otherwise dont configure*/ /*Firmware must support open sriov otherwise dont configure*/
indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL); indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL);
if (!indexes) if (indexes)
return; of_pci_parse_iov_addrs(pdev, indexes);
/* Assign the addresses from device tree*/ else
of_pci_parse_iov_addrs(pdev, indexes); pseries_disable_sriov_resources(pdev);
} }
static resource_size_t pseries_pci_iov_resource_alignment(struct pci_dev *pdev, static resource_size_t pseries_pci_iov_resource_alignment(struct pci_dev *pdev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment