mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 17:08:10 +00:00
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: Sam Bobroff <sbobroff@linux.ibm.com> Reviewed-by: Bryant G. Ly <bryantly@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
e0da99123f
commit
b87b9cf493
1 changed files with 17 additions and 8 deletions
|
@ -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)
|
||||||
|
|
||||||
/*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)
|
||||||
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,
|
||||||
|
|
Loading…
Reference in a new issue