powerpc/powernv/ioda2: Fix calculation for memory allocated for TCE table
The existing code stores the amount of memory allocated for a TCE table. At the moment it uses @offset which is a virtual offset in the TCE table which is only correct for a one level tables and it does not include memory allocated for intermediate levels. When multilevel TCE table is requested, WARN_ON in tce_iommu_create_table() prints a warning. This adds an additional counter to pnv_pci_ioda2_table_do_alloc_pages() to count actually allocated memory. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
c5dfd654d0
commit
3ba3a73e9f
|
@ -2220,7 +2220,7 @@ static void pnv_pci_ioda_setup_opal_tce_kill(struct pnv_phb *phb)
|
|||
|
||||
static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift,
|
||||
unsigned levels, unsigned long limit,
|
||||
unsigned long *current_offset)
|
||||
unsigned long *current_offset, unsigned long *total_allocated)
|
||||
{
|
||||
struct page *tce_mem = NULL;
|
||||
__be64 *addr, *tmp;
|
||||
|
@ -2236,6 +2236,7 @@ static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift,
|
|||
}
|
||||
addr = page_address(tce_mem);
|
||||
memset(addr, 0, allocated);
|
||||
*total_allocated += allocated;
|
||||
|
||||
--levels;
|
||||
if (!levels) {
|
||||
|
@ -2245,7 +2246,7 @@ static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift,
|
|||
|
||||
for (i = 0; i < entries; ++i) {
|
||||
tmp = pnv_pci_ioda2_table_do_alloc_pages(nid, shift,
|
||||
levels, limit, current_offset);
|
||||
levels, limit, current_offset, total_allocated);
|
||||
if (!tmp)
|
||||
break;
|
||||
|
||||
|
@ -2267,7 +2268,7 @@ static long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
|
|||
struct iommu_table *tbl)
|
||||
{
|
||||
void *addr;
|
||||
unsigned long offset = 0, level_shift;
|
||||
unsigned long offset = 0, level_shift, total_allocated = 0;
|
||||
const unsigned window_shift = ilog2(window_size);
|
||||
unsigned entries_shift = window_shift - page_shift;
|
||||
unsigned table_shift = max_t(unsigned, entries_shift + 3, PAGE_SHIFT);
|
||||
|
@ -2286,7 +2287,7 @@ static long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
|
|||
|
||||
/* Allocate TCE table */
|
||||
addr = pnv_pci_ioda2_table_do_alloc_pages(nid, level_shift,
|
||||
levels, tce_table_size, &offset);
|
||||
levels, tce_table_size, &offset, &total_allocated);
|
||||
|
||||
/* addr==NULL means that the first level allocation failed */
|
||||
if (!addr)
|
||||
|
@ -2308,7 +2309,7 @@ static long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
|
|||
page_shift);
|
||||
tbl->it_level_size = 1ULL << (level_shift - 3);
|
||||
tbl->it_indirect_levels = levels - 1;
|
||||
tbl->it_allocated_size = offset;
|
||||
tbl->it_allocated_size = total_allocated;
|
||||
|
||||
pr_devel("Created TCE table: ws=%08llx ts=%lx @%08llx\n",
|
||||
window_size, tce_table_size, bus_offset);
|
||||
|
|
Loading…
Reference in New Issue