.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Support PCI/PCIe on PowerNV platforms |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright 2011 Benjamin Herrenschmidt, IBM Corp. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or |
---|
7 | | - * modify it under the terms of the GNU General Public License |
---|
8 | | - * as published by the Free Software Foundation; either version |
---|
9 | | - * 2 of the License, or (at your option) any later version. |
---|
10 | 6 | */ |
---|
11 | 7 | |
---|
12 | 8 | #include <linux/kernel.h> |
---|
.. | .. |
---|
38 | 34 | #include "powernv.h" |
---|
39 | 35 | #include "pci.h" |
---|
40 | 36 | |
---|
41 | | -static DEFINE_MUTEX(p2p_mutex); |
---|
42 | 37 | static DEFINE_MUTEX(tunnel_mutex); |
---|
43 | 38 | |
---|
44 | 39 | int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id) |
---|
45 | 40 | { |
---|
46 | | - struct device_node *parent = np; |
---|
| 41 | + struct device_node *node = np; |
---|
47 | 42 | u32 bdfn; |
---|
48 | 43 | u64 phbid; |
---|
49 | 44 | int ret; |
---|
.. | .. |
---|
53 | 48 | return -ENXIO; |
---|
54 | 49 | |
---|
55 | 50 | bdfn = ((bdfn & 0x00ffff00) >> 8); |
---|
56 | | - while ((parent = of_get_parent(parent))) { |
---|
57 | | - if (!PCI_DN(parent)) { |
---|
58 | | - of_node_put(parent); |
---|
| 51 | + for (node = np; node; node = of_get_parent(node)) { |
---|
| 52 | + if (!PCI_DN(node)) { |
---|
| 53 | + of_node_put(node); |
---|
59 | 54 | break; |
---|
60 | 55 | } |
---|
61 | 56 | |
---|
62 | | - if (!of_device_is_compatible(parent, "ibm,ioda2-phb")) { |
---|
63 | | - of_node_put(parent); |
---|
| 57 | + if (!of_device_is_compatible(node, "ibm,ioda2-phb") && |
---|
| 58 | + !of_device_is_compatible(node, "ibm,ioda3-phb") && |
---|
| 59 | + !of_device_is_compatible(node, "ibm,ioda2-npu2-opencapi-phb")) { |
---|
| 60 | + of_node_put(node); |
---|
64 | 61 | continue; |
---|
65 | 62 | } |
---|
66 | 63 | |
---|
67 | | - ret = of_property_read_u64(parent, "ibm,opal-phbid", &phbid); |
---|
| 64 | + ret = of_property_read_u64(node, "ibm,opal-phbid", &phbid); |
---|
68 | 65 | if (ret) { |
---|
69 | | - of_node_put(parent); |
---|
| 66 | + of_node_put(node); |
---|
70 | 67 | return -ENXIO; |
---|
71 | 68 | } |
---|
72 | 69 | |
---|
73 | | - *id = PCI_SLOT_ID(phbid, bdfn); |
---|
| 70 | + if (of_device_is_compatible(node, "ibm,ioda2-npu2-opencapi-phb")) |
---|
| 71 | + *id = PCI_PHB_SLOT_ID(phbid); |
---|
| 72 | + else |
---|
| 73 | + *id = PCI_SLOT_ID(phbid, bdfn); |
---|
74 | 74 | return 0; |
---|
75 | 75 | } |
---|
76 | 76 | |
---|
.. | .. |
---|
160 | 160 | } |
---|
161 | 161 | EXPORT_SYMBOL_GPL(pnv_pci_set_power_state); |
---|
162 | 162 | |
---|
163 | | -#ifdef CONFIG_PCI_MSI |
---|
164 | 163 | int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) |
---|
165 | 164 | { |
---|
166 | | - struct pci_controller *hose = pci_bus_to_host(pdev->bus); |
---|
167 | | - struct pnv_phb *phb = hose->private_data; |
---|
| 165 | + struct pnv_phb *phb = pci_bus_to_pnvhb(pdev->bus); |
---|
168 | 166 | struct msi_desc *entry; |
---|
169 | 167 | struct msi_msg msg; |
---|
170 | 168 | int hwirq; |
---|
.. | .. |
---|
212 | 210 | |
---|
213 | 211 | void pnv_teardown_msi_irqs(struct pci_dev *pdev) |
---|
214 | 212 | { |
---|
215 | | - struct pci_controller *hose = pci_bus_to_host(pdev->bus); |
---|
216 | | - struct pnv_phb *phb = hose->private_data; |
---|
| 213 | + struct pnv_phb *phb = pci_bus_to_pnvhb(pdev->bus); |
---|
217 | 214 | struct msi_desc *entry; |
---|
218 | 215 | irq_hw_number_t hwirq; |
---|
219 | 216 | |
---|
.. | .. |
---|
229 | 226 | msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, 1); |
---|
230 | 227 | } |
---|
231 | 228 | } |
---|
232 | | -#endif /* CONFIG_PCI_MSI */ |
---|
233 | 229 | |
---|
234 | 230 | /* Nicely print the contents of the PE State Tables (PEST). */ |
---|
235 | 231 | static void pnv_pci_dump_pest(__be64 pestA[], __be64 pestB[], int pest_size) |
---|
.. | .. |
---|
816 | 812 | return tbl; |
---|
817 | 813 | } |
---|
818 | 814 | |
---|
819 | | -void pnv_pci_dma_dev_setup(struct pci_dev *pdev) |
---|
820 | | -{ |
---|
821 | | - struct pci_controller *hose = pci_bus_to_host(pdev->bus); |
---|
822 | | - struct pnv_phb *phb = hose->private_data; |
---|
823 | | - |
---|
824 | | - if (phb && phb->dma_dev_setup) |
---|
825 | | - phb->dma_dev_setup(phb, pdev); |
---|
826 | | -} |
---|
827 | | - |
---|
828 | | -void pnv_pci_dma_bus_setup(struct pci_bus *bus) |
---|
829 | | -{ |
---|
830 | | - struct pci_controller *hose = bus->sysdata; |
---|
831 | | - struct pnv_phb *phb = hose->private_data; |
---|
832 | | - struct pnv_ioda_pe *pe; |
---|
833 | | - |
---|
834 | | - list_for_each_entry(pe, &phb->ioda.pe_list, list) { |
---|
835 | | - if (!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL))) |
---|
836 | | - continue; |
---|
837 | | - |
---|
838 | | - if (!pe->pbus) |
---|
839 | | - continue; |
---|
840 | | - |
---|
841 | | - if (bus->number == ((pe->rid >> 8) & 0xFF)) { |
---|
842 | | - pe->pbus = bus; |
---|
843 | | - break; |
---|
844 | | - } |
---|
845 | | - } |
---|
846 | | -} |
---|
847 | | - |
---|
848 | | -int pnv_pci_set_p2p(struct pci_dev *initiator, struct pci_dev *target, u64 desc) |
---|
849 | | -{ |
---|
850 | | - struct pci_controller *hose; |
---|
851 | | - struct pnv_phb *phb_init, *phb_target; |
---|
852 | | - struct pnv_ioda_pe *pe_init; |
---|
853 | | - int rc; |
---|
854 | | - |
---|
855 | | - if (!opal_check_token(OPAL_PCI_SET_P2P)) |
---|
856 | | - return -ENXIO; |
---|
857 | | - |
---|
858 | | - hose = pci_bus_to_host(initiator->bus); |
---|
859 | | - phb_init = hose->private_data; |
---|
860 | | - |
---|
861 | | - hose = pci_bus_to_host(target->bus); |
---|
862 | | - phb_target = hose->private_data; |
---|
863 | | - |
---|
864 | | - pe_init = pnv_ioda_get_pe(initiator); |
---|
865 | | - if (!pe_init) |
---|
866 | | - return -ENODEV; |
---|
867 | | - |
---|
868 | | - /* |
---|
869 | | - * Configuring the initiator's PHB requires to adjust its |
---|
870 | | - * TVE#1 setting. Since the same device can be an initiator |
---|
871 | | - * several times for different target devices, we need to keep |
---|
872 | | - * a reference count to know when we can restore the default |
---|
873 | | - * bypass setting on its TVE#1 when disabling. Opal is not |
---|
874 | | - * tracking PE states, so we add a reference count on the PE |
---|
875 | | - * in linux. |
---|
876 | | - * |
---|
877 | | - * For the target, the configuration is per PHB, so we keep a |
---|
878 | | - * target reference count on the PHB. |
---|
879 | | - */ |
---|
880 | | - mutex_lock(&p2p_mutex); |
---|
881 | | - |
---|
882 | | - if (desc & OPAL_PCI_P2P_ENABLE) { |
---|
883 | | - /* always go to opal to validate the configuration */ |
---|
884 | | - rc = opal_pci_set_p2p(phb_init->opal_id, phb_target->opal_id, |
---|
885 | | - desc, pe_init->pe_number); |
---|
886 | | - |
---|
887 | | - if (rc != OPAL_SUCCESS) { |
---|
888 | | - rc = -EIO; |
---|
889 | | - goto out; |
---|
890 | | - } |
---|
891 | | - |
---|
892 | | - pe_init->p2p_initiator_count++; |
---|
893 | | - phb_target->p2p_target_count++; |
---|
894 | | - } else { |
---|
895 | | - if (!pe_init->p2p_initiator_count || |
---|
896 | | - !phb_target->p2p_target_count) { |
---|
897 | | - rc = -EINVAL; |
---|
898 | | - goto out; |
---|
899 | | - } |
---|
900 | | - |
---|
901 | | - if (--pe_init->p2p_initiator_count == 0) |
---|
902 | | - pnv_pci_ioda2_set_bypass(pe_init, true); |
---|
903 | | - |
---|
904 | | - if (--phb_target->p2p_target_count == 0) { |
---|
905 | | - rc = opal_pci_set_p2p(phb_init->opal_id, |
---|
906 | | - phb_target->opal_id, desc, |
---|
907 | | - pe_init->pe_number); |
---|
908 | | - if (rc != OPAL_SUCCESS) { |
---|
909 | | - rc = -EIO; |
---|
910 | | - goto out; |
---|
911 | | - } |
---|
912 | | - } |
---|
913 | | - } |
---|
914 | | - rc = 0; |
---|
915 | | -out: |
---|
916 | | - mutex_unlock(&p2p_mutex); |
---|
917 | | - return rc; |
---|
918 | | -} |
---|
919 | | -EXPORT_SYMBOL_GPL(pnv_pci_set_p2p); |
---|
920 | | - |
---|
921 | 815 | struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev) |
---|
922 | 816 | { |
---|
923 | 817 | struct pci_controller *hose = pci_bus_to_host(dev->bus); |
---|
.. | .. |
---|
926 | 820 | } |
---|
927 | 821 | EXPORT_SYMBOL(pnv_pci_get_phb_node); |
---|
928 | 822 | |
---|
929 | | -int pnv_pci_enable_tunnel(struct pci_dev *dev, u64 *asnind) |
---|
930 | | -{ |
---|
931 | | - struct device_node *np; |
---|
932 | | - const __be32 *prop; |
---|
933 | | - struct pnv_ioda_pe *pe; |
---|
934 | | - uint16_t window_id; |
---|
935 | | - int rc; |
---|
936 | | - |
---|
937 | | - if (!radix_enabled()) |
---|
938 | | - return -ENXIO; |
---|
939 | | - |
---|
940 | | - if (!(np = pnv_pci_get_phb_node(dev))) |
---|
941 | | - return -ENXIO; |
---|
942 | | - |
---|
943 | | - prop = of_get_property(np, "ibm,phb-indications", NULL); |
---|
944 | | - of_node_put(np); |
---|
945 | | - |
---|
946 | | - if (!prop || !prop[1]) |
---|
947 | | - return -ENXIO; |
---|
948 | | - |
---|
949 | | - *asnind = (u64)be32_to_cpu(prop[1]); |
---|
950 | | - pe = pnv_ioda_get_pe(dev); |
---|
951 | | - if (!pe) |
---|
952 | | - return -ENODEV; |
---|
953 | | - |
---|
954 | | - /* Increase real window size to accept as_notify messages. */ |
---|
955 | | - window_id = (pe->pe_number << 1 ) + 1; |
---|
956 | | - rc = opal_pci_map_pe_dma_window_real(pe->phb->opal_id, pe->pe_number, |
---|
957 | | - window_id, pe->tce_bypass_base, |
---|
958 | | - (uint64_t)1 << 48); |
---|
959 | | - return opal_error_code(rc); |
---|
960 | | -} |
---|
961 | | -EXPORT_SYMBOL_GPL(pnv_pci_enable_tunnel); |
---|
962 | | - |
---|
963 | | -int pnv_pci_disable_tunnel(struct pci_dev *dev) |
---|
964 | | -{ |
---|
965 | | - struct pnv_ioda_pe *pe; |
---|
966 | | - |
---|
967 | | - pe = pnv_ioda_get_pe(dev); |
---|
968 | | - if (!pe) |
---|
969 | | - return -ENODEV; |
---|
970 | | - |
---|
971 | | - /* Restore default real window size. */ |
---|
972 | | - pnv_pci_ioda2_set_bypass(pe, true); |
---|
973 | | - return 0; |
---|
974 | | -} |
---|
975 | | -EXPORT_SYMBOL_GPL(pnv_pci_disable_tunnel); |
---|
976 | | - |
---|
977 | 823 | int pnv_pci_set_tunnel_bar(struct pci_dev *dev, u64 addr, int enable) |
---|
978 | 824 | { |
---|
979 | | - __be64 val; |
---|
980 | | - struct pci_controller *hose; |
---|
981 | | - struct pnv_phb *phb; |
---|
| 825 | + struct pnv_phb *phb = pci_bus_to_pnvhb(dev->bus); |
---|
982 | 826 | u64 tunnel_bar; |
---|
| 827 | + __be64 val; |
---|
983 | 828 | int rc; |
---|
984 | 829 | |
---|
985 | 830 | if (!opal_check_token(OPAL_PCI_GET_PBCQ_TUNNEL_BAR)) |
---|
986 | 831 | return -ENXIO; |
---|
987 | 832 | if (!opal_check_token(OPAL_PCI_SET_PBCQ_TUNNEL_BAR)) |
---|
988 | 833 | return -ENXIO; |
---|
989 | | - |
---|
990 | | - hose = pci_bus_to_host(dev->bus); |
---|
991 | | - phb = hose->private_data; |
---|
992 | 834 | |
---|
993 | 835 | mutex_lock(&tunnel_mutex); |
---|
994 | 836 | rc = opal_pci_get_pbcq_tunnel_bar(phb->opal_id, &val); |
---|
.. | .. |
---|
1027 | 869 | return rc; |
---|
1028 | 870 | } |
---|
1029 | 871 | EXPORT_SYMBOL_GPL(pnv_pci_set_tunnel_bar); |
---|
1030 | | - |
---|
1031 | | -#ifdef CONFIG_PPC64 /* for thread.tidr */ |
---|
1032 | | -int pnv_pci_get_as_notify_info(struct task_struct *task, u32 *lpid, u32 *pid, |
---|
1033 | | - u32 *tid) |
---|
1034 | | -{ |
---|
1035 | | - struct mm_struct *mm = NULL; |
---|
1036 | | - |
---|
1037 | | - if (task == NULL) |
---|
1038 | | - return -EINVAL; |
---|
1039 | | - |
---|
1040 | | - mm = get_task_mm(task); |
---|
1041 | | - if (mm == NULL) |
---|
1042 | | - return -EINVAL; |
---|
1043 | | - |
---|
1044 | | - *pid = mm->context.id; |
---|
1045 | | - mmput(mm); |
---|
1046 | | - |
---|
1047 | | - *tid = task->thread.tidr; |
---|
1048 | | - *lpid = mfspr(SPRN_LPID); |
---|
1049 | | - return 0; |
---|
1050 | | -} |
---|
1051 | | -EXPORT_SYMBOL_GPL(pnv_pci_get_as_notify_info); |
---|
1052 | | -#endif |
---|
1053 | 872 | |
---|
1054 | 873 | void pnv_pci_shutdown(void) |
---|
1055 | 874 | { |
---|
.. | .. |
---|
1126 | 945 | set_pci_dma_ops(&dma_iommu_ops); |
---|
1127 | 946 | } |
---|
1128 | 947 | |
---|
1129 | | -machine_subsys_initcall_sync(powernv, tce_iommu_bus_notifier_init); |
---|
| 948 | +static int pnv_tce_iommu_bus_notifier(struct notifier_block *nb, |
---|
| 949 | + unsigned long action, void *data) |
---|
| 950 | +{ |
---|
| 951 | + struct device *dev = data; |
---|
| 952 | + |
---|
| 953 | + switch (action) { |
---|
| 954 | + case BUS_NOTIFY_DEL_DEVICE: |
---|
| 955 | + iommu_del_device(dev); |
---|
| 956 | + return 0; |
---|
| 957 | + default: |
---|
| 958 | + return 0; |
---|
| 959 | + } |
---|
| 960 | +} |
---|
| 961 | + |
---|
| 962 | +static struct notifier_block pnv_tce_iommu_bus_nb = { |
---|
| 963 | + .notifier_call = pnv_tce_iommu_bus_notifier, |
---|
| 964 | +}; |
---|
| 965 | + |
---|
| 966 | +static int __init pnv_tce_iommu_bus_notifier_init(void) |
---|
| 967 | +{ |
---|
| 968 | + bus_register_notifier(&pci_bus_type, &pnv_tce_iommu_bus_nb); |
---|
| 969 | + return 0; |
---|
| 970 | +} |
---|
| 971 | +machine_subsys_initcall_sync(powernv, pnv_tce_iommu_bus_notifier_init); |
---|