Commit 9fcd6f4a authored by Gavin Shan's avatar Gavin Shan Committed by Michael Ellerman

powerpc/powernv: Allocate PE# in reverse order

PE number for one particular PE can be allocated dynamically or
reserved according to the consumed M64 (64-bits prefetchable)
segments of the PE. The M64 segment can't be remapped to arbitrary
PE, meaning the PE number is determined according to the index
of the consumed M64 segment. As below figure shows, M64 resource
grows from low to high end, meaning the PE (number) reserved
according to M64 segment grows from low to high end as well,
so does the dynamically allocated PE number. It will lead to
conflict: PE number (M64 segment) reserved by dynamic allocation
is required by hot added PCI adapter at later point. It fails
the PCI hotplug because of the PE number can't be reserved
based on the index of the consumed M64 segment.

  +---+---+---+---+---+--------------------------------+-----+
  | 0 | 1 | 2 | 3 | 4 |      .......                   | 255 |
  +---+---+---+---+---+--------------------------------+-----+

  PE number for dynamic allocation          ----------------->
  PE number reserved for M64 segment        ----------------->

To resolve above conflicts, this forces the PE number to be
allocated dynamically in reverse order. With this patch applied,
the PE numbers are reserved in ascending order, but allocated
dynamically in reverse order.
Signed-off-by: default avatarGavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent c127562a
...@@ -141,16 +141,14 @@ static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no) ...@@ -141,16 +141,14 @@ static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no)
static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb) static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb)
{ {
unsigned long pe; unsigned long pe = phb->ioda.total_pe_num - 1;
do { for (pe = phb->ioda.total_pe_num - 1; pe >= 0; pe--) {
pe = find_next_zero_bit(phb->ioda.pe_alloc, if (!test_and_set_bit(pe, phb->ioda.pe_alloc))
phb->ioda.total_pe_num, 0); return pnv_ioda_init_pe(phb, pe);
if (pe >= phb->ioda.total_pe_num) }
return NULL;
} while(test_and_set_bit(pe, phb->ioda.pe_alloc));
return pnv_ioda_init_pe(phb, pe); return NULL;
} }
static void pnv_ioda_free_pe(struct pnv_ioda_pe *pe) static void pnv_ioda_free_pe(struct pnv_ioda_pe *pe)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment