Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Sam Bobroff and committed by
Michael Ellerman
b87b9cf4 e0da9912

+17 -8
+17 -8
arch/powerpc/platforms/pseries/setup.c
··· 647 647 } 648 648 } 649 649 650 + static void pseries_disable_sriov_resources(struct pci_dev *pdev) 651 + { 652 + int i; 653 + 654 + pci_warn(pdev, "No hypervisor support for SR-IOV on this device, IOV BARs disabled.\n"); 655 + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) 656 + pdev->resource[i + PCI_IOV_RESOURCES].flags = 0; 657 + } 658 + 650 659 static void pseries_pci_fixup_resources(struct pci_dev *pdev) 651 660 { 652 661 const int *indexes; ··· 663 654 664 655 /*Firmware must support open sriov otherwise dont configure*/ 665 656 indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL); 666 - if (!indexes) 667 - return; 668 - /* Assign the addresses from device tree*/ 669 - of_pci_set_vf_bar_size(pdev, indexes); 657 + if (indexes) 658 + of_pci_set_vf_bar_size(pdev, indexes); 659 + else 660 + pseries_disable_sriov_resources(pdev); 670 661 } 671 662 672 663 static void pseries_pci_fixup_iov_resources(struct pci_dev *pdev) ··· 678 669 return; 679 670 /*Firmware must support open sriov otherwise dont configure*/ 680 671 indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL); 681 - if (!indexes) 682 - return; 683 - /* Assign the addresses from device tree*/ 684 - of_pci_parse_iov_addrs(pdev, indexes); 672 + if (indexes) 673 + of_pci_parse_iov_addrs(pdev, indexes); 674 + else 675 + pseries_disable_sriov_resources(pdev); 685 676 } 686 677 687 678 static resource_size_t pseries_pci_iov_resource_alignment(struct pci_dev *pdev,