powerpc/powernv: Track M64 segment consumption
authorGavin Shan <gwshan@linux.vnet.ibm.com>
Tue, 3 May 2016 05:41:29 +0000 (15:41 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 11 May 2016 11:54:19 +0000 (21:54 +1000)
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 <gwshan@linux.vnet.ibm.com>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.h

index 904790bf956615a34f904fd56a7ef09bdc3bf97d..832b430b4964853f360eb290a68278997644d923 100644 (file)
@@ -305,6 +305,7 @@ static unsigned int pnv_ioda2_pick_m64_pe(struct pci_bus *bus, bool all)
                phb->ioda.total_pe_num) {
                pe = &phb->ioda.pe_array[i];
 
+               phb->ioda.m64_segmap[pe->pe_number] = pe->pe_number;
                if (!master_pe) {
                        pe->flags |= PNV_IODA_PE_MASTER;
                        INIT_LIST_HEAD(&pe->slaves);
@@ -3252,7 +3253,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
 {
        struct pci_controller *hose;
        struct pnv_phb *phb;
-       unsigned long size, m32map_off, pemap_off, iomap_off = 0;
+       unsigned long size, m64map_off, m32map_off, pemap_off, iomap_off = 0;
        const __be64 *prop64;
        const __be32 *prop32;
        int len;
@@ -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(unsigned long));
+       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) {
@@ -3350,9 +3353,12 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
        size += phb->ioda.total_pe_num * sizeof(struct pnv_ioda_pe);
        aux = memblock_virt_alloc(size, 0);
        phb->ioda.pe_alloc = aux;
+       phb->ioda.m64_segmap = aux + m64map_off;
        phb->ioda.m32_segmap = aux + m32map_off;
-       for (segno = 0; segno < phb->ioda.total_pe_num; segno++)
+       for (segno = 0; segno < phb->ioda.total_pe_num; segno++) {
+               phb->ioda.m64_segmap[segno] = IODA_INVALID_PE;
                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++)
index 66f256920296249e862318b1e0f69229f3b9cbae..a409165be868de056592a44bae0fe09b8c4def71 100644 (file)
@@ -146,6 +146,7 @@ struct pnv_phb {
                struct pnv_ioda_pe      *pe_array;
 
                /* M32 & IO segment maps */
+               unsigned int            *m64_segmap;
                unsigned int            *m32_segmap;
                unsigned int            *io_segmap;