The series is split from "[PATCH v8 00/45] powerpc/powernv: PCI hotplug
support". The series does couple of things as below. The patches are
required to support PCI hotplug on PowerNV platforms. However, the
patches refactor the code with the goal: not affecting current logic.
* Code cleanup and refactoring.
* Track IO/M32/M64 segments consumed by one particular PE.
* Remove DMA32 list and improve DMA32 segment tracking.
* M64 support for IODA1 so that we have unified basis for the
subsequent patches to support PCI hotplug.
* Couple of fixes to PCI hotplug (used by EEH).
* Exported functions to be used by PCI hotplug.
Gavin Shan (26):
powerpc/pci: Cleanup on struct pci_controller_ops
powerpc/powernv: Cleanup on pci_controller_ops instances
powerpc/powernv: Drop phb->bdfn_to_pe()
powerpc/powernv: Reorder fields in struct pnv_phb
powerpc/powernv: Rename PE# fields in struct pnv_phb
powerpc/powernv: Data type unsigned int for PE number
powerpc/powernv: Fix initial IO and M32 segmap
powerpc/powernv: Simplify pnv_ioda_setup_pe_seg()
powerpc/powernv: IO and M32 mapping based on PCI device resources
powerpc/powernv: Track M64 segment consumption
powerpc/powernv: Rename M64 related functions
powerpc/powernv/ioda1: M64 support on P7IOC
powerpc/powernv/ioda1: Rename pnv_pci_ioda_setup_dma_pe()
powerpc/powernv/ioda1: Introduce PNV_IODA1_DMA32_SEGSIZE
powerpc/powernv: Remove DMA32 PE list
powerpc/powernv/ioda1: Improve DMA32 segment track
powerpc/powernv: Use PE instead of number during setup and release
powerpc/pci: Rename pcibios_{add,remove}_pci_devices()
powerpc/pci: Rename pcibios_find_pci_bus()
powerpc/pci: Move pci_find_bus_by_node() around
powerpc/pci: Export pci_add_device_node_info()
powerpc/pci: Introduce pci_remove_device_node_info()
powerpc/pci: Export pci_traverse_device_nodes()
powerpc/pci: Don't scan empty slot
powerpc/powernv: Simplify pnv_eeh_reset()
powerpc/powernv: Exclude root bus in pnv_pci_reset_secondary_bus()
arch/powerpc/include/asm/pci-bridge.h | 41 +-
arch/powerpc/include/asm/ppc-pci.h | 6 +-
arch/powerpc/kernel/eeh_driver.c | 12 +-
arch/powerpc/kernel/pci-hotplug.c | 47 +-
arch/powerpc/kernel/pci_dn.c | 66 ++-
arch/powerpc/platforms/powernv/eeh-powernv.c | 81 ++-
arch/powerpc/platforms/powernv/pci-ioda.c | 719 +++++++++++++++------------
arch/powerpc/platforms/powernv/pci.c | 4 +-
arch/powerpc/platforms/powernv/pci.h | 41 +-
arch/powerpc/platforms/pseries/msi.c | 4 +-
arch/powerpc/platforms/pseries/pci_dlpar.c | 32 --
arch/powerpc/platforms/pseries/setup.c | 2 +-
drivers/pci/hotplug/rpadlpar_core.c | 8 +-
drivers/pci/hotplug/rpaphp_core.c | 4 +-
drivers/pci/hotplug/rpaphp_pci.c | 4 +-
15 files changed, 592 insertions(+), 479 deletions(-)
--
2.1.0
Each PHB has one instance of "struct pci_controller_ops" that includes
various callbacks called by PCI subsystem. In the definition of this
struct, some callbacks have explicit names for its arguments, but the
left don't have.
This adds all explicit names of the arguments to the callbacks in
"struct pci_controller_ops" so that the code looks consistent. Also,
argument name @dev is replaced by @pdev as the later one is the
preferred name for PCI device.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Daniel Axtens <redacted>
Reviewed-by: Andrew Donnellan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
@@ -17,33 +17,34 @@ struct device_node;*PCIcontrolleroperations*/structpci_controller_ops{-void(*dma_dev_setup)(structpci_dev*dev);+void(*dma_dev_setup)(structpci_dev*pdev);void(*dma_bus_setup)(structpci_bus*bus);-int(*probe_mode)(structpci_bus*);+int(*probe_mode)(structpci_bus*bus);/* Called when pci_enable_device() is called. Returns true to*allowassignment/enablingofthedevice.*/-bool(*enable_device_hook)(structpci_dev*);+bool(*enable_device_hook)(structpci_dev*pdev);-void(*disable_device)(structpci_dev*);+void(*disable_device)(structpci_dev*pdev);-void(*release_device)(structpci_dev*);+void(*release_device)(structpci_dev*pdev);/* Called during PCI resource reassignment */-resource_size_t(*window_alignment)(structpci_bus*,unsignedlongtype);-void(*reset_secondary_bus)(structpci_dev*dev);+resource_size_t(*window_alignment)(structpci_bus*bus,+unsignedlongtype);+void(*reset_secondary_bus)(structpci_dev*pdev);#ifdef CONFIG_PCI_MSI-int(*setup_msi_irqs)(structpci_dev*dev,+int(*setup_msi_irqs)(structpci_dev*pdev,intnvec,inttype);-void(*teardown_msi_irqs)(structpci_dev*dev);+void(*teardown_msi_irqs)(structpci_dev*pdev);#endif-int(*dma_set_mask)(structpci_dev*dev,u64dma_mask);-u64(*dma_get_required_mask)(structpci_dev*dev);+int(*dma_set_mask)(structpci_dev*pdev,u64dma_mask);+u64(*dma_get_required_mask)(structpci_dev*pdev);-void(*shutdown)(structpci_controller*);+void(*shutdown)(structpci_controller*hose);};/*
This moves those fields in struct pnv_phb that are related to PE
allocation around. No logical change.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/platforms/powernv/pci.h | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
Currently, the IO and M32 segments are mapped to the corresponding
PE based on the windows of the parent bridge of PE's primary bus.
It's not going to work when the windows of root port or upstream
port of the PCIe switch behind root port are extended to PHB's
apertures in order to support hotplug in subsequent patch.
This fixes the issue by mapping IO and M32 segments based on the
resources of the PCI devices included in the PE, instead of the
windows of the parent bridge of the PE's primary bus.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
This changes the data type of PE number from "int" to "unsigned int"
in order to match the fact PE number is never negative:
* The number of PE to which the specified PCI device is attached.
* The PE number map for SRIOV VFs.
* The returned PE number from pnv_ioda_alloc_pe().
* The returned PE number from pnv_ioda2_pick_m64_pe().
Suggested-by: Alexey Kardashevskiy <redacted>
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 6 +++---
arch/powerpc/platforms/powernv/pci-ioda.c | 8 ++++----
arch/powerpc/platforms/powernv/pci.c | 2 +-
arch/powerpc/platforms/powernv/pci.h | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
@@ -209,14 +209,14 @@ struct pci_dn {#ifdef CONFIG_EEHstructeeh_dev*edev;/* eeh device */#endif-#define IODA_INVALID_PE (-1)+#define IODA_INVALID_PE 0xFFFFFFFF#ifdef CONFIG_PPC_POWERNV-intpe_number;+unsignedintpe_number;intvf_index;/* VF index in the PF */#ifdef CONFIG_PCI_IOVu16vfs_expanded;/* number of VFs IOV BAR expanded */u16num_vfs;/* number of VFs enabled*/-int*pe_num_map;/* PE# for the first VF PE or array */+unsignedint*pe_num_map;/* PE# for the first VF PE or array */boolm64_single_mode;/* Use M64 BAR in Single Mode */#define IODA_INVALID_M64 (-1)int(*m64_map)[PCI_SRIOV_NUM_BARS];
@@ -919,7 +919,7 @@ static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev)structpnv_phb*phb=hose->private_data;structpci_dn*pdn=pci_get_pdn(dev);structpnv_ioda_pe*pe;-intpe_num;+unsignedintpe_num;if(!pdn){pr_err("%s: Device tree node not associated properly\n",
@@ -1010,7 +1010,7 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all)structpci_controller*hose=pci_bus_to_host(bus);structpnv_phb*phb=hose->private_data;structpnv_ioda_pe*pe;-intpe_num=IODA_INVALID_PE;+unsignedintpe_num=IODA_INVALID_PE;/* Check if PE is determined by M64 */if(phb->pick_m64_pe)
In hotplug case, function pci_add_pci_devices() is called to rescan
the specified PCI bus, which might not have any child devices. Access
to the PCI bus's child device node will cause kernel crash without
exception.
This adds one more check to skip scanning PCI bus that doesn't have
any subordinate devices from device-tree, in order to avoid kernel
crash.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/kernel/pci-hotplug.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
This implements and exports pci_remove_device_node_info(). It's
used to remove the pdn (struct pci_dn) for the indicated device
node. The function is going to be used by PowerNV PCI hotplug
driver.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 1 +
arch/powerpc/kernel/pci_dn.c | 23 +++++++++++++++++++++++
2 files changed, 24 insertions(+)
This enables M64 window on P7IOC, which has been enabled on PHB3.
Different from PHB3 where 16 M64 BARs are supported and each of
them can be owned by one particular PE# exclusively or divided
evenly to 256 segments, every P7IOC PHB has 16 M64 BARs and each
of them are divided to 8 segments. So every P7IOC PHB supports
128 M64 segments in total. P7IOC has M64DT, which helps mapping
one particular M64 segment# to arbitrary PE#. PHB3 doesn't have
M64DT, indicating that one M64 segment can only be pinned to the
fixed PE#.
In order to unified M64 support M64 on P7IOC and PHB3, we just
provide 128 M64 segments on every P7IOC PHB and each of them is
pinned to the fixed PE# by bypassing the function of M64DT. In
turn, we just need different phb->init_m64() for P7IOC and PHB3
and maps M64 segment in pnv_ioda_reserve_m64_pe() for P7IOC, most
of the code are shared by them.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 89 +++++++++++++++++++++++++++++--
1 file changed, 86 insertions(+), 3 deletions(-)
@@ -315,6 +376,26 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all)pe->master=master_pe;list_add_tail(&pe->list,&master_pe->slaves);}++/*+*P7IOCsupportsM64DT,whichhelpsmappingM64segment+*tooneparticularPE#.However,PHB3hasfixedmapping+*betweenM64segmentandPE#.Inordertohavesamelogic+*forP7IOCandPHB3,weenforcefixedmappingbetweenM64+*segmentandPE#onP7IOC.+*/+if(phb->type==PNV_PHB_IODA1){+int64_trc;++rc=opal_pci_map_pe_mmio_window(phb->opal_id,+pe->pe_number,OPAL_M64_WINDOW_TYPE,+pe->pe_number/PNV_IODA1_M64_SEGS,+pe->pe_number%PNV_IODA1_M64_SEGS);+if(rc!=OPAL_SUCCESS)+pr_warn("%s: Error %lld mapping M64 for PHB#%d-PE#%d\n",+__func__,rc,phb->hose->global_number,+pe->pe_number);+}}kfree(pe_alloc);
@@ -329,8 +410,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)constu32*r;u64pci_addr;-/* FIXME: Support M64 for P7IOC */-if(phb->type!=PNV_PHB_IODA2){+if(phb->type!=PNV_PHB_IODA1&&phb->type!=PNV_PHB_IODA2){pr_info(" Not support M64 window\n");return;}
@@ -364,7 +444,10 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)/* Use last M64 BAR to cover M64 window */phb->ioda.m64_bar_idx=15;-phb->init_m64=pnv_ioda2_init_m64;+if(phb->type==PNV_PHB_IODA1)+phb->init_m64=pnv_ioda1_init_m64;+else+phb->init_m64=pnv_ioda2_init_m64;phb->reserve_m64_pe=pnv_ioda_reserve_m64_pe;phb->pick_m64_pe=pnv_ioda_pick_m64_pe;}
This renames those functions picking PE number based on consumed
M64 segments, mapping M64 segments to PEs as those functions are
going to be shared by IODA1/IODA2 in next patch. No logical changes
introduced.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
@@ -283,7 +283,7 @@ static unsigned int pnv_ioda2_pick_m64_pe(struct pci_bus *bus, bool all)}/* Figure out reserved PE numbers by the PE */-pnv_ioda2_reserve_m64_pe(bus,pe_alloc,all);+pnv_ioda_reserve_m64_pe(bus,pe_alloc,all);/**thecurrentbusmightnotownM64windowandthat'sall
@@ -365,8 +365,8 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)/* Use last M64 BAR to cover M64 window */phb->ioda.m64_bar_idx=15;phb->init_m64=pnv_ioda2_init_m64;-phb->reserve_m64_pe=pnv_ioda2_reserve_m64_pe;-phb->pick_m64_pe=pnv_ioda2_pick_m64_pe;+phb->reserve_m64_pe=pnv_ioda_reserve_m64_pe;+phb->pick_m64_pe=pnv_ioda_pick_m64_pe;}staticvoidpnv_ioda_freeze_pe(structpnv_phb*phb,intpe_no)
In current implementation, the PEs that are allocated or picked
from the reserved list are identified by PE number. The PE instance
has to be picked according to the PE number eventually. We have
same issue when PE is released.
For pnv_ioda_pick_m64_pe() and pnv_ioda_alloc_pe(), this returns
PE instance so that pnv_ioda_setup_bus_PE() can use the allocated
or reserved PE instance directly. Also, pnv_ioda_setup_bus_PE()
returns the reserved/allocated PE instance to be used in subsequent
patches. On the other hand, pnv_ioda_free_pe() uses PE instance
(not number) as its argument. No logical changes introduced.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 104 +++++++++++++++++-------------
arch/powerpc/platforms/powernv/pci.h | 2 +-
2 files changed, 59 insertions(+), 47 deletions(-)
@@ -123,6 +123,14 @@ static inline bool pnv_pci_is_mem_pref_64(unsigned long flags)(IORESOURCE_MEM_64|IORESOURCE_PREFETCH));}+staticstructpnv_ioda_pe*pnv_ioda_init_pe(structpnv_phb*phb,intpe_no)+{+phb->ioda.pe_array[pe_no].phb=phb;+phb->ioda.pe_array[pe_no].pe_number=pe_no;++return&phb->ioda.pe_array[pe_no];+}+staticvoidpnv_ioda_reserve_pe(structpnv_phb*phb,intpe_no){if(!(pe_no>=0&&pe_no<phb->ioda.total_pe_num)){
@@ -135,11 +143,10 @@ static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no)pr_debug("%s: PE %d was reserved on PHB#%x\n",__func__,pe_no,phb->hose->global_number);-phb->ioda.pe_array[pe_no].phb=phb;-phb->ioda.pe_array[pe_no].pe_number=pe_no;+pnv_ioda_init_pe(phb,pe_no);}-staticunsignedintpnv_ioda_alloc_pe(structpnv_phb*phb)+staticstructpnv_ioda_pe*pnv_ioda_alloc_pe(structpnv_phb*phb){unsignedlongpe;
@@ -147,20 +154,20 @@ static unsigned int pnv_ioda_alloc_pe(struct pnv_phb *phb)pe=find_next_zero_bit(phb->ioda.pe_alloc,phb->ioda.total_pe_num,0);if(pe>=phb->ioda.total_pe_num)-returnIODA_INVALID_PE;+returnNULL;}while(test_and_set_bit(pe,phb->ioda.pe_alloc));-phb->ioda.pe_array[pe].phb=phb;-phb->ioda.pe_array[pe].pe_number=pe;-returnpe;+returnpnv_ioda_init_pe(phb,pe);}-staticvoidpnv_ioda_free_pe(structpnv_phb*phb,intpe)+staticvoidpnv_ioda_free_pe(structpnv_ioda_pe*pe){-WARN_ON(phb->ioda.pe_array[pe].pdev);+structpnv_phb*phb=pe->phb;-memset(&phb->ioda.pe_array[pe],0,sizeof(structpnv_ioda_pe));-clear_bit(pe,phb->ioda.pe_alloc);+WARN_ON(pe->pdev);++memset(pe,0,sizeof(structpnv_ioda_pe));+clear_bit(pe->pe_number,phb->ioda.pe_alloc);}/* The default M64 BAR is shared by all PEs */
@@ -330,7 +337,7 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all)/* Root bus shouldn't use M64 */if(pci_is_root_bus(bus))-returnIODA_INVALID_PE;+returnNULL;/* Allocate bitmap */size=_ALIGN_UP(phb->ioda.total_pe_num/8,sizeof(unsignedlong));
@@ -338,7 +345,7 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all)if(!pe_alloc){pr_warn("%s: Out of memory !\n",__func__);-returnIODA_INVALID_PE;+returnNULL;}/* Figure out reserved PE numbers by the PE */
@@ -1001,8 +1006,7 @@ static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev)if(pnv_ioda_configure_pe(phb,pe)){/* XXX What do we do here ? */-if(pe_num)-pnv_ioda_free_pe(phb,pe_num);+pnv_ioda_free_pe(pe);pdn->pe_number=IODA_INVALID_PE;pe->pdev=NULL;pci_dev_put(dev);
@@ -1037,28 +1041,26 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)*subordinatePCIdevicesandbuses.ThesecondtypeofPEisnormally*orgiriatedbyPCIe-to-PCIbridgeorPLXswitchdownstreamports.*/-staticvoidpnv_ioda_setup_bus_PE(structpci_bus*bus,boolall)+staticstructpnv_ioda_pe*pnv_ioda_setup_bus_PE(structpci_bus*bus,boolall){structpci_controller*hose=pci_bus_to_host(bus);structpnv_phb*phb=hose->private_data;-structpnv_ioda_pe*pe;-unsignedintpe_num=IODA_INVALID_PE;+structpnv_ioda_pe*pe=NULL;/* Check if PE is determined by M64 */if(phb->pick_m64_pe)-pe_num=phb->pick_m64_pe(bus,all);+pe=phb->pick_m64_pe(bus,all);/* The PE number isn't pinned by M64 */-if(pe_num==IODA_INVALID_PE)-pe_num=pnv_ioda_alloc_pe(phb);+if(!pe)+pe=pnv_ioda_alloc_pe(phb);-if(pe_num==IODA_INVALID_PE){+if(!pe){pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n",__func__,pci_domain_nr(bus),bus->number);-return;+returnNULL;}-pe=&phb->ioda.pe_array[pe_num];pe->flags|=(all?PNV_IODA_PE_BUS_ALL:PNV_IODA_PE_BUS);pe->pbus=bus;pe->pdev=NULL;
@@ -1067,17 +1069,16 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all)if(all)pe_info(pe,"Secondary bus %d..%d associated with PE#%d\n",-bus->busn_res.start,bus->busn_res.end,pe_num);+bus->busn_res.start,bus->busn_res.end,pe->pe_number);elsepe_info(pe,"Secondary bus %d associated with PE#%d\n",-bus->busn_res.start,pe_num);+bus->busn_res.start,pe->pe_number);if(pnv_ioda_configure_pe(phb,pe)){/* XXX What do we do here ? */-if(pe_num)-pnv_ioda_free_pe(phb,pe_num);+pnv_ioda_free_pe(pe);pe->pbus=NULL;-return;+returnNULL;}/* Associate it with all child devices */
@@ -1085,6 +1086,8 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all)/* Put PE to the list */list_add_tail(&pe->list,&phb->ioda.pe_list);++returnpe;}staticstructpnv_ioda_pe*pnv_ioda_setup_npu_PE(structpci_dev*npu_pdev)
@@ -1483,8 +1490,7 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs)if(pnv_ioda_configure_pe(phb,pe)){/* XXX What do we do here ? */-if(pe_num)-pnv_ioda_free_pe(phb,pe_num);+pnv_ioda_free_pe(pe);pe->pdev=NULL;continue;}
@@ -1503,6 +1509,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)structpci_bus*bus;structpci_controller*hose;structpnv_phb*phb;+structpnv_ioda_pe*pe;structpci_dn*pdn;intret;u16i;
@@ -1545,11 +1552,13 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)/* Calculate available PE for required VFs */if(pdn->m64_single_mode){for(i=0;i<num_vfs;i++){-pdn->pe_num_map[i]=pnv_ioda_alloc_pe(phb);-if(pdn->pe_num_map[i]==IODA_INVALID_PE){+pe=pnv_ioda_alloc_pe(phb);+if(!pe){ret=-EBUSY;gotom64_failed;}++pdn->pe_num_map[i]=pe->pe_number;}}else{mutex_lock(&phb->ioda.pe_alloc_mutex);
@@ -1594,8 +1603,11 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)m64_failed:if(pdn->m64_single_mode){for(i=0;i<num_vfs;i++){-if(pdn->pe_num_map[i]!=IODA_INVALID_PE)-pnv_ioda_free_pe(phb,pdn->pe_num_map[i]);+if(pdn->pe_num_map[i]==IODA_INVALID_PE)+continue;++pe=&phb->ioda.pe_array[pdn->pe_num_map[i]];+pnv_ioda_free_pe(pe);}}elsebitmap_clear(phb->ioda.pe_alloc,*pdn->pe_num_map,num_vfs);
@@ -260,10 +260,10 @@ static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn)externstructpci_bus*pcibios_find_pci_bus(structdevice_node*dn);/** Remove all of the PCI devices under this bus */-externvoidpcibios_remove_pci_devices(structpci_bus*bus);+externvoidpci_hp_remove_devices(structpci_bus*bus);/** Discover new pci devices under this bus, and add them */-externvoidpcibios_add_pci_devices(structpci_bus*bus);+externvoidpci_hp_add_devices(structpci_bus*bus);externvoidisa_bridge_find_early(structpci_controller*hose);
@@ -38,20 +38,20 @@ void pcibios_release_device(struct pci_dev *dev)}/**-*pcibios_remove_pci_devices-removealldevicesunderthisbus+*pci_hp_remove_devices-removealldevicesunderthisbus*@bus:theindicatedPCIbus**RemoveallofthePCIdevicesunderthisbusbothfromthe*linuxpcidevicetree,andfromthepowerpcEEHaddresscache.*/-voidpcibios_remove_pci_devices(structpci_bus*bus)+voidpci_hp_remove_devices(structpci_bus*bus){structpci_dev*dev,*tmp;structpci_bus*child_bus;/* First go down child busses */list_for_each_entry(child_bus,&bus->children,node)-pcibios_remove_pci_devices(child_bus);+pci_hp_remove_devices(child_bus);pr_debug("PCI: Removing devices on bus %04x:%02x\n",pci_domain_nr(bus),bus->number);
pnv_ioda_setup_pe_seg() associates the IO and M32 segments with the
owner PE. The code mapping segments should be fixed and immune from
logic changes introduced to pnv_ioda_setup_pe_seg().
This moves the code mapping segments to helper pnv_ioda_setup_pe_res().
The data type for @rc is changed to "int64_t". Also, argument @hose is
removed from pnv_ioda_setup_pe() as it can be got from @pe. No functional
changes introduced.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 121 +++++++++++++++---------------
1 file changed, 62 insertions(+), 59 deletions(-)
There are two arrays for IO and M32 segment maps on every PHB.
The index of the arrays are segment number and the value stored
in the corresponding element is PE number, indicating the segment
is assigned to the PE. Initially, all elements in those two arrays
are zeroes, meaning all segments are assigned to PE#0. It's wrong.
This fixes the initial values in the elements of those two arrays
to IODA_INVALID_PE, meaning all segments aren't assigned to any
PE.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
This renames update_dn_pci_info() to pci_add_device_node_info()
with corresponding adjustment on the parameter type and exports it.
The function is used to create pdn (struct pci_dn) for the indicated
device node. Another function add_pdn(), almost wrapper of
pci_add_device_node_info(), to be used in traverse_pci_devices(). No
logical changes introduced.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 3 ++-
arch/powerpc/kernel/pci_dn.c | 30 +++++++++++++++++++-----------
arch/powerpc/platforms/pseries/setup.c | 2 +-
3 files changed, 22 insertions(+), 13 deletions(-)
@@ -446,8 +455,7 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb)structpci_dn*pdn;/* PHB nodes themselves must not match */-update_dn_pci_info(dn,phb);-pdn=dn->data;+pdn=pci_add_device_node_info(phb,dn);if(pdn){pdn->devfn=pdn->busno=-1;pdn->vendor_id=pdn->device_id=pdn->class_code=0;
@@ -456,7 +464,7 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb)}/* Update dn->phb ptrs for new phb and children devices */-traverse_pci_devices(dn,update_dn_pci_info,phb);+traverse_pci_devices(dn,add_pdn,phb);}/**
This renames the fields related to PE number in "struct pnv_phb"
for better reflecting of their usages as Alexey suggested. No
logical changes introduced.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/platforms/powernv/eeh-powernv.c | 2 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 58 ++++++++++++++--------------
arch/powerpc/platforms/powernv/pci.c | 2 +-
arch/powerpc/platforms/powernv/pci.h | 4 +-
4 files changed, 33 insertions(+), 33 deletions(-)
@@ -124,7 +124,7 @@ static inline bool pnv_pci_is_mem_pref_64(unsigned long flags)staticvoidpnv_ioda_reserve_pe(structpnv_phb*phb,intpe_no){-if(!(pe_no>=0&&pe_no<phb->ioda.total_pe)){+if(!(pe_no>=0&&pe_no<phb->ioda.total_pe_num)){pr_warn("%s: Invalid PE %d on PHB#%x\n",__func__,pe_no,phb->hose->global_number);return;
@@ -144,8 +144,8 @@ static int pnv_ioda_alloc_pe(struct pnv_phb *phb)do{pe=find_next_zero_bit(phb->ioda.pe_alloc,-phb->ioda.total_pe,0);-if(pe>=phb->ioda.total_pe)+phb->ioda.total_pe_num,0);+if(pe>=phb->ioda.total_pe_num)returnIODA_INVALID_PE;}while(test_and_set_bit(pe,phb->ioda.pe_alloc));
@@ -199,13 +199,13 @@ static int pnv_ioda2_init_m64(struct pnv_phb *phb)*expectedtobe0orlastoneofPEcapabicity.*/r=&phb->hose->mem_resources[1];-if(phb->ioda.reserved_pe==0)+if(phb->ioda.reserved_pe_idx==0)r->start+=phb->ioda.m64_segsize;-elseif(phb->ioda.reserved_pe==(phb->ioda.total_pe-1))+elseif(phb->ioda.reserved_pe_idx==(phb->ioda.total_pe_num-1))r->end-=phb->ioda.m64_segsize;elsepr_warn(" Cannot strip M64 segment for reserved PE#%d\n",-phb->ioda.reserved_pe);+phb->ioda.reserved_pe_idx);return0;
@@ -274,7 +274,7 @@ static int pnv_ioda2_pick_m64_pe(struct pci_bus *bus, bool all)returnIODA_INVALID_PE;/* Allocate bitmap */-size=_ALIGN_UP(phb->ioda.total_pe/8,sizeof(unsignedlong));+size=_ALIGN_UP(phb->ioda.total_pe_num/8,sizeof(unsignedlong));pe_alloc=kzalloc(size,GFP_KERNEL);if(!pe_alloc){pr_warn("%s: Out of memory !\n",
@@ -456,7 +456,7 @@ static int pnv_ioda_get_pe_state(struct pnv_phb *phb, int pe_no)s64rc;/* Sanity check on PE number */-if(pe_no<0||pe_no>=phb->ioda.total_pe)+if(pe_no<0||pe_no>=phb->ioda.total_pe_num)returnOPAL_EEH_STOPPED_PERM_UNAVAIL;/*
@@ -3300,13 +3300,13 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,pr_err(" Failed to map registers !\n");/* Initialize more IODA stuff */-phb->ioda.total_pe=1;+phb->ioda.total_pe_num=1;prop32=of_get_property(np,"ibm,opal-num-pes",NULL);if(prop32)-phb->ioda.total_pe=be32_to_cpup(prop32);+phb->ioda.total_pe_num=be32_to_cpup(prop32);prop32=of_get_property(np,"ibm,opal-reserved-pe",NULL);if(prop32)-phb->ioda.reserved_pe=be32_to_cpup(prop32);+phb->ioda.reserved_pe_idx=be32_to_cpup(prop32);/* Parse 64-bit MMIO range */pnv_ioda_parse_m64_window(phb);
@@ -3315,29 +3315,29 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,/* FW Has already off top 64k of M32 space (MSI space) */phb->ioda.m32_size+=0x10000;-phb->ioda.m32_segsize=phb->ioda.m32_size/phb->ioda.total_pe;+phb->ioda.m32_segsize=phb->ioda.m32_size/phb->ioda.total_pe_num;phb->ioda.m32_pci_base=hose->mem_resources[0].start-hose->mem_offset[0];phb->ioda.io_size=hose->pci_io_size;-phb->ioda.io_segsize=phb->ioda.io_size/phb->ioda.total_pe;+phb->ioda.io_segsize=phb->ioda.io_size/phb->ioda.total_pe_num;phb->ioda.io_pci_base=0;/* XXX calculate this ? *//* Allocate aux data & arrays. We don't have IO ports on PHB3 */-size=_ALIGN_UP(phb->ioda.total_pe/8,sizeof(unsignedlong));+size=_ALIGN_UP(phb->ioda.total_pe_num/8,sizeof(unsignedlong));m32map_off=size;-size+=phb->ioda.total_pe*sizeof(phb->ioda.m32_segmap[0]);+size+=phb->ioda.total_pe_num*sizeof(phb->ioda.m32_segmap[0]);if(phb->type==PNV_PHB_IODA1){iomap_off=size;-size+=phb->ioda.total_pe*sizeof(phb->ioda.io_segmap[0]);+size+=phb->ioda.total_pe_num*sizeof(phb->ioda.io_segmap[0]);}pemap_off=size;-size+=phb->ioda.total_pe*sizeof(structpnv_ioda_pe);+size+=phb->ioda.total_pe_num*sizeof(structpnv_ioda_pe);aux=memblock_virt_alloc(size,0);phb->ioda.pe_alloc=aux;phb->ioda.m32_segmap=aux+m32map_off;if(phb->type==PNV_PHB_IODA1)phb->ioda.io_segmap=aux+iomap_off;phb->ioda.pe_array=aux+pemap_off;-set_bit(phb->ioda.reserved_pe,phb->ioda.pe_alloc);+set_bit(phb->ioda.reserved_pe_idx,phb->ioda.pe_alloc);INIT_LIST_HEAD(&phb->ioda.pe_dma_list);INIT_LIST_HEAD(&phb->ioda.pe_list);
PEs are put into PHB DMA32 list (phb->ioda.pe_dma_list) according
to their DMA32 weight. The PEs on the list are iterated to setup
their TCE32 tables at system booting time. The list is used for
once at boot time and no need to keep it.
This moves the logic calculating DMA32 weight of PHB and PE to
pnv_ioda_setup_dma() to drop PHB's DMA32 list. Also, every PE
traces the consumed DMA32 segment by @tce32_seg and @tce32_segcount
are useless and they're removed.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 171 ++++++++++++++----------------
arch/powerpc/platforms/powernv/pci.h | 19 ----
2 files changed, 78 insertions(+), 112 deletions(-)
@@ -890,44 +890,6 @@ out:return0;}-staticvoidpnv_ioda_link_pe_by_weight(structpnv_phb*phb,-structpnv_ioda_pe*pe)-{-structpnv_ioda_pe*lpe;--list_for_each_entry(lpe,&phb->ioda.pe_dma_list,dma_link){-if(lpe->dma_weight<pe->dma_weight){-list_add_tail(&pe->dma_link,&lpe->dma_link);-return;-}-}-list_add_tail(&pe->dma_link,&phb->ioda.pe_dma_list);-}--staticunsignedintpnv_ioda_dma_weight(structpci_dev*dev)-{-/* This is quite simplistic. The "base" weight of a device-*is10.0meansnoDMAistobeaccountedforit.-*/--/* If it's a bridge, no DMA */-if(dev->hdr_type!=PCI_HEADER_TYPE_NORMAL)-return0;--/* Reduce the weight of slow USB controllers */-if(dev->class==PCI_CLASS_SERIAL_USB_UHCI||-dev->class==PCI_CLASS_SERIAL_USB_OHCI||-dev->class==PCI_CLASS_SERIAL_USB_EHCI)-return3;--/* Increase the weight of RAID (includes Obsidian) */-if((dev->class>>8)==PCI_CLASS_STORAGE_RAID)-return15;--/* Default */-return10;-}-#ifdef CONFIG_PCI_IOVstaticintpnv_pci_vf_resource_shift(structpci_dev*dev,intoffset){
@@ -1048,16 +1009,6 @@ static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev)returnNULL;}-/* Assign a DMA weight to the device */-pe->dma_weight=pnv_ioda_dma_weight(dev);-if(pe->dma_weight!=0){-phb->ioda.dma_weight+=pe->dma_weight;-phb->ioda.dma_pe_count++;-}--/* Link the PE */-pnv_ioda_link_pe_by_weight(phb,pe);-returnpe;}
@@ -1112,10 +1062,8 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all)pe->flags|=(all?PNV_IODA_PE_BUS_ALL:PNV_IODA_PE_BUS);pe->pbus=bus;pe->pdev=NULL;-pe->tce32_seg=-1;pe->mve_number=-1;pe->rid=bus->busn_res.start<<8;-pe->dma_weight=0;if(all)pe_info(pe,"Secondary bus %d..%d associated with PE#%d\n",
@@ -1137,17 +1085,6 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all)/* Put PE to the list */list_add_tail(&pe->list,&phb->ioda.pe_list);--/* Account for one DMA PE if at least one DMA capable device exist-*belowthebridge-*/-if(pe->dma_weight!=0){-phb->ioda.dma_weight+=pe->dma_weight;-phb->ioda.dma_pe_count++;-}--/* Link the PE */-pnv_ioda_link_pe_by_weight(phb,pe);}staticstructpnv_ioda_pe*pnv_ioda_setup_npu_PE(structpci_dev*npu_pdev)
@@ -1188,7 +1125,6 @@ static struct pnv_ioda_pe *pnv_ioda_setup_npu_PE(struct pci_dev *npu_pdev)rid=npu_pdev->bus->number<<8|npu_pdn->devfn;npu_pdn->pcidev=npu_pdev;npu_pdn->pe_number=pe_num;-pe->dma_weight+=pnv_ioda_dma_weight(npu_pdev);phb->ioda.pe_rmap[rid]=pe->pe_number;/* Map the PE to this link */
@@ -2027,6 +1962,54 @@ static struct iommu_table_ops pnv_ioda2_iommu_ops = {.free=pnv_ioda2_table_free,};+staticintpnv_pci_ioda_dev_dma_weight(structpci_dev*dev,void*data)+{+unsignedint*weight=(unsignedint*)data;++/* This is quite simplistic. The "base" weight of a device+*is10.0meansnoDMAistobeaccountedforit.+*/+if(dev->hdr_type!=PCI_HEADER_TYPE_NORMAL)+return0;++if(dev->class==PCI_CLASS_SERIAL_USB_UHCI||+dev->class==PCI_CLASS_SERIAL_USB_OHCI||+dev->class==PCI_CLASS_SERIAL_USB_EHCI)+*weight+=3;+elseif((dev->class>>8)==PCI_CLASS_STORAGE_RAID)+*weight+=15;+else+*weight+=10;++return0;+}++staticunsignedintpnv_pci_ioda_pe_dma_weight(structpnv_ioda_pe*pe)+{+unsignedintweight=0;++/* SRIOV VF has same DMA32 weight as its PF */+#ifdef CONFIG_PCI_IOV+if((pe->flags&PNV_IODA_PE_VF)&&pe->parent_dev){+pnv_pci_ioda_dev_dma_weight(pe->parent_dev,&weight);+returnweight;+}+#endif++if((pe->flags&PNV_IODA_PE_DEV)&&pe->pdev){+pnv_pci_ioda_dev_dma_weight(pe->pdev,&weight);+}elseif((pe->flags&PNV_IODA_PE_BUS)&&pe->pbus){+structpci_dev*pdev;++list_for_each_entry(pdev,&pe->pbus->devices,bus_list)+pnv_pci_ioda_dev_dma_weight(pdev,&weight);+}elseif((pe->flags&PNV_IODA_PE_BUS_ALL)&&pe->pbus){+pci_walk_bus(pe->pbus,pnv_pci_ioda_dev_dma_weight,&weight);+}++returnweight;+}+staticvoidpnv_pci_ioda1_setup_dma_pe(structpnv_phb*phb,structpnv_ioda_pe*pe,unsignedintbase,
@@ -2043,17 +2026,12 @@ static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb,/* XXX FIXME: Provide 64-bit DMA facilities & non-4K TCE tables etc.. *//* XXX FIXME: Allocate multi-level tables on PHB3 */-/* We shouldn't already have a 32-bit DMA associated */-if(WARN_ON(pe->tce32_seg>=0))-return;-tbl=pnv_pci_table_alloc(phb->hose->node);iommu_register_group(&pe->table_group,phb->hose->global_number,pe->pe_number);pnv_pci_link_table_and_group(phb->hose->node,0,tbl,&pe->table_group);/* Grab a 32-bit TCE table */-pe->tce32_seg=base;pe_info(pe," Setting up 32-bit TCE table at %08x..%08x\n",base*PNV_IODA1_DMA32_SEGSIZE,(base+segs)*PNV_IODA1_DMA32_SEGSIZE-1);
@@ -2120,8 +2098,6 @@ static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb,return;fail:/* XXX Failure: Try to fallback to 64-bit only ? */-if(pe->tce32_seg>=0)-pe->tce32_seg=-1;if(tce_mem)__free_pages(tce_mem,get_order(tce32_segsz*segs));if(tbl){
@@ -2532,10 +2508,6 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,{int64_trc;-/* We shouldn't already have a 32-bit DMA associated */-if(WARN_ON(pe->tce32_seg>=0))-return;-/* TVE #1 is selected by PCI address bit 59 */pe->tce_bypass_base=1ull<<59;
@@ -2543,7 +2515,6 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,pe->pe_number);/* The PE will reserve all possible 32-bits space */-pe->tce32_seg=0;pe_info(pe,"Setting up 32-bit TCE table at 0..%08x\n",phb->ioda.m32_pci_base);
@@ -2574,24 +2542,35 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,staticvoidpnv_ioda_setup_dma(structpnv_phb*phb){structpci_controller*hose=phb->hose;-unsignedintresidual,remaining,segs,tw,base;+unsignedintweight,total_weight,dma_pe_count;+unsignedintresidual,remaining,segs,base;structpnv_ioda_pe*pe;+total_weight=0;+pci_walk_bus(phb->hose->bus,pnv_pci_ioda_dev_dma_weight,+&total_weight);++dma_pe_count=0;+list_for_each_entry(pe,&phb->ioda.pe_list,list){+weight=pnv_pci_ioda_pe_dma_weight(pe);+if(weight>0)+dma_pe_count++;+}+/* If we have more PE# than segments available, hand out one*perPEuntilwerunoutandlettherestfail.Ifnot,*thenweassignatleastonesegmentperPE,plusmorebased*ontheamountofdevicesunderthatPE*/-if(phb->ioda.dma_pe_count>phb->ioda.tce32_count)+if(dma_pe_count>phb->ioda.tce32_count)residual=0;else-residual=phb->ioda.tce32_count--phb->ioda.dma_pe_count;+residual=phb->ioda.tce32_count-dma_pe_count;pr_info("PCI: Domain %04x has %ld available 32-bit DMA segments\n",hose->global_number,phb->ioda.tce32_count);pr_info("PCI: %d PE# for a total weight of %d\n",-phb->ioda.dma_pe_count,phb->ioda.dma_weight);+dma_pe_count,total_weight);pnv_pci_ioda_setup_opal_tce_kill(phb);
@@ -53,14 +53,7 @@ struct pnv_ioda_pe {/* PE number */unsignedintpe_number;-/* "Weight" assigned to the PE for the sake of DMA resource-*allocations-*/-unsignedintdma_weight;-/* "Base" iommu table, ie, 4K TCEs, 32-bit DMA */-inttce32_seg;-inttce32_segcount;structiommu_table_grouptable_group;/* 64-bit TCE bypass region */
@@ -78,7 +71,6 @@ struct pnv_ioda_pe {structlist_headslaves;/* Link in list of PE#s */-structlist_headdma_link;structlist_headlist;};
@@ -169,17 +161,6 @@ struct pnv_phb {/* 32-bit TCE tables allocation */unsignedlongtce32_count;-/* Total "weight" for the sake of DMA resources-*allocation-*/-unsignedintdma_weight;-unsignedintdma_pe_count;--/* Sorted list of used PE's, sorted at-*bootforresourceallocationpurposes-*/-structlist_headpe_dma_list;-/* TCE cache invalidate registers (physical and*remapped)*/
Currently, there is one macro (TCE32_TABLE_SIZE) representing the
TCE table size for one DMA32 segment. The constant representing
the DMA32 segment size (1 << 28) is still used in the code.
This defines PNV_IODA1_DMA32_SEGSIZE representing one DMA32
segment size. the TCE table size can be calcualted when the page
has fixed 4KB size. So all the related calculation depends on one
macro (PNV_IODA1_DMA32_SEGSIZE). No logical changes introduced.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
@@ -2057,29 +2055,34 @@ static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb,/* Grab a 32-bit TCE table */pe->tce32_seg=base;pe_info(pe," Setting up 32-bit TCE table at %08x..%08x\n",-(base<<28),((base+segs)<<28)-1);+base*PNV_IODA1_DMA32_SEGSIZE,+(base+segs)*PNV_IODA1_DMA32_SEGSIZE-1);/* XXX Currently, we allocate one big contiguous table for the*TCEs.Weonlyreallyneedonechunkper256MofTCEspace*(iepersegment)butthat'sanoptimizationforlater,it*requiressomeaddedsmartswithourget/put_tceimplementation+*+*EachTCEpageis4KBinsizeandeachTCEentryoccupies8+*bytes*/+tce32_segsz=PNV_IODA1_DMA32_SEGSIZE>>(IOMMU_PAGE_SHIFT_4K-3);tce_mem=alloc_pages_node(phb->hose->node,GFP_KERNEL,-get_order(TCE32_TABLE_SIZE*segs));+get_order(tce32_segsz*segs));if(!tce_mem){pe_err(pe," Failed to allocate a 32-bit TCE memory\n");gotofail;}addr=page_address(tce_mem);-memset(addr,0,TCE32_TABLE_SIZE*segs);+memset(addr,0,tce32_segsz*segs);/* Configure HW */for(i=0;i<segs;i++){rc=opal_pci_map_pe_dma_window(phb->opal_id,pe->pe_number,base+i,1,-__pa(addr)+TCE32_TABLE_SIZE*i,-TCE32_TABLE_SIZE,0x1000);+__pa(addr)+tce32_segsz*i,+tce32_segsz,IOMMU_PAGE_SIZE_4K);if(rc){pe_err(pe," Failed to configure 32-bit TCE table,"" err %ld\n",rc);
@@ -3456,7 +3460,8 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,mutex_init(&phb->ioda.pe_list_mutex);/* Calculate how many 32-bit TCE segments we have */-phb->ioda.tce32_count=phb->ioda.m32_pci_base>>28;+phb->ioda.tce32_count=phb->ioda.m32_pci_base/+PNV_IODA1_DMA32_SEGSIZE;#if 0 /* We should really do that ... */rc=opal_pci_set_phb_mem_window(opal->phb_id,
This renames traverse_pci_devices() to pci_traverse_device_nodes().
The function traverses all subordinate device nodes of the specified
one. Also, below cleanup applied to the function. No logical changes
introduced.
* Rename "pre" to "fn".
* Avoid assignment in if condition reported from checkpatch.pl.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/include/asm/ppc-pci.h | 6 +++---
arch/powerpc/kernel/pci_dn.c | 15 ++++++++++-----
arch/powerpc/platforms/pseries/msi.c | 4 ++--
3 files changed, 15 insertions(+), 10 deletions(-)
@@ -33,9 +33,9 @@ extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */structdevice_node;structpci_dn;-typedefvoid*(*traverse_func)(structdevice_node*me,void*data);-void*traverse_pci_devices(structdevice_node*start,traverse_funcpre,-void*data);+void*pci_traverse_device_nodes(structdevice_node*start,+void*(*fn)(structdevice_node*,void*),+void*data);void*traverse_pci_dn(structpci_dn*root,void*(*fn)(structpci_dn*,void*),void*data);
@@ -388,8 +389,11 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,if(classp)class=of_read_number(classp,1);-if(pre&&((ret=pre(dn,data))!=NULL))-returnret;+if(fn){+ret=fn(dn,data);+if(ret)+returnret;+}/* If we are a PCI bridge, go down */if(dn->child&&((class>>8)==PCI_CLASS_BRIDGE_PCI||
@@ -487,7 +492,7 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb)}/* Update dn->phb ptrs for new phb and children devices */-traverse_pci_devices(dn,add_pdn,phb);+pci_traverse_device_nodes(dn,add_pdn,phb);}/**
@@ -305,7 +305,7 @@ static int msi_quota_for_device(struct pci_dev *dev, int request)memset(&counts,0,sizeof(structmsi_counts));/* Work out how many devices we have below this PE */-traverse_pci_devices(pe_dn,count_non_bridge_devices,&counts);+pci_traverse_device_nodes(pe_dn,count_non_bridge_devices,&counts);if(counts.num_devices==0){pr_err("rtas_msi: found 0 devices under PE for %s\n",
@@ -320,7 +320,7 @@ static int msi_quota_for_device(struct pci_dev *dev, int request)/* else, we have some more calculating to do */counts.requestor=pci_device_to_OF_node(dev);counts.request=request;-traverse_pci_devices(pe_dn,count_spare_msis,&counts);+pci_traverse_device_nodes(pe_dn,count_spare_msis,&counts);/* If the quota isn't an integer multiple of the total, we can*usetheremainderasspareMSIsforanyonethatwantsthem.*/
The function pnv_pci_reset_secondary_bus() is called like below.
It's impossible for call the function on root bus. So it's safe
to remove the root bus case in the function. No functional changes
introduced.
pci_parent_bus_reset() / pci_bus_reset() / pci_try_reset_bus()
pci_reset_bridge_secondary_bus()
pcibios_reset_secondary_bus()
pnv_pci_reset_secondary_bus()
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Daniel Axtens <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/platforms/powernv/eeh-powernv.c | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
This moves pci_find_bus_by_node() from arch/powerpc/platforms/
pseries/pci_dlpar.c to arch/powerpc/kernel/pci-hotplug.c so that
the function can be used by pSeries and PowerNV platform at the
same time. Also, below cleanup applied. No functional changes
introduced.
* Remove variable "busdn" in find_bus_among_children()
* Use PCI_DN() to convert device node to pci_dn
Signed-off-by: Gavin Shan <redacted>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/pci-hotplug.c | 29 ++++++++++++++++++++++++++++
arch/powerpc/platforms/pseries/pci_dlpar.c | 31 ------------------------------
2 files changed, 29 insertions(+), 31 deletions(-)
@@ -257,7 +257,7 @@ static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn)#endif/** Find the bus corresponding to the indicated device node */-externstructpci_bus*pcibios_find_pci_bus(structdevice_node*dn);+externstructpci_bus*pci_find_bus_by_node(structdevice_node*dn);/** Remove all of the PCI devices under this bus */externvoidpci_hp_remove_devices(structpci_bus*bus);
@@ -175,7 +175,7 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)structpci_dev*dev;structpci_controller*phb;-if(pcibios_find_pci_bus(dn))+if(pci_find_bus_by_node(dn))return-EINVAL;/* Add pci bus */
@@ -212,7 +212,7 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)structpci_dn*pdn;intrc=0;-if(!pcibios_find_pci_bus(dn))+if(!pci_find_bus_by_node(dn))return-EINVAL;/* If pci slot is hotpluggable, use hotplug to remove it */
@@ -356,7 +356,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)pci_lock_rescan_remove();-bus=pcibios_find_pci_bus(dn);+bus=pci_find_bus_by_node(dn);if(!bus){ret=-EINVAL;gotoout;
@@ -93,7 +93,7 @@ int rpaphp_enable_slot(struct slot *slot)if(rc)returnrc;-bus=pcibios_find_pci_bus(slot->dn);+bus=pci_find_bus_by_node(slot->dn);if(!bus){err("%s: no pci_bus for dn %s\n",__func__,slot->dn->full_name);return-EINVAL;
When unplugging PCI devices, their parent PEs might be offline.
The consumed M64 resource by the PEs should be released at that
time. As we track M32 segment consumption, this introduces an
array to the PHB to track the mapping between M64 segment and
PE number.
Note: M64 mapping isn't covered by pnv_ioda_setup_pe_seg() as
IODA2 doesn't support the mapping explicitly while it's supported
on IODA1. Until now, no M64 is supported on IODA1 in software.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 10 ++++++++--
arch/powerpc/platforms/powernv/pci.h | 1 +
2 files changed, 9 insertions(+), 2 deletions(-)
@@ -3340,6 +3341,8 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,/* Allocate aux data & arrays. We don't have IO ports on PHB3 */size=_ALIGN_UP(phb->ioda.total_pe_num/8,sizeof(unsignedlong));+m64map_off=size;+size+=phb->ioda.total_pe_num*sizeof(phb->ioda.m64_segmap[0]);m32map_off=size;size+=phb->ioda.total_pe_num*sizeof(phb->ioda.m32_segmap[0]);if(phb->type==PNV_PHB_IODA1){
This drops unnecessary nested if statements in pnv_eeh_reset() to
improve the code readability. After the changes, the unused local
variable "ret" is dropped as well. No logical changes introduced.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Andrew Donnellan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/platforms/powernv/eeh-powernv.c | 67 +++++++++++++---------------
1 file changed, 31 insertions(+), 36 deletions(-)
This cleans up on below data struct instances to use tab instead of
space indent of statement to avoid complains from scripts/checkpatch.pl.
No logical changes introduced.
@pnv_pci_ioda_controller_ops
@pnv_npu_ioda_controller_ops
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Daniel Axtens <redacted>
Reviewed-by: Andrew Donnellan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 36 +++++++++++++++----------------
1 file changed, 18 insertions(+), 18 deletions(-)
In current implementation, the DMA32 segments required by one specific
PE isn't calculated with the information hold in the PE independently.
It conflicts with the PCI hotplug design: PE centralized, meaning the
PE's DMA32 segments should be calculated from the information hold in
the PE independently.
This introduces an array (@dma32_segmap) for every PHB to track the
DMA32 segmeng usage. Besides, this moves the logic calculating PE's
consumed DMA32 segments to pnv_pci_ioda1_setup_dma_pe() so that PE's
DMA32 segments are calculated/allocated from the information hold in
the PE (DMA32 weight). Also the logic is improved: we try to allocate
as much DMA32 segments as we can. It's acceptable that number of DMA32
segments less than the expected number are allocated.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 110 ++++++++++++++++--------------
arch/powerpc/platforms/powernv/pci.h | 7 +-
2 files changed, 61 insertions(+), 56 deletions(-)
@@ -2542,73 +2576,34 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,staticvoidpnv_ioda_setup_dma(structpnv_phb*phb){structpci_controller*hose=phb->hose;-unsignedintweight,total_weight,dma_pe_count;-unsignedintresidual,remaining,segs,base;structpnv_ioda_pe*pe;--total_weight=0;-pci_walk_bus(phb->hose->bus,pnv_pci_ioda_dev_dma_weight,-&total_weight);--dma_pe_count=0;-list_for_each_entry(pe,&phb->ioda.pe_list,list){-weight=pnv_pci_ioda_pe_dma_weight(pe);-if(weight>0)-dma_pe_count++;-}+unsignedintweight;/* If we have more PE# than segments available, hand out one*perPEuntilwerunoutandlettherestfail.Ifnot,*thenweassignatleastonesegmentperPE,plusmorebased*ontheamountofdevicesunderthatPE*/-if(dma_pe_count>phb->ioda.tce32_count)-residual=0;-else-residual=phb->ioda.tce32_count-dma_pe_count;--pr_info("PCI: Domain %04x has %ld available 32-bit DMA segments\n",-hose->global_number,phb->ioda.tce32_count);-pr_info("PCI: %d PE# for a total weight of %d\n",-dma_pe_count,total_weight);+pr_info("PCI: Domain %04x has %d available 32-bit DMA segments\n",+hose->global_number,phb->ioda.dma32_count);pnv_pci_ioda_setup_opal_tce_kill(phb);-/* Walk our PE list and configure their DMA segments, hand them-*outonebasesegmentplusanyresidualsegmentsbasedon-*weight-*/-remaining=phb->ioda.tce32_count;-base=0;+/* Walk our PE list and configure their DMA segments */list_for_each_entry(pe,&phb->ioda.pe_list,list){weight=pnv_pci_ioda_pe_dma_weight(pe);if(!weight)continue;-if(!remaining){-pe_warn(pe,"No DMA32 resources available\n");-continue;-}-segs=1;-if(residual){-segs+=((weight*residual)+(total_weight/2))/-total_weight;-if(segs>remaining)-segs=remaining;-}-/**ForIODA2compliantPHB3,weneedn'tcareabouttheweight.*Theallavailable32-bitsDMAspacewillbeassignedto*thespecificPE.*/if(phb->type==PNV_PHB_IODA1){-pe_info(pe,"DMA weight %d, assigned %d DMA32 segments\n",-weight,segs);-pnv_pci_ioda1_setup_dma_pe(phb,pe,base,segs);+pnv_pci_ioda1_setup_dma_pe(phb,pe);}elseif(phb->type==PNV_PHB_IODA2){pe_info(pe,"Assign DMA32 space\n");-segs=0;pnv_pci_ioda2_setup_dma_pe(phb,pe);}elseif(phb->type==PNV_PHB_NPU){/*
@@ -3413,6 +3406,10 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,phb->ioda.io_segsize=phb->ioda.io_size/phb->ioda.total_pe_num;phb->ioda.io_pci_base=0;/* XXX calculate this ? */+/* Calculate how many 32-bit TCE segments we have */+phb->ioda.dma32_count=phb->ioda.m32_pci_base/+PNV_IODA1_DMA32_SEGSIZE;+/* Allocate aux data & arrays. We don't have IO ports on PHB3 */size=_ALIGN_UP(phb->ioda.total_pe_num/8,sizeof(unsignedlong));m64map_off=size;
@@ -3445,7 +3449,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,mutex_init(&phb->ioda.pe_list_mutex);/* Calculate how many 32-bit TCE segments we have */-phb->ioda.tce32_count=phb->ioda.m32_pci_base/+phb->ioda.dma32_count=phb->ioda.m32_pci_base/PNV_IODA1_DMA32_SEGSIZE;#if 0 /* We should really do that ... */
This renames pcibios_{add,remove}_pci_devices() to avoid conflicts
with names of the weak functions in PCI subsystem, which have the
prefix "pcibios". No logical changes introduced.
I'm guessing this is just protecting against future weak PCI subsystem
functions that may get these names? In other words none of these functions
currently exist as weak PCI subsystem functions and hence aren't called from
the PCI subsystem?
If so this just looks like a simple rename.
Reviewed-By: Alistair Popple <redacted>
extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
/** Remove all of the PCI devices under this bus */
-extern void pcibios_remove_pci_devices(struct pci_bus *bus);
+extern void pci_hp_remove_devices(struct pci_bus *bus);
/** Discover new pci devices under this bus, and add them */
-extern void pcibios_add_pci_devices(struct pci_bus *bus);
+extern void pci_hp_add_devices(struct pci_bus *bus);
extern void isa_bridge_find_early(struct pci_controller *hose);
@@ -621,7 +621,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct
pci_bus *bus,
quoted hunk
* We don't remove the corresponding PE instances because
* we need the information afterwords. The attached EEH
* devices are expected to be attached soon when calling
- * into pcibios_add_pci_devices().
+ * into pci_hp_add_devices().
*/
eeh_pe_state_mark(pe, EEH_PE_KEEP);
if (bus) {
@@ -630,7 +630,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct
@@ -38,20 +38,20 @@ void pcibios_release_device(struct pci_dev *dev)}/**-*pcibios_remove_pci_devices-removealldevicesunderthisbus+*pci_hp_remove_devices-removealldevicesunderthisbus*@bus:theindicatedPCIbus**RemoveallofthePCIdevicesunderthisbusbothfromthe*linuxpcidevicetree,andfromthepowerpcEEHaddresscache.*/-voidpcibios_remove_pci_devices(structpci_bus*bus)+voidpci_hp_remove_devices(structpci_bus*bus){structpci_dev*dev,*tmp;structpci_bus*child_bus;/* First go down child busses */list_for_each_entry(child_bus,&bus->children,node)-pcibios_remove_pci_devices(child_bus);+pci_hp_remove_devices(child_bus);pr_debug("PCI: Removing devices on bus %04x:%02x\n",pci_domain_nr(bus),bus->number);
Currently, there is one macro (TCE32_TABLE_SIZE) representing the
TCE table size for one DMA32 segment. The constant representing
the DMA32 segment size (1 << 28) is still used in the code.
This defines PNV_IODA1_DMA32_SEGSIZE representing one DMA32
segment size. the TCE table size can be calcualted when the page
has fixed 4KB size. So all the related calculation depends on one
macro (PNV_IODA1_DMA32_SEGSIZE). No logical changes introduced.
Looks ok to me.
Reviewed-By: Alistair Popple <redacted>
@@ -2057,29 +2055,34 @@ static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb,/* Grab a 32-bit TCE table */pe->tce32_seg=base;pe_info(pe," Setting up 32-bit TCE table at %08x..%08x\n",-(base<<28),((base+segs)<<28)-1);+base*PNV_IODA1_DMA32_SEGSIZE,+(base+segs)*PNV_IODA1_DMA32_SEGSIZE-1);/* XXX Currently, we allocate one big contiguous table for the*TCEs.Weonlyreallyneedonechunkper256MofTCEspace*(iepersegment)butthat'sanoptimizationforlater,it*requiressomeaddedsmartswithourget/put_tceimplementation+*+*EachTCEpageis4KBinsizeandeachTCEentryoccupies8+*bytes*/+tce32_segsz=PNV_IODA1_DMA32_SEGSIZE>>(IOMMU_PAGE_SHIFT_4K-3);tce_mem=alloc_pages_node(phb->hose->node,GFP_KERNEL,-get_order(TCE32_TABLE_SIZE*segs));+get_order(tce32_segsz*segs));if(!tce_mem){pe_err(pe," Failed to allocate a 32-bit TCE memory\n");gotofail;}addr=page_address(tce_mem);-memset(addr,0,TCE32_TABLE_SIZE*segs);+memset(addr,0,tce32_segsz*segs);/* Configure HW */for(i=0;i<segs;i++){rc=opal_pci_map_pe_dma_window(phb->opal_id,pe->pe_number,base+i,1,-__pa(addr)+TCE32_TABLE_SIZE*i,-TCE32_TABLE_SIZE,0x1000);+__pa(addr)+tce32_segsz*i,+tce32_segsz,IOMMU_PAGE_SIZE_4K);if(rc){pe_err(pe," Failed to configure 32-bit TCE table,"" err %ld\n",rc);
@@ -3456,7 +3460,8 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,mutex_init(&phb->ioda.pe_list_mutex);/* Calculate how many 32-bit TCE segments we have */-phb->ioda.tce32_count=phb->ioda.m32_pci_base>>28;+phb->ioda.tce32_count=phb->ioda.m32_pci_base/+PNV_IODA1_DMA32_SEGSIZE;#if 0 /* We should really do that ... */rc=opal_pci_set_phb_mem_window(opal->phb_id,
pnv_ioda_setup_pe_seg() associates the IO and M32 segments with the
owner PE. The code mapping segments should be fixed and immune from
logic changes introduced to pnv_ioda_setup_pe_seg().
This moves the code mapping segments to helper pnv_ioda_setup_pe_res().
The data type for @rc is changed to "int64_t". Also, argument @hose is
removed from pnv_ioda_setup_pe() as it can be got from @pe. No functional
changes introduced.
Signed-off-by: Gavin Shan <redacted>
g IO segment#%d to PE#%d\n",
+ __func__, rc, index, pe->pe_number);
+ break;
+ }
+
+ region.start += phb->ioda.io_segsize;
+ index++;
+ }
+ } else if ((res->flags & IORESOURCE_MEM) &&
+ !pnv_pci_is_mem_pref_64(res->flags)) {
+ region.start = res->start -
+ phb->hose->mem_offset[0] -
+ phb->ioda.m32_pci_base;
+ region.end = res->end -
+ phb->hose->mem_offset[0] -
+ phb->ioda.m32_pci_base;
+ index = region.start / phb->ioda.m32_segsize;
+
+ while (index < phb->ioda.total_pe_num &&
+ region.start <= region.end) {
+ phb->ioda.m32_segmap[index] = pe->pe_number;
+ rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+ pe->pe_number, OPAL_M32_WINDOW_TYPE, 0, index);
+ if (rc != OPAL_SUCCESS) {
+ pr_err("%s: Error %lld mapping M32 segment#%d to PE#%d",
+ __func__, rc, index, pe->pe_number);
+ break;
+ }
+
+ region.start += phb->ioda.m32_segsize;
+ index++;
+ }
+ }
+}
+
/*
* This function is supposed to be called on basis of PE from top
* to bottom style. So the the I/O or MMIO segment assigned to
* parent PE could be overrided by its child PEs if necessary.
*/
-static void pnv_ioda_setup_pe_seg(struct pci_controller *hose,
- struct pnv_ioda_pe *pe)
+static void pnv_ioda_setup_pe_seg(struct pnv_ioda_pe *pe)
{
- struct pnv_phb *phb = hose->private_data;
- struct pci_bus_region region;
struct resource *res;
- int i, index;
- int rc;
+ int i;
/*
* NOTE: We only care PCI bus based PE for now. For PCI
There are two arrays for IO and M32 segment maps on every PHB.
The index of the arrays are segment number and the value stored
in the corresponding element is PE number, indicating the segment
is assigned to the PE. Initially, all elements in those two arrays
are zeroes, meaning all segments are assigned to PE#0. It's wrong.
This fixes the initial values in the elements of those two arrays
to IODA_INVALID_PE, meaning all segments aren't assigned to any
PE.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
aux = memblock_virt_alloc(size, 0);
phb->ioda.pe_alloc = aux;
phb->ioda.m32_segmap = aux + m32map_off;
- if (phb->type == PNV_PHB_IODA1)
+ for (segno = 0; segno < phb->ioda.total_pe_num; segno++)
These arrays are indexed by segment number but the upper bound is the total
number of PEs. Does IODA1 & IODA2 hardware always have the same number of PE#s
and segments? Is there any chance there could be more or less PE#s
(total_pe_num) than segments?
- Alistair
+ phb->ioda.m32_segmap[segno] = IODA_INVALID_PE;
+ if (phb->type == PNV_PHB_IODA1) {
phb->ioda.io_segmap = aux + iomap_off;
+ for (segno = 0; segno < phb->ioda.total_pe_num; segno++)
+ phb->ioda.io_segmap[segno] = IODA_INVALID_PE;
+ }
phb->ioda.pe_array = aux + pemap_off;
set_bit(phb->ioda.reserved_pe_idx, phb->ioda.pe_alloc);
I had a quick look at the surrounding code and couldn't see anything obvious
that would result in a behaviour change.
Reviewed-By: Alistair Popple <redacted>
On Tue, 3 May 2016 15:41:25 Gavin Shan wrote:
quoted hunk
This changes the data type of PE number from "int" to "unsigned int"
in order to match the fact PE number is never negative:
* The number of PE to which the specified PCI device is attached.
* The PE number map for SRIOV VFs.
* The returned PE number from pnv_ioda_alloc_pe().
* The returned PE number from pnv_ioda2_pick_m64_pe().
Suggested-by: Alexey Kardashevskiy <redacted>
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 6 +++---
arch/powerpc/platforms/powernv/pci-ioda.c | 8 ++++----
arch/powerpc/platforms/powernv/pci.c | 2 +-
arch/powerpc/platforms/powernv/pci.h | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
@@ -209,14 +209,14 @@ struct pci_dn {#ifdef CONFIG_EEHstructeeh_dev*edev;/* eeh device */#endif-#define IODA_INVALID_PE (-1)+#define IODA_INVALID_PE 0xFFFFFFFF#ifdef CONFIG_PPC_POWERNV-intpe_number;+unsignedintpe_number;intvf_index;/* VF index in the PF */#ifdef CONFIG_PCI_IOVu16vfs_expanded;/* number of VFs IOV BAR expanded */u16num_vfs;/* number of VFs enabled*/-int*pe_num_map;/* PE# for the first VF PE or array */+unsignedint*pe_num_map;/* PE# for the first VF PE or array */boolm64_single_mode;/* Use M64 BAR in Single Mode */#define IODA_INVALID_M64 (-1)int(*m64_map)[PCI_SRIOV_NUM_BARS];
struct pci_controller *hose = pci_bus_to_host(bus);
struct pnv_phb *phb = hose->private_data;
struct pnv_ioda_pe *pe;
- int pe_num = IODA_INVALID_PE;
+ unsigned int pe_num = IODA_INVALID_PE;
/* Check if PE is determined by M64 */
if (phb->pick_m64_pe)
On Wed, May 04, 2016 at 01:31:04PM +1000, Alistair Popple wrote:
On Tue, 3 May 2016 15:41:26 Gavin Shan wrote:
quoted
There are two arrays for IO and M32 segment maps on every PHB.
The index of the arrays are segment number and the value stored
in the corresponding element is PE number, indicating the segment
is assigned to the PE. Initially, all elements in those two arrays
are zeroes, meaning all segments are assigned to PE#0. It's wrong.
This fixes the initial values in the elements of those two arrays
to IODA_INVALID_PE, meaning all segments aren't assigned to any
PE.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
aux = memblock_virt_alloc(size, 0);
phb->ioda.pe_alloc = aux;
phb->ioda.m32_segmap = aux + m32map_off;
- if (phb->type == PNV_PHB_IODA1)
+ for (segno = 0; segno < phb->ioda.total_pe_num; segno++)
These arrays are indexed by segment number but the upper bound is the total
number of PEs. Does IODA1 & IODA2 hardware always have the same number of PE#s
and segments? Is there any chance there could be more or less PE#s
(total_pe_num) than segments?
Alistair, thanks for review the code in time. The total number of M32 segments
and PEs are always equal on IODA1/IODA2.
Thanks,
Gavin
- Alistair
quoted
+ phb->ioda.m32_segmap[segno] = IODA_INVALID_PE;
+ if (phb->type == PNV_PHB_IODA1) {
phb->ioda.io_segmap = aux + iomap_off;
+ for (segno = 0; segno < phb->ioda.total_pe_num; segno++)
+ phb->ioda.io_segmap[segno] = IODA_INVALID_PE;
+ }
phb->ioda.pe_array = aux + pemap_off;
set_bit(phb->ioda.reserved_pe_idx, phb->ioda.pe_alloc);
From: Andrew Donnellan <hidden> Date: 2016-05-04 04:44:11
On 03/05/16 15:41, Gavin Shan wrote:
This renames pcibios_{add,remove}_pci_devices() to avoid conflicts
with names of the weak functions in PCI subsystem, which have the
prefix "pcibios". No logical changes introduced.
Signed-off-by: Gavin Shan <redacted>
Looks fine to me.
Reviewed-by: Andrew Donnellan <redacted>
@@ -260,10 +260,10 @@ static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn)externstructpci_bus*pcibios_find_pci_bus(structdevice_node*dn);/** Remove all of the PCI devices under this bus */-externvoidpcibios_remove_pci_devices(structpci_bus*bus);+externvoidpci_hp_remove_devices(structpci_bus*bus);/** Discover new pci devices under this bus, and add them */-externvoidpcibios_add_pci_devices(structpci_bus*bus);+externvoidpci_hp_add_devices(structpci_bus*bus);externvoidisa_bridge_find_early(structpci_controller*hose);
@@ -38,20 +38,20 @@ void pcibios_release_device(struct pci_dev *dev)}/**-*pcibios_remove_pci_devices-removealldevicesunderthisbus+*pci_hp_remove_devices-removealldevicesunderthisbus*@bus:theindicatedPCIbus**RemoveallofthePCIdevicesunderthisbusbothfromthe*linuxpcidevicetree,andfromthepowerpcEEHaddresscache.*/-voidpcibios_remove_pci_devices(structpci_bus*bus)+voidpci_hp_remove_devices(structpci_bus*bus){structpci_dev*dev,*tmp;structpci_bus*child_bus;/* First go down child busses */list_for_each_entry(child_bus,&bus->children,node)-pcibios_remove_pci_devices(child_bus);+pci_hp_remove_devices(child_bus);pr_debug("PCI: Removing devices on bus %04x:%02x\n",pci_domain_nr(bus),bus->number);
On Wed, May 04, 2016 at 02:10:47PM +1000, Alistair Popple wrote:
On Tue, 3 May 2016 15:41:37 Gavin Shan wrote:
quoted
This renames pcibios_{add,remove}_pci_devices() to avoid conflicts
with names of the weak functions in PCI subsystem, which have the
prefix "pcibios". No logical changes introduced.
I'm guessing this is just protecting against future weak PCI subsystem
functions that may get these names? In other words none of these functions
currently exist as weak PCI subsystem functions and hence aren't called from
the PCI subsystem?
If so this just looks like a simple rename.
Thanks for review, Alistair. Yes, it's simple rename. In PCI subsystem,
the weak funtion names have prefix pcibios_. Those functions are not weak
functions. Also, The functions are exported so that they can be used in PCI
hotplug driver (module) and it's worthy to have better names for them.
Those functions are called in PCI hotplug path to accomodate request from
EEH or PCI hotplug driver.
Thanks,
Gavin
extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
/** Remove all of the PCI devices under this bus */
-extern void pcibios_remove_pci_devices(struct pci_bus *bus);
+extern void pci_hp_remove_devices(struct pci_bus *bus);
/** Discover new pci devices under this bus, and add them */
-extern void pcibios_add_pci_devices(struct pci_bus *bus);
+extern void pci_hp_add_devices(struct pci_bus *bus);
extern void isa_bridge_find_early(struct pci_controller *hose);
@@ -621,7 +621,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct
pci_bus *bus,
quoted
* We don't remove the corresponding PE instances because
* we need the information afterwords. The attached EEH
* devices are expected to be attached soon when calling
- * into pcibios_add_pci_devices().
+ * into pci_hp_add_devices().
*/
eeh_pe_state_mark(pe, EEH_PE_KEEP);
if (bus) {
@@ -630,7 +630,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct
@@ -38,20 +38,20 @@ void pcibios_release_device(struct pci_dev *dev)}/**-*pcibios_remove_pci_devices-removealldevicesunderthisbus+*pci_hp_remove_devices-removealldevicesunderthisbus*@bus:theindicatedPCIbus**RemoveallofthePCIdevicesunderthisbusbothfromthe*linuxpcidevicetree,andfromthepowerpcEEHaddresscache.*/-voidpcibios_remove_pci_devices(structpci_bus*bus)+voidpci_hp_remove_devices(structpci_bus*bus){structpci_dev*dev,*tmp;structpci_bus*child_bus;/* First go down child busses */list_for_each_entry(child_bus,&bus->children,node)-pcibios_remove_pci_devices(child_bus);+pci_hp_remove_devices(child_bus);pr_debug("PCI: Removing devices on bus %04x:%02x\n",pci_domain_nr(bus),bus->number);
From: Andrew Donnellan <hidden> Date: 2016-05-04 04:57:52
On 03/05/16 15:41, Gavin Shan wrote:
This moves pci_find_bus_by_node() from arch/powerpc/platforms/
pseries/pci_dlpar.c to arch/powerpc/kernel/pci-hotplug.c so that
the function can be used by pSeries and PowerNV platform at the
same time. Also, below cleanup applied. No functional changes
introduced.
* Remove variable "busdn" in find_bus_among_children()
* Use PCI_DN() to convert device node to pci_dn
Signed-off-by: Gavin Shan <redacted>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Looks good to me
Reviewed-by: Andrew Donnellan <redacted>
This enables M64 window on P7IOC, which has been enabled on PHB3.
Have we tested that this works with an adaptor? This looks to be enabling
support for something that didn't previously work (64-bit BARs on P7IOC)?
Regards,
Alistair
Different from PHB3 where 16 M64 BARs are supported and each of
them can be owned by one particular PE# exclusively or divided
evenly to 256 segments, every P7IOC PHB has 16 M64 BARs and each
of them are divided to 8 segments. So every P7IOC PHB supports
128 M64 segments in total. P7IOC has M64DT, which helps mapping
one particular M64 segment# to arbitrary PE#. PHB3 doesn't have
M64DT, indicating that one M64 segment can only be pinned to the
fixed PE#.
In order to unified M64 support M64 on P7IOC and PHB3, we just
provide 128 M64 segments on every P7IOC PHB and each of them is
pinned to the fixed PE# by bypassing the function of M64DT. In
turn, we just need different phb->init_m64() for P7IOC and PHB3
and maps M64 segment in pnv_ioda_reserve_m64_pe() for P7IOC, most
of the code are shared by them.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 89
}
}
+static int pnv_ioda1_init_m64(struct pnv_phb *phb)
+{
+ struct resource *r;
+ int index;
+
+ /*
+ * There are 16 M64 BARs, each of which has 8 segments. So
+ * there are as many M64 segments as the maximum number of
+ * PEs, which is 128.
+ */
+ for (index = 0; index < PNV_IODA1_M64_NUM; index++) {
+ unsigned long base, segsz = phb->ioda.m64_segsize;
+ int64_t rc;
+
+ base = phb->ioda.m64_base +
+ index * PNV_IODA1_M64_SEGS * segsz;
+ rc = opal_pci_set_phb_mem_window(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index, base, 0,
+ PNV_IODA1_M64_SEGS * segsz);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld setting M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+
+ rc = opal_pci_phb_mmio_enable(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index,
+ OPAL_ENABLE_M64_SPLIT);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld enabling M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+ }
+
+ /*
+ * Exclude the segment used by the reserved PE, which
+ * is expected to be 0 or last supported PE#.
+ */
+ r = &phb->hose->mem_resources[1];
+ if (phb->ioda.reserved_pe_idx == 0)
+ r->start += phb->ioda.m64_segsize;
+ else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
+ r->end -= phb->ioda.m64_segsize;
+ else
+ pr_warn(" Cannot cut M64 segment for reserved PE#%d\n",
+ phb->ioda.reserved_pe_idx);
+
+ return 0;
+
+fail:
+ for ( ; index >= 0; index--)
+ opal_pci_phb_mmio_enable(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index, OPAL_DISABLE_M64);
+
+ return -EIO;
+}
+
static void pnv_ioda_reserve_m64_pe(struct pci_bus *bus,
unsigned long *pe_bitmap,
bool all)
@@ -315,6 +376,26 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus
*bus, bool all)
pe->master = master_pe;
list_add_tail(&pe->list, &master_pe->slaves);
}
+
+ /*
+ * P7IOC supports M64DT, which helps mapping M64 segment
+ * to one particular PE#. However, PHB3 has fixed mapping
+ * between M64 segment and PE#. In order to have same logic
+ * for P7IOC and PHB3, we enforce fixed mapping between M64
+ * segment and PE# on P7IOC.
+ */
+ if (phb->type == PNV_PHB_IODA1) {
+ int64_t rc;
+
+ rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+ pe->pe_number, OPAL_M64_WINDOW_TYPE,
+ pe->pe_number / PNV_IODA1_M64_SEGS,
+ pe->pe_number % PNV_IODA1_M64_SEGS);
+ if (rc != OPAL_SUCCESS)
+ pr_warn("%s: Error %lld mapping M64 for
On Wed, May 04, 2016 at 03:17:51PM +1000, Alistair Popple wrote:
On Tue, 3 May 2016 15:41:31 Gavin Shan wrote:
quoted
This enables M64 window on P7IOC, which has been enabled on PHB3.
Have we tested that this works with an adaptor? This looks to be enabling
support for something that didn't previously work (64-bit BARs on P7IOC)?
The M64 isn't supported on P7IOC before, meaning the PCI device's M64
BAR is covered by PHB's M32 window. With the patch applied, the PCI
device's M64 BAR is covered by PHB's M64 window as below log I got
from vpl4. The kernel including the series of patches boots successfully
on vpl4 and all looks normal.
[ 0.246110] pci 0000:60:00.0: BAR 2: assigned [mem 0x3da810000000-0x3da810ffffff 64bit pref]
[ 0.246218] pci 0000:60:00.0: BAR 0: assigned [mem 0x3da081000000-0x3da08103ffff 64bit]
[ 0.246306] pci 0000:60:00.0: BAR 6: assigned [mem 0x3da081040000-0x3da08105ffff pref]
[ 0.246392] pci 0000:60 : [PE# 001] Secondary bus 96 associated with PE#1
[ 0.246484] pci 0000:60 : [PE# 001] DMA weight 15 (64), assigned (0) 1 DMA32 segments
[ 0.246552] pci 0000:60 : [PE# 001] Setting up 32-bit TCE table at 00000000..0fffffff
Thanks,
Gavin
Regards,
Alistair
quoted
Different from PHB3 where 16 M64 BARs are supported and each of
them can be owned by one particular PE# exclusively or divided
evenly to 256 segments, every P7IOC PHB has 16 M64 BARs and each
of them are divided to 8 segments. So every P7IOC PHB supports
128 M64 segments in total. P7IOC has M64DT, which helps mapping
one particular M64 segment# to arbitrary PE#. PHB3 doesn't have
M64DT, indicating that one M64 segment can only be pinned to the
fixed PE#.
In order to unified M64 support M64 on P7IOC and PHB3, we just
provide 128 M64 segments on every P7IOC PHB and each of them is
pinned to the fixed PE# by bypassing the function of M64DT. In
turn, we just need different phb->init_m64() for P7IOC and PHB3
and maps M64 segment in pnv_ioda_reserve_m64_pe() for P7IOC, most
of the code are shared by them.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 89
}
}
+static int pnv_ioda1_init_m64(struct pnv_phb *phb)
+{
+ struct resource *r;
+ int index;
+
+ /*
+ * There are 16 M64 BARs, each of which has 8 segments. So
+ * there are as many M64 segments as the maximum number of
+ * PEs, which is 128.
+ */
+ for (index = 0; index < PNV_IODA1_M64_NUM; index++) {
+ unsigned long base, segsz = phb->ioda.m64_segsize;
+ int64_t rc;
+
+ base = phb->ioda.m64_base +
+ index * PNV_IODA1_M64_SEGS * segsz;
+ rc = opal_pci_set_phb_mem_window(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index, base, 0,
+ PNV_IODA1_M64_SEGS * segsz);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld setting M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+
+ rc = opal_pci_phb_mmio_enable(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index,
+ OPAL_ENABLE_M64_SPLIT);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld enabling M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+ }
+
+ /*
+ * Exclude the segment used by the reserved PE, which
+ * is expected to be 0 or last supported PE#.
+ */
+ r = &phb->hose->mem_resources[1];
+ if (phb->ioda.reserved_pe_idx == 0)
+ r->start += phb->ioda.m64_segsize;
+ else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
+ r->end -= phb->ioda.m64_segsize;
+ else
+ pr_warn(" Cannot cut M64 segment for reserved PE#%d\n",
+ phb->ioda.reserved_pe_idx);
+
+ return 0;
+
+fail:
+ for ( ; index >= 0; index--)
+ opal_pci_phb_mmio_enable(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index, OPAL_DISABLE_M64);
+
+ return -EIO;
+}
+
static void pnv_ioda_reserve_m64_pe(struct pci_bus *bus,
unsigned long *pe_bitmap,
bool all)
@@ -315,6 +376,26 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus
*bus, bool all)
quoted
pe->master = master_pe;
list_add_tail(&pe->list, &master_pe->slaves);
}
+
+ /*
+ * P7IOC supports M64DT, which helps mapping M64 segment
+ * to one particular PE#. However, PHB3 has fixed mapping
+ * between M64 segment and PE#. In order to have same logic
+ * for P7IOC and PHB3, we enforce fixed mapping between M64
+ * segment and PE# on P7IOC.
+ */
+ if (phb->type == PNV_PHB_IODA1) {
+ int64_t rc;
+
+ rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+ pe->pe_number, OPAL_M64_WINDOW_TYPE,
+ pe->pe_number / PNV_IODA1_M64_SEGS,
+ pe->pe_number % PNV_IODA1_M64_SEGS);
+ if (rc != OPAL_SUCCESS)
+ pr_warn("%s: Error %lld mapping M64 for
This changes the data type of PE number from "int" to "unsigned int"
in order to match the fact PE number is never negative:
* The number of PE to which the specified PCI device is attached.
* The PE number map for SRIOV VFs.
* The returned PE number from pnv_ioda_alloc_pe().
* The returned PE number from pnv_ioda2_pick_m64_pe().
Suggested-by: Alexey Kardashevskiy <redacted>
Signed-off-by: Gavin Shan <redacted>
@@ -209,14 +209,14 @@ struct pci_dn {#ifdef CONFIG_EEHstructeeh_dev*edev;/* eeh device */#endif-#define IODA_INVALID_PE (-1)+#define IODA_INVALID_PE 0xFFFFFFFF#ifdef CONFIG_PPC_POWERNV-intpe_number;+unsignedintpe_number;intvf_index;/* VF index in the PF */#ifdef CONFIG_PCI_IOVu16vfs_expanded;/* number of VFs IOV BAR expanded */u16num_vfs;/* number of VFs enabled*/-int*pe_num_map;/* PE# for the first VF PE or array */+unsignedint*pe_num_map;/* PE# for the first VF PE or array */boolm64_single_mode;/* Use M64 BAR in Single Mode */#define IODA_INVALID_M64 (-1)int(*m64_map)[PCI_SRIOV_NUM_BARS];
@@ -919,7 +919,7 @@ static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev)structpnv_phb*phb=hose->private_data;structpci_dn*pdn=pci_get_pdn(dev);structpnv_ioda_pe*pe;-intpe_num;+unsignedintpe_num;if(!pdn){pr_err("%s: Device tree node not associated properly\n",
@@ -1010,7 +1010,7 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all)structpci_controller*hose=pci_bus_to_host(bus);structpnv_phb*phb=hose->private_data;structpnv_ioda_pe*pe;-intpe_num=IODA_INVALID_PE;+unsignedintpe_num=IODA_INVALID_PE;/* Check if PE is determined by M64 */if(phb->pick_m64_pe)
On Tue, May 03, 2016 at 03:41:35PM +1000, Gavin Shan wrote:
In current implementation, the DMA32 segments required by one specific
PE isn't calculated with the information hold in the PE independently.
It conflicts with the PCI hotplug design: PE centralized, meaning the
PE's DMA32 segments should be calculated from the information hold in
the PE independently.
This introduces an array (@dma32_segmap) for every PHB to track the
DMA32 segmeng usage. Besides, this moves the logic calculating PE's
consumed DMA32 segments to pnv_pci_ioda1_setup_dma_pe() so that PE's
DMA32 segments are calculated/allocated from the information hold in
the PE (DMA32 weight). Also the logic is improved: we try to allocate
as much DMA32 segments as we can. It's acceptable that number of DMA32
segments less than the expected number are allocated.
Signed-off-by: Gavin Shan <redacted>
This can cause overlapped DMA32 segments to different PEs in some cases.
I already had the fix and hold for posting after discussion with Michael
on how to handle the series tomorrow.
Thanks,
Gavin
static void pnv_ioda_setup_dma(struct pnv_phb *phb)
{
struct pci_controller *hose = phb->hose;
- unsigned int weight, total_weight, dma_pe_count;
- unsigned int residual, remaining, segs, base;
struct pnv_ioda_pe *pe;
-
- total_weight = 0;
- pci_walk_bus(phb->hose->bus, pnv_pci_ioda_dev_dma_weight,
- &total_weight);
-
- dma_pe_count = 0;
- list_for_each_entry(pe, &phb->ioda.pe_list, list) {
- weight = pnv_pci_ioda_pe_dma_weight(pe);
- if (weight > 0)
- dma_pe_count++;
- }
+ unsigned int weight;
/* If we have more PE# than segments available, hand out one
* per PE until we run out and let the rest fail. If not,
* then we assign at least one segment per PE, plus more based
* on the amount of devices under that PE
*/
- if (dma_pe_count > phb->ioda.tce32_count)
- residual = 0;
- else
- residual = phb->ioda.tce32_count - dma_pe_count;
-
- pr_info("PCI: Domain %04x has %ld available 32-bit DMA segments\n",
- hose->global_number, phb->ioda.tce32_count);
- pr_info("PCI: %d PE# for a total weight of %d\n",
- dma_pe_count, total_weight);
+ pr_info("PCI: Domain %04x has %d available 32-bit DMA segments\n",
+ hose->global_number, phb->ioda.dma32_count);
pnv_pci_ioda_setup_opal_tce_kill(phb);
- /* Walk our PE list and configure their DMA segments, hand them
- * out one base segment plus any residual segments based on
- * weight
- */
- remaining = phb->ioda.tce32_count;
- base = 0;
+ /* Walk our PE list and configure their DMA segments */
list_for_each_entry(pe, &phb->ioda.pe_list, list) {
weight = pnv_pci_ioda_pe_dma_weight(pe);
if (!weight)
continue;
- if (!remaining) {
- pe_warn(pe, "No DMA32 resources available\n");
- continue;
- }
- segs = 1;
- if (residual) {
- segs += ((weight * residual) + (total_weight / 2)) /
- total_weight;
- if (segs > remaining)
- segs = remaining;
- }
-
/*
* For IODA2 compliant PHB3, we needn't care about the weight.
* The all available 32-bits DMA space will be assigned to
* the specific PE.
*/
if (phb->type == PNV_PHB_IODA1) {
- pe_info(pe, "DMA weight %d, assigned %d DMA32 segments\n",
- weight, segs);
- pnv_pci_ioda1_setup_dma_pe(phb, pe, base, segs);
+ pnv_pci_ioda1_setup_dma_pe(phb, pe);
} else if (phb->type == PNV_PHB_IODA2) {
pe_info(pe, "Assign DMA32 space\n");
- segs = 0;
pnv_pci_ioda2_setup_dma_pe(phb, pe);
} else if (phb->type == PNV_PHB_NPU) {
/*
mutex_init(&phb->ioda.pe_list_mutex);
/* Calculate how many 32-bit TCE segments we have */
- phb->ioda.tce32_count = phb->ioda.m32_pci_base /
+ phb->ioda.dma32_count = phb->ioda.m32_pci_base /
PNV_IODA1_DMA32_SEGSIZE;
#if 0 /* We should really do that ... */
On Wed, May 04, 2016 at 03:17:51PM +1000, Alistair Popple wrote:
quoted
On Tue, 3 May 2016 15:41:31 Gavin Shan wrote:
quoted
This enables M64 window on P7IOC, which has been enabled on PHB3.
Have we tested that this works with an adaptor? This looks to be enabling
support for something that didn't previously work (64-bit BARs on P7IOC)?
The M64 isn't supported on P7IOC before, meaning the PCI device's M64
BAR is covered by PHB's M32 window. With the patch applied, the PCI
device's M64 BAR is covered by PHB's M64 window as below log I got
from vpl4. The kernel including the series of patches boots successfully
on vpl4 and all looks normal.
So you're changing the way 64-bit BARs work on P7IOC to use a different bit of
the hardware/firmware? This means it could break older systems if there is
an issue with the M64 support. Other than the comments below the code looks
reasonable. However I am assuming you've tested that cards with 64-bit BARs
still function on P7 after this change as I'm not familiar enough to comment on
the specific hardware details, although your comments make sense and match the
code.
Different from PHB3 where 16 M64 BARs are supported and each of
them can be owned by one particular PE# exclusively or divided
evenly to 256 segments, every P7IOC PHB has 16 M64 BARs and each
of them are divided to 8 segments. So every P7IOC PHB supports
128 M64 segments in total. P7IOC has M64DT, which helps mapping
one particular M64 segment# to arbitrary PE#. PHB3 doesn't have
M64DT, indicating that one M64 segment can only be pinned to the
fixed PE#.
In order to unified M64 support M64 on P7IOC and PHB3, we just
provide 128 M64 segments on every P7IOC PHB and each of them is
pinned to the fixed PE# by bypassing the function of M64DT. In
turn, we just need different phb->init_m64() for P7IOC and PHB3
and maps M64 segment in pnv_ioda_reserve_m64_pe() for P7IOC, most
of the code are shared by them.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 89
}
}
+static int pnv_ioda1_init_m64(struct pnv_phb *phb)
+{
+ struct resource *r;
+ int index;
+
+ /*
+ * There are 16 M64 BARs, each of which has 8 segments. So
+ * there are as many M64 segments as the maximum number of
+ * PEs, which is 128.
+ */
+ for (index = 0; index < PNV_IODA1_M64_NUM; index++) {
+ unsigned long base, segsz = phb->ioda.m64_segsize;
+ int64_t rc;
+
+ base = phb->ioda.m64_base +
+ index * PNV_IODA1_M64_SEGS * segsz;
+ rc = opal_pci_set_phb_mem_window(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index, base, 0,
+ PNV_IODA1_M64_SEGS * segsz);
Has firmware always supported OPAL_M64_WINDOW_TYPE for P7IOC? If older versions
don't support it what happens? Do we gracefully fall back to the old mode of
allocating all BARs from the M32 window or does it break?
quoted
quoted
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld setting M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+
+ rc = opal_pci_phb_mmio_enable(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index,
+ OPAL_ENABLE_M64_SPLIT);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld enabling M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+ }
+
+ /*
+ * Exclude the segment used by the reserved PE, which
+ * is expected to be 0 or last supported PE#.
+ */
+ r = &phb->hose->mem_resources[1];
+ if (phb->ioda.reserved_pe_idx == 0)
+ r->start += phb->ioda.m64_segsize;
+ else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
+ r->end -= phb->ioda.m64_segsize;
+ else
+ pr_warn(" Cannot cut M64 segment for reserved PE#%d\n",
+ phb->ioda.reserved_pe_idx);
Should this be a WARN_ON()? If this condition can only exist because a future
programmer changes the reserved_pe_idx then I think it should be a WARN_ON()
as the above message would be too easy to miss.
@@ -315,6 +376,26 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus
*bus, bool all)
quoted
pe->master = master_pe;
list_add_tail(&pe->list, &master_pe->slaves);
}
+
+ /*
+ * P7IOC supports M64DT, which helps mapping M64 segment
+ * to one particular PE#. However, PHB3 has fixed mapping
+ * between M64 segment and PE#. In order to have same logic
+ * for P7IOC and PHB3, we enforce fixed mapping between M64
+ * segment and PE# on P7IOC.
+ */
+ if (phb->type == PNV_PHB_IODA1) {
+ int64_t rc;
+
+ rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+ pe->pe_number, OPAL_M64_WINDOW_TYPE,
+ pe->pe_number / PNV_IODA1_M64_SEGS,
+ pe->pe_number % PNV_IODA1_M64_SEGS);
+ if (rc != OPAL_SUCCESS)
+ pr_warn("%s: Error %lld mapping M64 for
On Thu, May 05, 2016 at 09:53:51AM +1000, Alistair Popple wrote:
On Wed, 4 May 2016 16:48:53 Gavin Shan wrote:
quoted
On Wed, May 04, 2016 at 03:17:51PM +1000, Alistair Popple wrote:
quoted
On Tue, 3 May 2016 15:41:31 Gavin Shan wrote:
quoted
This enables M64 window on P7IOC, which has been enabled on PHB3.
Have we tested that this works with an adaptor? This looks to be enabling
support for something that didn't previously work (64-bit BARs on P7IOC)?
The M64 isn't supported on P7IOC before, meaning the PCI device's M64
BAR is covered by PHB's M32 window. With the patch applied, the PCI
device's M64 BAR is covered by PHB's M64 window as below log I got
from vpl4. The kernel including the series of patches boots successfully
on vpl4 and all looks normal.
So you're changing the way 64-bit BARs work on P7IOC to use a different bit of
the hardware/firmware? This means it could break older systems if there is
an issue with the M64 support. Other than the comments below the code looks
reasonable. However I am assuming you've tested that cards with 64-bit BARs
still function on P7 after this change as I'm not familiar enough to comment on
the specific hardware details, although your comments make sense and match the
code.
Nope, it doesn't rely on changes in firmware. The old firmware enables and
exposes PHB M64 window. The kernel doesn't use it on P7IOC until this patch.
On VPL4, there is a IPR adapter (0000:60:00.0) as below kernel log indicates.
Its BAR#2 is M64 (64-bits prefetchable) BAR. The BAR#2 is covered by PHB's M64
window with this patch. The PHB's M64 window is [0x00003da800000000..0x00003dafffffffff].
After it's applied, the IPR and root filesystem resident in the disk drive out
of it work fine.
Different from PHB3 where 16 M64 BARs are supported and each of
them can be owned by one particular PE# exclusively or divided
evenly to 256 segments, every P7IOC PHB has 16 M64 BARs and each
of them are divided to 8 segments. So every P7IOC PHB supports
128 M64 segments in total. P7IOC has M64DT, which helps mapping
one particular M64 segment# to arbitrary PE#. PHB3 doesn't have
M64DT, indicating that one M64 segment can only be pinned to the
fixed PE#.
In order to unified M64 support M64 on P7IOC and PHB3, we just
provide 128 M64 segments on every P7IOC PHB and each of them is
pinned to the fixed PE# by bypassing the function of M64DT. In
turn, we just need different phb->init_m64() for P7IOC and PHB3
and maps M64 segment in pnv_ioda_reserve_m64_pe() for P7IOC, most
of the code are shared by them.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 89
}
}
+static int pnv_ioda1_init_m64(struct pnv_phb *phb)
+{
+ struct resource *r;
+ int index;
+
+ /*
+ * There are 16 M64 BARs, each of which has 8 segments. So
+ * there are as many M64 segments as the maximum number of
+ * PEs, which is 128.
+ */
+ for (index = 0; index < PNV_IODA1_M64_NUM; index++) {
+ unsigned long base, segsz = phb->ioda.m64_segsize;
+ int64_t rc;
+
+ base = phb->ioda.m64_base +
+ index * PNV_IODA1_M64_SEGS * segsz;
+ rc = opal_pci_set_phb_mem_window(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index, base, 0,
+ PNV_IODA1_M64_SEGS * segsz);
Has firmware always supported OPAL_M64_WINDOW_TYPE for P7IOC? If older versions
don't support it what happens? Do we gracefully fall back to the old mode of
allocating all BARs from the M32 window or does it break?
Old firmware enables and exposes M64 window (OPAL_M64_WINDOW_TYPE), but kernel
doesn't use it until this patch. If the OPAL call fails, errcode is returned.
The caller, pnv_pci_init_ioda_phb(), disables the window. It means the PCI
device M64 BARs will fail back to be covered by M32 window. The path is same
on PHB3 and P7IOC.
quoted
quoted
quoted
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld setting M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+
+ rc = opal_pci_phb_mmio_enable(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index,
+ OPAL_ENABLE_M64_SPLIT);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld enabling M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+ }
+
+ /*
+ * Exclude the segment used by the reserved PE, which
+ * is expected to be 0 or last supported PE#.
+ */
+ r = &phb->hose->mem_resources[1];
+ if (phb->ioda.reserved_pe_idx == 0)
+ r->start += phb->ioda.m64_segsize;
+ else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
+ r->end -= phb->ioda.m64_segsize;
+ else
+ pr_warn(" Cannot cut M64 segment for reserved PE#%d\n",
+ phb->ioda.reserved_pe_idx);
Should this be a WARN_ON()? If this condition can only exist because a future
programmer changes the reserved_pe_idx then I think it should be a WARN_ON()
as the above message would be too easy to miss.
@@ -315,6 +376,26 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus
*bus, bool all)
quoted
pe->master = master_pe;
list_add_tail(&pe->list, &master_pe->slaves);
}
+
+ /*
+ * P7IOC supports M64DT, which helps mapping M64 segment
+ * to one particular PE#. However, PHB3 has fixed mapping
+ * between M64 segment and PE#. In order to have same logic
+ * for P7IOC and PHB3, we enforce fixed mapping between M64
+ * segment and PE# on P7IOC.
+ */
+ if (phb->type == PNV_PHB_IODA1) {
+ int64_t rc;
+
+ rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+ pe->pe_number, OPAL_M64_WINDOW_TYPE,
+ pe->pe_number / PNV_IODA1_M64_SEGS,
+ pe->pe_number % PNV_IODA1_M64_SEGS);
+ if (rc != OPAL_SUCCESS)
+ pr_warn("%s: Error %lld mapping M64 for
Thanks for the clarifications Gavin. Aside from the WARN_ON() (which is not a
major thing) everything looks good.
Reviewed-By: Alistair Popple <redacted>
On Thu, 5 May 2016 10:40:33 Gavin Shan wrote:
On Thu, May 05, 2016 at 09:53:51AM +1000, Alistair Popple wrote:
quoted
On Wed, 4 May 2016 16:48:53 Gavin Shan wrote:
quoted
On Wed, May 04, 2016 at 03:17:51PM +1000, Alistair Popple wrote:
quoted
On Tue, 3 May 2016 15:41:31 Gavin Shan wrote:
quoted
This enables M64 window on P7IOC, which has been enabled on PHB3.
Have we tested that this works with an adaptor? This looks to be enabling
support for something that didn't previously work (64-bit BARs on P7IOC)?
The M64 isn't supported on P7IOC before, meaning the PCI device's M64
BAR is covered by PHB's M32 window. With the patch applied, the PCI
device's M64 BAR is covered by PHB's M64 window as below log I got
from vpl4. The kernel including the series of patches boots successfully
on vpl4 and all looks normal.
So you're changing the way 64-bit BARs work on P7IOC to use a different bit of
the hardware/firmware? This means it could break older systems if there is
an issue with the M64 support. Other than the comments below the code looks
reasonable. However I am assuming you've tested that cards with 64-bit BARs
still function on P7 after this change as I'm not familiar enough to comment on
the specific hardware details, although your comments make sense and match the
code.
Nope, it doesn't rely on changes in firmware. The old firmware enables and
exposes PHB M64 window. The kernel doesn't use it on P7IOC until this patch.
On VPL4, there is a IPR adapter (0000:60:00.0) as below kernel log indicates.
Its BAR#2 is M64 (64-bits prefetchable) BAR. The BAR#2 is covered by PHB's M64
window with this patch. The PHB's M64 window is [0x00003da800000000..0x00003dafffffffff].
After it's applied, the IPR and root filesystem resident in the disk drive out
of it work fine.
Different from PHB3 where 16 M64 BARs are supported and each of
them can be owned by one particular PE# exclusively or divided
evenly to 256 segments, every P7IOC PHB has 16 M64 BARs and each
of them are divided to 8 segments. So every P7IOC PHB supports
128 M64 segments in total. P7IOC has M64DT, which helps mapping
one particular M64 segment# to arbitrary PE#. PHB3 doesn't have
M64DT, indicating that one M64 segment can only be pinned to the
fixed PE#.
In order to unified M64 support M64 on P7IOC and PHB3, we just
provide 128 M64 segments on every P7IOC PHB and each of them is
pinned to the fixed PE# by bypassing the function of M64DT. In
turn, we just need different phb->init_m64() for P7IOC and PHB3
and maps M64 segment in pnv_ioda_reserve_m64_pe() for P7IOC, most
of the code are shared by them.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 89
}
}
+static int pnv_ioda1_init_m64(struct pnv_phb *phb)
+{
+ struct resource *r;
+ int index;
+
+ /*
+ * There are 16 M64 BARs, each of which has 8 segments. So
+ * there are as many M64 segments as the maximum number of
+ * PEs, which is 128.
+ */
+ for (index = 0; index < PNV_IODA1_M64_NUM; index++) {
+ unsigned long base, segsz = phb->ioda.m64_segsize;
+ int64_t rc;
+
+ base = phb->ioda.m64_base +
+ index * PNV_IODA1_M64_SEGS * segsz;
+ rc = opal_pci_set_phb_mem_window(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index, base, 0,
+ PNV_IODA1_M64_SEGS * segsz);
Has firmware always supported OPAL_M64_WINDOW_TYPE for P7IOC? If older versions
don't support it what happens? Do we gracefully fall back to the old mode of
allocating all BARs from the M32 window or does it break?
Old firmware enables and exposes M64 window (OPAL_M64_WINDOW_TYPE), but kernel
doesn't use it until this patch. If the OPAL call fails, errcode is returned.
The caller, pnv_pci_init_ioda_phb(), disables the window. It means the PCI
device M64 BARs will fail back to be covered by M32 window. The path is same
on PHB3 and P7IOC.
quoted
quoted
quoted
quoted
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld setting M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+
+ rc = opal_pci_phb_mmio_enable(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index,
+ OPAL_ENABLE_M64_SPLIT);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld enabling M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+ }
+
+ /*
+ * Exclude the segment used by the reserved PE, which
+ * is expected to be 0 or last supported PE#.
+ */
+ r = &phb->hose->mem_resources[1];
+ if (phb->ioda.reserved_pe_idx == 0)
+ r->start += phb->ioda.m64_segsize;
+ else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
+ r->end -= phb->ioda.m64_segsize;
+ else
+ pr_warn(" Cannot cut M64 segment for reserved PE#%d\n",
+ phb->ioda.reserved_pe_idx);
Should this be a WARN_ON()? If this condition can only exist because a future
programmer changes the reserved_pe_idx then I think it should be a WARN_ON()
as the above message would be too easy to miss.
@@ -315,6 +376,26 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus
*bus, bool all)
quoted
pe->master = master_pe;
list_add_tail(&pe->list, &master_pe->slaves);
}
+
+ /*
+ * P7IOC supports M64DT, which helps mapping M64 segment
+ * to one particular PE#. However, PHB3 has fixed mapping
+ * between M64 segment and PE#. In order to have same logic
+ * for P7IOC and PHB3, we enforce fixed mapping between M64
+ * segment and PE# on P7IOC.
+ */
+ if (phb->type == PNV_PHB_IODA1) {
+ int64_t rc;
+
+ rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+ pe->pe_number, OPAL_M64_WINDOW_TYPE,
+ pe->pe_number / PNV_IODA1_M64_SEGS,
+ pe->pe_number % PNV_IODA1_M64_SEGS);
+ if (rc != OPAL_SUCCESS)
+ pr_warn("%s: Error %lld mapping M64 for
On Wed, May 04, 2016 at 11:20:01PM +1000, Gavin Shan wrote:
On Tue, May 03, 2016 at 03:41:35PM +1000, Gavin Shan wrote:
quoted
In current implementation, the DMA32 segments required by one specific
PE isn't calculated with the information hold in the PE independently.
It conflicts with the PCI hotplug design: PE centralized, meaning the
PE's DMA32 segments should be calculated from the information hold in
the PE independently.
This introduces an array (@dma32_segmap) for every PHB to track the
DMA32 segmeng usage. Besides, this moves the logic calculating PE's
consumed DMA32 segments to pnv_pci_ioda1_setup_dma_pe() so that PE's
DMA32 segments are calculated/allocated from the information hold in
the PE (DMA32 weight). Also the logic is improved: we try to allocate
as much DMA32 segments as we can. It's acceptable that number of DMA32
segments less than the expected number are allocated.
Signed-off-by: Gavin Shan <redacted>
This can cause overlapped DMA32 segments to different PEs in some cases.
I already had the fix and hold for posting after discussion with Michael
on how to handle the series tomorrow.
I'm going to send v10 as a reply to this thread.
Thanks,
Gavin
static void pnv_ioda_setup_dma(struct pnv_phb *phb)
{
struct pci_controller *hose = phb->hose;
- unsigned int weight, total_weight, dma_pe_count;
- unsigned int residual, remaining, segs, base;
struct pnv_ioda_pe *pe;
-
- total_weight = 0;
- pci_walk_bus(phb->hose->bus, pnv_pci_ioda_dev_dma_weight,
- &total_weight);
-
- dma_pe_count = 0;
- list_for_each_entry(pe, &phb->ioda.pe_list, list) {
- weight = pnv_pci_ioda_pe_dma_weight(pe);
- if (weight > 0)
- dma_pe_count++;
- }
+ unsigned int weight;
/* If we have more PE# than segments available, hand out one
* per PE until we run out and let the rest fail. If not,
* then we assign at least one segment per PE, plus more based
* on the amount of devices under that PE
*/
- if (dma_pe_count > phb->ioda.tce32_count)
- residual = 0;
- else
- residual = phb->ioda.tce32_count - dma_pe_count;
-
- pr_info("PCI: Domain %04x has %ld available 32-bit DMA segments\n",
- hose->global_number, phb->ioda.tce32_count);
- pr_info("PCI: %d PE# for a total weight of %d\n",
- dma_pe_count, total_weight);
+ pr_info("PCI: Domain %04x has %d available 32-bit DMA segments\n",
+ hose->global_number, phb->ioda.dma32_count);
pnv_pci_ioda_setup_opal_tce_kill(phb);
- /* Walk our PE list and configure their DMA segments, hand them
- * out one base segment plus any residual segments based on
- * weight
- */
- remaining = phb->ioda.tce32_count;
- base = 0;
+ /* Walk our PE list and configure their DMA segments */
list_for_each_entry(pe, &phb->ioda.pe_list, list) {
weight = pnv_pci_ioda_pe_dma_weight(pe);
if (!weight)
continue;
- if (!remaining) {
- pe_warn(pe, "No DMA32 resources available\n");
- continue;
- }
- segs = 1;
- if (residual) {
- segs += ((weight * residual) + (total_weight / 2)) /
- total_weight;
- if (segs > remaining)
- segs = remaining;
- }
-
/*
* For IODA2 compliant PHB3, we needn't care about the weight.
* The all available 32-bits DMA space will be assigned to
* the specific PE.
*/
if (phb->type == PNV_PHB_IODA1) {
- pe_info(pe, "DMA weight %d, assigned %d DMA32 segments\n",
- weight, segs);
- pnv_pci_ioda1_setup_dma_pe(phb, pe, base, segs);
+ pnv_pci_ioda1_setup_dma_pe(phb, pe);
} else if (phb->type == PNV_PHB_IODA2) {
pe_info(pe, "Assign DMA32 space\n");
- segs = 0;
pnv_pci_ioda2_setup_dma_pe(phb, pe);
} else if (phb->type == PNV_PHB_NPU) {
/*
mutex_init(&phb->ioda.pe_list_mutex);
/* Calculate how many 32-bit TCE segments we have */
- phb->ioda.tce32_count = phb->ioda.m32_pci_base /
+ phb->ioda.dma32_count = phb->ioda.m32_pci_base /
PNV_IODA1_DMA32_SEGSIZE;
#if 0 /* We should really do that ... */
This enables M64 window on P7IOC, which has been enabled on PHB3.
Different from PHB3 where 16 M64 BARs are supported and each of
them can be owned by one particular PE# exclusively or divided
evenly to 256 segments, every P7IOC PHB has 16 M64 BARs and each
of them are divided to 8 segments. So every P7IOC PHB supports
128 M64 segments in total. P7IOC has M64DT, which helps mapping
one particular M64 segment# to arbitrary PE#. PHB3 doesn't have
M64DT, indicating that one M64 segment can only be pinned to the
fixed PE#.
In order to unified M64 support M64 on P7IOC and PHB3, we just
provide 128 M64 segments on every P7IOC PHB and each of them is
pinned to the fixed PE# by bypassing the function of M64DT. In
turn, we just need different phb->init_m64() for P7IOC and PHB3
and maps M64 segment in pnv_ioda_reserve_m64_pe() for P7IOC, most
of the code are shared by them.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alistair Popple <redacted>
---
v10: Replace pr_warn() with WARN() suggested by Alistair
---
arch/powerpc/platforms/powernv/pci-ioda.c | 89 +++++++++++++++++++++++++++++--
1 file changed, 86 insertions(+), 3 deletions(-)
@@ -315,6 +376,26 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all)pe->master=master_pe;list_add_tail(&pe->list,&master_pe->slaves);}++/*+*P7IOCsupportsM64DT,whichhelpsmappingM64segment+*tooneparticularPE#.However,PHB3hasfixedmapping+*betweenM64segmentandPE#.Inordertohavesamelogic+*forP7IOCandPHB3,weenforcefixedmappingbetweenM64+*segmentandPE#onP7IOC.+*/+if(phb->type==PNV_PHB_IODA1){+int64_trc;++rc=opal_pci_map_pe_mmio_window(phb->opal_id,+pe->pe_number,OPAL_M64_WINDOW_TYPE,+pe->pe_number/PNV_IODA1_M64_SEGS,+pe->pe_number%PNV_IODA1_M64_SEGS);+if(rc!=OPAL_SUCCESS)+pr_warn("%s: Error %lld mapping M64 for PHB#%d-PE#%d\n",+__func__,rc,phb->hose->global_number,+pe->pe_number);+}}kfree(pe_alloc);
@@ -329,8 +410,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)constu32*r;u64pci_addr;-/* FIXME: Support M64 for P7IOC */-if(phb->type!=PNV_PHB_IODA2){+if(phb->type!=PNV_PHB_IODA1&&phb->type!=PNV_PHB_IODA2){pr_info(" Not support M64 window\n");return;}
@@ -364,7 +444,10 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)/* Use last M64 BAR to cover M64 window */phb->ioda.m64_bar_idx=15;-phb->init_m64=pnv_ioda2_init_m64;+if(phb->type==PNV_PHB_IODA1)+phb->init_m64=pnv_ioda1_init_m64;+else+phb->init_m64=pnv_ioda2_init_m64;phb->reserve_m64_pe=pnv_ioda_reserve_m64_pe;phb->pick_m64_pe=pnv_ioda_pick_m64_pe;}
There are two arrays for IO and M32 segment maps on every PHB.
The index of the arrays are segment number and the value stored
in the corresponding element is PE number, indicating the segment
is assigned to the PE. Initially, all elements in those two arrays
are zeroes, meaning all segments are assigned to PE#0. It's wrong.
This fixes the initial values in the elements of those two arrays
to IODA_INVALID_PE, meaning all segments aren't assigned to any
PE.
Signed-off-by: Gavin Shan <redacted>
In current implementation, the DMA32 segments required by one specific
PE isn't calculated with the information hold in the PE independently.
It conflicts with the PCI hotplug design: PE centralized, meaning the
PE's DMA32 segments should be calculated from the information hold in
the PE independently.
This introduces an array (@dma32_segmap) for every PHB to track the
DMA32 segmeng usage. Besides, this moves the logic calculating PE's
consumed DMA32 segments to pnv_pci_ioda1_setup_dma_pe() so that PE's
DMA32 segments are calculated/allocated from the information hold in
the PE (DMA32 weight). Also the logic is improved: we try to allocate
as much DMA32 segments as we can. It's acceptable that number of DMA32
segments less than the expected number are allocated.
Signed-off-by: Gavin Shan <redacted>
---
v10: Fixed picking same DMA32 segment by different PEs in some cases
---
arch/powerpc/platforms/powernv/pci-ioda.c | 115 ++++++++++++++++--------------
arch/powerpc/platforms/powernv/pci.h | 7 +-
2 files changed, 66 insertions(+), 56 deletions(-)
@@ -2542,73 +2581,34 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,staticvoidpnv_ioda_setup_dma(structpnv_phb*phb){structpci_controller*hose=phb->hose;-unsignedintweight,total_weight,dma_pe_count;-unsignedintresidual,remaining,segs,base;structpnv_ioda_pe*pe;--total_weight=0;-pci_walk_bus(phb->hose->bus,pnv_pci_ioda_dev_dma_weight,-&total_weight);--dma_pe_count=0;-list_for_each_entry(pe,&phb->ioda.pe_list,list){-weight=pnv_pci_ioda_pe_dma_weight(pe);-if(weight>0)-dma_pe_count++;-}+unsignedintweight;/* If we have more PE# than segments available, hand out one*perPEuntilwerunoutandlettherestfail.Ifnot,*thenweassignatleastonesegmentperPE,plusmorebased*ontheamountofdevicesunderthatPE*/-if(dma_pe_count>phb->ioda.tce32_count)-residual=0;-else-residual=phb->ioda.tce32_count-dma_pe_count;--pr_info("PCI: Domain %04x has %ld available 32-bit DMA segments\n",-hose->global_number,phb->ioda.tce32_count);-pr_info("PCI: %d PE# for a total weight of %d\n",-dma_pe_count,total_weight);+pr_info("PCI: Domain %04x has %d available 32-bit DMA segments\n",+hose->global_number,phb->ioda.dma32_count);pnv_pci_ioda_setup_opal_tce_kill(phb);-/* Walk our PE list and configure their DMA segments, hand them-*outonebasesegmentplusanyresidualsegmentsbasedon-*weight-*/-remaining=phb->ioda.tce32_count;-base=0;+/* Walk our PE list and configure their DMA segments */list_for_each_entry(pe,&phb->ioda.pe_list,list){weight=pnv_pci_ioda_pe_dma_weight(pe);if(!weight)continue;-if(!remaining){-pe_warn(pe,"No DMA32 resources available\n");-continue;-}-segs=1;-if(residual){-segs+=((weight*residual)+(total_weight/2))/-total_weight;-if(segs>remaining)-segs=remaining;-}-/**ForIODA2compliantPHB3,weneedn'tcareabouttheweight.*Theallavailable32-bitsDMAspacewillbeassignedto*thespecificPE.*/if(phb->type==PNV_PHB_IODA1){-pe_info(pe,"DMA weight %d, assigned %d DMA32 segments\n",-weight,segs);-pnv_pci_ioda1_setup_dma_pe(phb,pe,base,segs);+pnv_pci_ioda1_setup_dma_pe(phb,pe);}elseif(phb->type==PNV_PHB_IODA2){pe_info(pe,"Assign DMA32 space\n");-segs=0;pnv_pci_ioda2_setup_dma_pe(phb,pe);}elseif(phb->type==PNV_PHB_NPU){/*
@@ -3413,6 +3411,10 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,phb->ioda.io_segsize=phb->ioda.io_size/phb->ioda.total_pe_num;phb->ioda.io_pci_base=0;/* XXX calculate this ? */+/* Calculate how many 32-bit TCE segments we have */+phb->ioda.dma32_count=phb->ioda.m32_pci_base/+PNV_IODA1_DMA32_SEGSIZE;+/* Allocate aux data & arrays. We don't have IO ports on PHB3 */size=_ALIGN_UP(phb->ioda.total_pe_num/8,sizeof(unsignedlong));m64map_off=size;
@@ -3445,7 +3454,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,mutex_init(&phb->ioda.pe_list_mutex);/* Calculate how many 32-bit TCE segments we have */-phb->ioda.tce32_count=phb->ioda.m32_pci_base/+phb->ioda.dma32_count=phb->ioda.m32_pci_base/PNV_IODA1_DMA32_SEGSIZE;#if 0 /* We should really do that ... */
pnv_ioda_setup_pe_seg() associates the IO and M32 segments with the
owner PE. The code mapping segments should be fixed and immune from
logic changes introduced to pnv_ioda_setup_pe_seg().
This moves the code mapping segments to helper pnv_ioda_setup_pe_res().
The data type for @rc is changed to "int64_t". Also, argument @hose is
removed from pnv_ioda_setup_pe() as it can be got from @pe. No functional
changes introduced.
Signed-off-by: Gavin Shan <redacted>
On Thu, May 05, 2016 at 11:03:28AM +1000, Alistair Popple wrote:
Thanks for the clarifications Gavin. Aside from the WARN_ON() (which is not a
major thing) everything looks good.
Reviewed-By: Alistair Popple <redacted>
Thanks, Alistair. I'm going to send a updated revision (v10) replacing pr_warn()
with WARN(). The detailed message is as below:
WARN(1, "Wrong reserved PE#%d on PHB#%d\n",
phb->ioda.reserved_pe_idx, phb->hose->global_number);
Thanks,
Gavin
On Thu, 5 May 2016 10:40:33 Gavin Shan wrote:
quoted
On Thu, May 05, 2016 at 09:53:51AM +1000, Alistair Popple wrote:
quoted
On Wed, 4 May 2016 16:48:53 Gavin Shan wrote:
quoted
On Wed, May 04, 2016 at 03:17:51PM +1000, Alistair Popple wrote:
quoted
On Tue, 3 May 2016 15:41:31 Gavin Shan wrote:
quoted
This enables M64 window on P7IOC, which has been enabled on PHB3.
Have we tested that this works with an adaptor? This looks to be enabling
support for something that didn't previously work (64-bit BARs on P7IOC)?
The M64 isn't supported on P7IOC before, meaning the PCI device's M64
BAR is covered by PHB's M32 window. With the patch applied, the PCI
device's M64 BAR is covered by PHB's M64 window as below log I got
from vpl4. The kernel including the series of patches boots successfully
on vpl4 and all looks normal.
So you're changing the way 64-bit BARs work on P7IOC to use a different bit of
the hardware/firmware? This means it could break older systems if there is
an issue with the M64 support. Other than the comments below the code looks
reasonable. However I am assuming you've tested that cards with 64-bit BARs
still function on P7 after this change as I'm not familiar enough to comment on
the specific hardware details, although your comments make sense and match the
code.
Nope, it doesn't rely on changes in firmware. The old firmware enables and
exposes PHB M64 window. The kernel doesn't use it on P7IOC until this patch.
On VPL4, there is a IPR adapter (0000:60:00.0) as below kernel log indicates.
Its BAR#2 is M64 (64-bits prefetchable) BAR. The BAR#2 is covered by PHB's M64
window with this patch. The PHB's M64 window is [0x00003da800000000..0x00003dafffffffff].
After it's applied, the IPR and root filesystem resident in the disk drive out
of it work fine.
Different from PHB3 where 16 M64 BARs are supported and each of
them can be owned by one particular PE# exclusively or divided
evenly to 256 segments, every P7IOC PHB has 16 M64 BARs and each
of them are divided to 8 segments. So every P7IOC PHB supports
128 M64 segments in total. P7IOC has M64DT, which helps mapping
one particular M64 segment# to arbitrary PE#. PHB3 doesn't have
M64DT, indicating that one M64 segment can only be pinned to the
fixed PE#.
In order to unified M64 support M64 on P7IOC and PHB3, we just
provide 128 M64 segments on every P7IOC PHB and each of them is
pinned to the fixed PE# by bypassing the function of M64DT. In
turn, we just need different phb->init_m64() for P7IOC and PHB3
and maps M64 segment in pnv_ioda_reserve_m64_pe() for P7IOC, most
of the code are shared by them.
Signed-off-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 89
}
}
+static int pnv_ioda1_init_m64(struct pnv_phb *phb)
+{
+ struct resource *r;
+ int index;
+
+ /*
+ * There are 16 M64 BARs, each of which has 8 segments. So
+ * there are as many M64 segments as the maximum number of
+ * PEs, which is 128.
+ */
+ for (index = 0; index < PNV_IODA1_M64_NUM; index++) {
+ unsigned long base, segsz = phb->ioda.m64_segsize;
+ int64_t rc;
+
+ base = phb->ioda.m64_base +
+ index * PNV_IODA1_M64_SEGS * segsz;
+ rc = opal_pci_set_phb_mem_window(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index, base, 0,
+ PNV_IODA1_M64_SEGS * segsz);
Has firmware always supported OPAL_M64_WINDOW_TYPE for P7IOC? If older versions
don't support it what happens? Do we gracefully fall back to the old mode of
allocating all BARs from the M32 window or does it break?
Old firmware enables and exposes M64 window (OPAL_M64_WINDOW_TYPE), but kernel
doesn't use it until this patch. If the OPAL call fails, errcode is returned.
The caller, pnv_pci_init_ioda_phb(), disables the window. It means the PCI
device M64 BARs will fail back to be covered by M32 window. The path is same
on PHB3 and P7IOC.
quoted
quoted
quoted
quoted
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld setting M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+
+ rc = opal_pci_phb_mmio_enable(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE, index,
+ OPAL_ENABLE_M64_SPLIT);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn(" Error %lld enabling M64 PHB#%d-BAR#%d\n",
+ rc, phb->hose->global_number, index);
+ goto fail;
+ }
+ }
+
+ /*
+ * Exclude the segment used by the reserved PE, which
+ * is expected to be 0 or last supported PE#.
+ */
+ r = &phb->hose->mem_resources[1];
+ if (phb->ioda.reserved_pe_idx == 0)
+ r->start += phb->ioda.m64_segsize;
+ else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
+ r->end -= phb->ioda.m64_segsize;
+ else
+ pr_warn(" Cannot cut M64 segment for reserved PE#%d\n",
+ phb->ioda.reserved_pe_idx);
Should this be a WARN_ON()? If this condition can only exist because a future
programmer changes the reserved_pe_idx then I think it should be a WARN_ON()
as the above message would be too easy to miss.
@@ -315,6 +376,26 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus
*bus, bool all)
quoted
pe->master = master_pe;
list_add_tail(&pe->list, &master_pe->slaves);
}
+
+ /*
+ * P7IOC supports M64DT, which helps mapping M64 segment
+ * to one particular PE#. However, PHB3 has fixed mapping
+ * between M64 segment and PE#. In order to have same logic
+ * for P7IOC and PHB3, we enforce fixed mapping between M64
+ * segment and PE# on P7IOC.
+ */
+ if (phb->type == PNV_PHB_IODA1) {
+ int64_t rc;
+
+ rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+ pe->pe_number, OPAL_M64_WINDOW_TYPE,
+ pe->pe_number / PNV_IODA1_M64_SEGS,
+ pe->pe_number % PNV_IODA1_M64_SEGS);
+ if (rc != OPAL_SUCCESS)
+ pr_warn("%s: Error %lld mapping M64 for
This enables M64 window on P7IOC, which has been enabled on PHB3.
Different from PHB3 where 16 M64 BARs are supported and each of
them can be owned by one particular PE# exclusively or divided
evenly to 256 segments, every P7IOC PHB has 16 M64 BARs and each
of them are divided to 8 segments. So every P7IOC PHB supports
128 M64 segments in total. P7IOC has M64DT, which helps mapping
one particular M64 segment# to arbitrary PE#. PHB3 doesn't have
M64DT, indicating that one M64 segment can only be pinned to the
fixed PE#.
In order to unified M64 support M64 on P7IOC and PHB3, we just
provide 128 M64 segments on every P7IOC PHB and each of them is
pinned to the fixed PE# by bypassing the function of M64DT. In
turn, we just need different phb->init_m64() for P7IOC and PHB3
and maps M64 segment in pnv_ioda_reserve_m64_pe() for P7IOC, most
of the code are shared by them.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alistair Popple <redacted>
@@ -315,6 +376,26 @@ static unsigned int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all)pe->master=master_pe;list_add_tail(&pe->list,&master_pe->slaves);}++/*+*P7IOCsupportsM64DT,whichhelpsmappingM64segment+*tooneparticularPE#.However,PHB3hasfixedmapping+*betweenM64segmentandPE#.Inordertohavesamelogic+*forP7IOCandPHB3,weenforcefixedmappingbetweenM64+*segmentandPE#onP7IOC.+*/+if(phb->type==PNV_PHB_IODA1){+int64_trc;++rc=opal_pci_map_pe_mmio_window(phb->opal_id,+pe->pe_number,OPAL_M64_WINDOW_TYPE,+pe->pe_number/PNV_IODA1_M64_SEGS,+pe->pe_number%PNV_IODA1_M64_SEGS);+if(rc!=OPAL_SUCCESS)+pr_warn("%s: Error %lld mapping M64 for PHB#%d-PE#%d\n",+__func__,rc,phb->hose->global_number,+pe->pe_number);+}}kfree(pe_alloc);
@@ -329,8 +410,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)constu32*r;u64pci_addr;-/* FIXME: Support M64 for P7IOC */-if(phb->type!=PNV_PHB_IODA2){+if(phb->type!=PNV_PHB_IODA1&&phb->type!=PNV_PHB_IODA2){pr_info(" Not support M64 window\n");return;}
@@ -364,7 +444,10 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)/* Use last M64 BAR to cover M64 window */phb->ioda.m64_bar_idx=15;-phb->init_m64=pnv_ioda2_init_m64;+if(phb->type==PNV_PHB_IODA1)+phb->init_m64=pnv_ioda1_init_m64;+else+phb->init_m64=pnv_ioda2_init_m64;phb->reserve_m64_pe=pnv_ioda_reserve_m64_pe;phb->pick_m64_pe=pnv_ioda_pick_m64_pe;}
Currently, there is one macro (TCE32_TABLE_SIZE) representing the
TCE table size for one DMA32 segment. The constant representing
the DMA32 segment size (1 << 28) is still used in the code.
This defines PNV_IODA1_DMA32_SEGSIZE representing one DMA32
segment size. the TCE table size can be calcualted when the page
has fixed 4KB size. So all the related calculation depends on one
macro (PNV_IODA1_DMA32_SEGSIZE). No logical changes introduced.
Signed-off-by: Gavin Shan <redacted>
@@ -2057,29 +2055,34 @@ static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb,/* Grab a 32-bit TCE table */pe->tce32_seg=base;pe_info(pe," Setting up 32-bit TCE table at %08x..%08x\n",-(base<<28),((base+segs)<<28)-1);+base*PNV_IODA1_DMA32_SEGSIZE,+(base+segs)*PNV_IODA1_DMA32_SEGSIZE-1);/* XXX Currently, we allocate one big contiguous table for the*TCEs.Weonlyreallyneedonechunkper256MofTCEspace*(iepersegment)butthat'sanoptimizationforlater,it*requiressomeaddedsmartswithourget/put_tceimplementation+*+*EachTCEpageis4KBinsizeandeachTCEentryoccupies8+*bytes*/+tce32_segsz=PNV_IODA1_DMA32_SEGSIZE>>(IOMMU_PAGE_SHIFT_4K-3);tce_mem=alloc_pages_node(phb->hose->node,GFP_KERNEL,-get_order(TCE32_TABLE_SIZE*segs));+get_order(tce32_segsz*segs));if(!tce_mem){pe_err(pe," Failed to allocate a 32-bit TCE memory\n");gotofail;}addr=page_address(tce_mem);-memset(addr,0,TCE32_TABLE_SIZE*segs);+memset(addr,0,tce32_segsz*segs);/* Configure HW */for(i=0;i<segs;i++){rc=opal_pci_map_pe_dma_window(phb->opal_id,pe->pe_number,base+i,1,-__pa(addr)+TCE32_TABLE_SIZE*i,-TCE32_TABLE_SIZE,0x1000);+__pa(addr)+tce32_segsz*i,+tce32_segsz,IOMMU_PAGE_SIZE_4K);if(rc){pe_err(pe," Failed to configure 32-bit TCE table,"" err %ld\n",rc);
@@ -3456,7 +3460,8 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,mutex_init(&phb->ioda.pe_list_mutex);/* Calculate how many 32-bit TCE segments we have */-phb->ioda.tce32_count=phb->ioda.m32_pci_base>>28;+phb->ioda.tce32_count=phb->ioda.m32_pci_base/+PNV_IODA1_DMA32_SEGSIZE;#if 0 /* We should really do that ... */rc=opal_pci_set_phb_mem_window(opal->phb_id,
Currently, the IO and M32 segments are mapped to the corresponding
PE based on the windows of the parent bridge of PE's primary bus.
It's not going to work when the windows of root port or upstream
port of the PCIe switch behind root port are extended to PHB's
apertures in order to support hotplug in subsequent patch.
This fixes the issue by mapping IO and M32 segments based on the
resources of the PCI devices included in the PE, instead of the
windows of the parent bridge of the PE's primary bus.
Signed-off-by: Gavin Shan <redacted>
This renames pcibios_{add,remove}_pci_devices() to avoid conflicts
with names of the weak functions in PCI subsystem, which have the
prefix "pcibios". No logical changes introduced.
Signed-off-by: Gavin Shan <redacted>
@@ -260,10 +260,10 @@ static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn)externstructpci_bus*pcibios_find_pci_bus(structdevice_node*dn);/** Remove all of the PCI devices under this bus */-externvoidpcibios_remove_pci_devices(structpci_bus*bus);+externvoidpci_hp_remove_devices(structpci_bus*bus);/** Discover new pci devices under this bus, and add them */-externvoidpcibios_add_pci_devices(structpci_bus*bus);+externvoidpci_hp_add_devices(structpci_bus*bus);externvoidisa_bridge_find_early(structpci_controller*hose);
@@ -38,20 +38,20 @@ void pcibios_release_device(struct pci_dev *dev)}/**-*pcibios_remove_pci_devices-removealldevicesunderthisbus+*pci_hp_remove_devices-removealldevicesunderthisbus*@bus:theindicatedPCIbus**RemoveallofthePCIdevicesunderthisbusbothfromthe*linuxpcidevicetree,andfromthepowerpcEEHaddresscache.*/-voidpcibios_remove_pci_devices(structpci_bus*bus)+voidpci_hp_remove_devices(structpci_bus*bus){structpci_dev*dev,*tmp;structpci_bus*child_bus;/* First go down child busses */list_for_each_entry(child_bus,&bus->children,node)-pcibios_remove_pci_devices(child_bus);+pci_hp_remove_devices(child_bus);pr_debug("PCI: Removing devices on bus %04x:%02x\n",pci_domain_nr(bus),bus->number);
This moves pci_find_bus_by_node() from arch/powerpc/platforms/
pseries/pci_dlpar.c to arch/powerpc/kernel/pci-hotplug.c so that
the function can be used by pSeries and PowerNV platform at the
same time. Also, below cleanup applied. No functional changes
introduced.
* Remove variable "busdn" in find_bus_among_children()
* Use PCI_DN() to convert device node to pci_dn
Signed-off-by: Gavin Shan <redacted>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
In current implementation, the DMA32 segments required by one specific
PE isn't calculated with the information hold in the PE independently.
It conflicts with the PCI hotplug design: PE centralized, meaning the
PE's DMA32 segments should be calculated from the information hold in
the PE independently.
This introduces an array (@dma32_segmap) for every PHB to track the
DMA32 segmeng usage. Besides, this moves the logic calculating PE's
consumed DMA32 segments to pnv_pci_ioda1_setup_dma_pe() so that PE's
DMA32 segments are calculated/allocated from the information hold in
the PE (DMA32 weight). Also the logic is improved: we try to allocate
as much DMA32 segments as we can. It's acceptable that number of DMA32
segments less than the expected number are allocated.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
quoted hunk
---
v10: Fixed picking same DMA32 segment by different PEs in some cases
---
arch/powerpc/platforms/powernv/pci-ioda.c | 115 ++++++++++++++++--------------
arch/powerpc/platforms/powernv/pci.h | 7 +-
2 files changed, 66 insertions(+), 56 deletions(-)
@@ -2542,73 +2581,34 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,staticvoidpnv_ioda_setup_dma(structpnv_phb*phb){structpci_controller*hose=phb->hose;-unsignedintweight,total_weight,dma_pe_count;-unsignedintresidual,remaining,segs,base;structpnv_ioda_pe*pe;--total_weight=0;-pci_walk_bus(phb->hose->bus,pnv_pci_ioda_dev_dma_weight,-&total_weight);--dma_pe_count=0;-list_for_each_entry(pe,&phb->ioda.pe_list,list){-weight=pnv_pci_ioda_pe_dma_weight(pe);-if(weight>0)-dma_pe_count++;-}+unsignedintweight;/* If we have more PE# than segments available, hand out one*perPEuntilwerunoutandlettherestfail.Ifnot,*thenweassignatleastonesegmentperPE,plusmorebased*ontheamountofdevicesunderthatPE*/-if(dma_pe_count>phb->ioda.tce32_count)-residual=0;-else-residual=phb->ioda.tce32_count-dma_pe_count;--pr_info("PCI: Domain %04x has %ld available 32-bit DMA segments\n",-hose->global_number,phb->ioda.tce32_count);-pr_info("PCI: %d PE# for a total weight of %d\n",-dma_pe_count,total_weight);+pr_info("PCI: Domain %04x has %d available 32-bit DMA segments\n",+hose->global_number,phb->ioda.dma32_count);pnv_pci_ioda_setup_opal_tce_kill(phb);-/* Walk our PE list and configure their DMA segments, hand them-*outonebasesegmentplusanyresidualsegmentsbasedon-*weight-*/-remaining=phb->ioda.tce32_count;-base=0;+/* Walk our PE list and configure their DMA segments */list_for_each_entry(pe,&phb->ioda.pe_list,list){weight=pnv_pci_ioda_pe_dma_weight(pe);if(!weight)continue;-if(!remaining){-pe_warn(pe,"No DMA32 resources available\n");-continue;-}-segs=1;-if(residual){-segs+=((weight*residual)+(total_weight/2))/-total_weight;-if(segs>remaining)-segs=remaining;-}-/**ForIODA2compliantPHB3,weneedn'tcareabouttheweight.*Theallavailable32-bitsDMAspacewillbeassignedto*thespecificPE.*/if(phb->type==PNV_PHB_IODA1){-pe_info(pe,"DMA weight %d, assigned %d DMA32 segments\n",-weight,segs);-pnv_pci_ioda1_setup_dma_pe(phb,pe,base,segs);+pnv_pci_ioda1_setup_dma_pe(phb,pe);}elseif(phb->type==PNV_PHB_IODA2){pe_info(pe,"Assign DMA32 space\n");-segs=0;pnv_pci_ioda2_setup_dma_pe(phb,pe);}elseif(phb->type==PNV_PHB_NPU){/*
@@ -3413,6 +3411,10 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,phb->ioda.io_segsize=phb->ioda.io_size/phb->ioda.total_pe_num;phb->ioda.io_pci_base=0;/* XXX calculate this ? */+/* Calculate how many 32-bit TCE segments we have */+phb->ioda.dma32_count=phb->ioda.m32_pci_base/+PNV_IODA1_DMA32_SEGSIZE;+/* Allocate aux data & arrays. We don't have IO ports on PHB3 */size=_ALIGN_UP(phb->ioda.total_pe_num/8,sizeof(unsignedlong));m64map_off=size;
@@ -3445,7 +3454,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,mutex_init(&phb->ioda.pe_list_mutex);/* Calculate how many 32-bit TCE segments we have */-phb->ioda.tce32_count=phb->ioda.m32_pci_base/+phb->ioda.dma32_count=phb->ioda.m32_pci_base/PNV_IODA1_DMA32_SEGSIZE;#if 0 /* We should really do that ... */
This cleans up on below data struct instances to use tab instead of
space indent of statement to avoid complains from scripts/checkpatch.pl.
No logical changes introduced.
@pnv_pci_ioda_controller_ops
@pnv_npu_ioda_controller_ops
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Daniel Axtens <redacted>
Reviewed-by: Andrew Donnellan <redacted>
Spaces to tabs conversion is correct, aligning "=" is not to _my_
_personal_ _taste_.
Acked-by: Alexey Kardashevskiy <redacted>
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2016-05-10 21:48:36
On Tue, 2016-03-05 at 05:41:20 UTC, Gavin Shan wrote:
Each PHB has one instance of "struct pci_controller_ops" that includes
various callbacks called by PCI subsystem. In the definition of this
struct, some callbacks have explicit names for its arguments, but the
left don't have.
This adds all explicit names of the arguments to the callbacks in
"struct pci_controller_ops" so that the code looks consistent. Also,
argument name @dev is replaced by @pdev as the later one is the
preferred name for PCI device.
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Daniel Axtens <redacted>
Reviewed-by: Andrew Donnellan <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
On Tue, May 03, 2016 at 03:41:45PM +1000, Gavin Shan wrote:
quoted hunk
The function pnv_pci_reset_secondary_bus() is called like below.
It's impossible for call the function on root bus. So it's safe
to remove the root bus case in the function. No functional changes
introduced.
pci_parent_bus_reset() / pci_bus_reset() / pci_try_reset_bus()
pci_reset_bridge_secondary_bus()
pcibios_reset_secondary_bus()
pnv_pci_reset_secondary_bus()
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Daniel Axtens <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/platforms/powernv/eeh-powernv.c | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
Michael, please revert this one as it is already in linux-ppc-next
branch. Sorry for the overhead.
Obviously, I missed the truth that it affects the PCI passthrou path as
reported by Alexey: When passing GPU (0003:01:00.0) which seats behind
the root port, the reset request is routed to skiboot in original code.
In skiboot, the link bouncing events are masked during the reset. So we
don't see EEH (freeze all) error even link bouncing happens. With the
changes included, the reset is done by kernel and the link bouncing
events aren't masked by altering content of PHB3 (or P7IOC) specific
hardware registers which are invisible to kernel (skiboot hides the
hardware specific). It means the link bouncing is seen by the root port
and it causes a EEH (freeze all) error. The PCI passthrough on GPU device
cannot work.
Thanks,
Gavin
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2016-05-12 11:35:10
On Thu, 2016-05-12 at 13:48 +1000, Gavin Shan wrote:
On Tue, May 03, 2016 at 03:41:45PM +1000, Gavin Shan wrote:
quoted
The function pnv_pci_reset_secondary_bus() is called like below.
It's impossible for call the function on root bus. So it's safe
to remove the root bus case in the function. No functional changes
introduced.
pci_parent_bus_reset() / pci_bus_reset() / pci_try_reset_bus()
pci_reset_bridge_secondary_bus()
pcibios_reset_secondary_bus()
pnv_pci_reset_secondary_bus()
Signed-off-by: Gavin Shan <redacted>
Reviewed-by: Daniel Axtens <redacted>
Reviewed-by: Alexey Kardashevskiy <redacted>
---
arch/powerpc/platforms/powernv/eeh-powernv.c | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)