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

powerpc/powernv: Use PCI slot reset infrastructure

The (OPAL) firmware might provide the PCI slot reset capability
which is identified by property "ibm,reset-by-firmware" on the
PCI slot associated device node.

This routes the reset request to firmware if "ibm,reset-by-firmware"
exists in the PCI slot device node. Otherwise, the reset is done
inside kernel as before.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Gavin Shan and committed by
Michael Ellerman
9c0e1ecb ebe22531

+40 -1
+40 -1
arch/powerpc/platforms/powernv/eeh-powernv.c
··· 36 36 #include <asm/msi_bitmap.h> 37 37 #include <asm/opal.h> 38 38 #include <asm/ppc-pci.h> 39 + #include <asm/pnv-pci.h> 39 40 40 41 #include "powernv.h" 41 42 #include "pci.h" ··· 816 815 return 0; 817 816 } 818 817 819 - static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option) 818 + static int __pnv_eeh_bridge_reset(struct pci_dev *dev, int option) 820 819 { 821 820 struct pci_dn *pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn); 822 821 struct eeh_dev *edev = pdn_to_eeh_dev(pdn); ··· 865 864 } 866 865 867 866 return 0; 867 + } 868 + 869 + static int pnv_eeh_bridge_reset(struct pci_dev *pdev, int option) 870 + { 871 + struct pci_controller *hose = pci_bus_to_host(pdev->bus); 872 + struct pnv_phb *phb = hose->private_data; 873 + struct device_node *dn = pci_device_to_OF_node(pdev); 874 + uint64_t id = PCI_SLOT_ID(phb->opal_id, 875 + (pdev->bus->number << 8) | pdev->devfn); 876 + uint8_t scope; 877 + int64_t rc; 878 + 879 + /* Hot reset to the bus if firmware cannot handle */ 880 + if (!dn || !of_get_property(dn, "ibm,reset-by-firmware", NULL)) 881 + return __pnv_eeh_bridge_reset(pdev, option); 882 + 883 + switch (option) { 884 + case EEH_RESET_FUNDAMENTAL: 885 + scope = OPAL_RESET_PCI_FUNDAMENTAL; 886 + break; 887 + case EEH_RESET_HOT: 888 + scope = OPAL_RESET_PCI_HOT; 889 + break; 890 + case EEH_RESET_DEACTIVATE: 891 + return 0; 892 + default: 893 + dev_dbg(&pdev->dev, "%s: Unsupported reset %d\n", 894 + __func__, option); 895 + return -EINVAL; 896 + } 897 + 898 + rc = opal_pci_reset(id, scope, OPAL_ASSERT_RESET); 899 + if (rc <= OPAL_SUCCESS) 900 + goto out; 901 + 902 + rc = pnv_eeh_poll(id); 903 + out: 904 + return (rc == OPAL_SUCCESS) ? 0 : -EIO; 868 905 } 869 906 870 907 void pnv_pci_reset_secondary_bus(struct pci_dev *dev)