mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-07 13:53:24 +00:00
powerpc/iommu: Do not immediately panic when failed IOMMU table allocation
Most platforms allocate IOMMU table structures (specifically it_map) at the boot time and when this fails - it is a valid reason for panic(). However the powernv platform allocates it_map after a device is returned to the host OS after being passed through and this happens long after the host OS booted. It is quite possible to trigger the it_map allocation panic() and kill the host even though it is not necessary - the host OS can still use the DMA bypass mode (requires a tiny fraction of it_map's memory) and even if that fails, the host OS is runnnable as it was without the device for which allocating it_map causes the panic. Instead of immediately crashing in a powernv/ioda2 system, this prints an error and continues. All other platforms still call panic(). Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Leonardo Bras <leobras.c@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20210216033307.69863-3-aik@ozlabs.ru
This commit is contained in:
parent
7f1fa82d79
commit
4be518d838
@ -727,8 +727,10 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid,
|
||||
sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long);
|
||||
|
||||
tbl->it_map = vzalloc_node(sz, nid);
|
||||
if (!tbl->it_map)
|
||||
panic("iommu_init_table: Can't allocate %ld bytes\n", sz);
|
||||
if (!tbl->it_map) {
|
||||
pr_err("%s: Can't allocate %ld bytes\n", __func__, sz);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
iommu_table_reserve_pages(tbl, res_start, res_end);
|
||||
|
||||
|
@ -486,7 +486,8 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
|
||||
window->table.it_size = size >> window->table.it_page_shift;
|
||||
window->table.it_ops = &cell_iommu_ops;
|
||||
|
||||
iommu_init_table(&window->table, iommu->nid, 0, 0);
|
||||
if (!iommu_init_table(&window->table, iommu->nid, 0, 0))
|
||||
panic("Failed to initialize iommu table");
|
||||
|
||||
pr_debug("\tioid %d\n", window->ioid);
|
||||
pr_debug("\tblocksize %ld\n", window->table.it_blocksize);
|
||||
|
@ -146,7 +146,9 @@ static void iommu_table_iobmap_setup(void)
|
||||
*/
|
||||
iommu_table_iobmap.it_blocksize = 4;
|
||||
iommu_table_iobmap.it_ops = &iommu_table_iobmap_ops;
|
||||
iommu_init_table(&iommu_table_iobmap, 0, 0, 0);
|
||||
if (!iommu_init_table(&iommu_table_iobmap, 0, 0, 0))
|
||||
panic("Failed to initialize iommu table");
|
||||
|
||||
pr_debug(" <- %s\n", __func__);
|
||||
}
|
||||
|
||||
|
@ -1762,7 +1762,8 @@ static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb,
|
||||
tbl->it_ops = &pnv_ioda1_iommu_ops;
|
||||
pe->table_group.tce32_start = tbl->it_offset << tbl->it_page_shift;
|
||||
pe->table_group.tce32_size = tbl->it_size << tbl->it_page_shift;
|
||||
iommu_init_table(tbl, phb->hose->node, 0, 0);
|
||||
if (!iommu_init_table(tbl, phb->hose->node, 0, 0))
|
||||
panic("Failed to initialize iommu table");
|
||||
|
||||
pe->dma_setup_done = true;
|
||||
return;
|
||||
@ -1930,16 +1931,16 @@ static long pnv_pci_ioda2_setup_default_config(struct pnv_ioda_pe *pe)
|
||||
res_start = pe->phb->ioda.m32_pci_base >> tbl->it_page_shift;
|
||||
res_end = min(window_size, SZ_4G) >> tbl->it_page_shift;
|
||||
}
|
||||
iommu_init_table(tbl, pe->phb->hose->node, res_start, res_end);
|
||||
|
||||
rc = pnv_pci_ioda2_set_window(&pe->table_group, 0, tbl);
|
||||
if (iommu_init_table(tbl, pe->phb->hose->node, res_start, res_end))
|
||||
rc = pnv_pci_ioda2_set_window(&pe->table_group, 0, tbl);
|
||||
else
|
||||
rc = -ENOMEM;
|
||||
if (rc) {
|
||||
pe_err(pe, "Failed to configure 32-bit TCE table, err %ld\n",
|
||||
rc);
|
||||
pe_err(pe, "Failed to configure 32-bit TCE table, err %ld\n", rc);
|
||||
iommu_tce_table_put(tbl);
|
||||
return rc;
|
||||
tbl = NULL; /* This clears iommu_table_base below */
|
||||
}
|
||||
|
||||
if (!pnv_iommu_bypass_disabled)
|
||||
pnv_pci_ioda2_set_bypass(pe, true);
|
||||
|
||||
|
@ -638,7 +638,8 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
|
||||
|
||||
iommu_table_setparms(pci->phb, dn, tbl);
|
||||
tbl->it_ops = &iommu_table_pseries_ops;
|
||||
iommu_init_table(tbl, pci->phb->node, 0, 0);
|
||||
if (!iommu_init_table(tbl, pci->phb->node, 0, 0))
|
||||
panic("Failed to initialize iommu table");
|
||||
|
||||
/* Divide the rest (1.75GB) among the children */
|
||||
pci->phb->dma_window_size = 0x80000000ul;
|
||||
@ -720,7 +721,8 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
|
||||
iommu_table_setparms_lpar(ppci->phb, pdn, tbl,
|
||||
ppci->table_group, dma_window);
|
||||
tbl->it_ops = &iommu_table_lpar_multi_ops;
|
||||
iommu_init_table(tbl, ppci->phb->node, 0, 0);
|
||||
if (!iommu_init_table(tbl, ppci->phb->node, 0, 0))
|
||||
panic("Failed to initialize iommu table");
|
||||
iommu_register_group(ppci->table_group,
|
||||
pci_domain_nr(bus), 0);
|
||||
pr_debug(" created table: %p\n", ppci->table_group);
|
||||
@ -749,7 +751,9 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
|
||||
tbl = PCI_DN(dn)->table_group->tables[0];
|
||||
iommu_table_setparms(phb, dn, tbl);
|
||||
tbl->it_ops = &iommu_table_pseries_ops;
|
||||
iommu_init_table(tbl, phb->node, 0, 0);
|
||||
if (!iommu_init_table(tbl, phb->node, 0, 0))
|
||||
panic("Failed to initialize iommu table");
|
||||
|
||||
set_iommu_table_base(&dev->dev, tbl);
|
||||
return;
|
||||
}
|
||||
|
@ -344,7 +344,8 @@ static void iommu_table_dart_setup(void)
|
||||
iommu_table_dart.it_index = 0;
|
||||
iommu_table_dart.it_blocksize = 1;
|
||||
iommu_table_dart.it_ops = &iommu_dart_ops;
|
||||
iommu_init_table(&iommu_table_dart, -1, 0, 0);
|
||||
if (!iommu_init_table(&iommu_table_dart, -1, 0, 0))
|
||||
panic("Failed to initialize iommu table");
|
||||
|
||||
/* Reserve the last page of the DART to avoid possible prefetch
|
||||
* past the DART mapped area
|
||||
|
Loading…
Reference in New Issue
Block a user