mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-20 13:41:30 +00:00
powerpc/fsl_pci: Don't set up inbound windows in kdump crash kernel
Otherwise, because the top end of the crash kernel is treated as the absolute top of memory rather than the beginning of a reserved region, in-flight DMA from the previous kernel that targets areas above the crash kernel can trigger a storm of PCI errors. We only do this for kdump, not normal kexec, in case kexec is being used to upgrade to a kernel that wants a different inbound memory map. Signed-off-by: Scott Wood <scottwood@freescale.com> Cc: Mingkai Hu <Mingkai.hu@freescale.com>
This commit is contained in:
parent
1112450a18
commit
1930bb5ccf
1 changed files with 61 additions and 23 deletions
|
@ -179,6 +179,19 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci,
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_kdump(void)
|
||||||
|
{
|
||||||
|
struct device_node *node;
|
||||||
|
|
||||||
|
node = of_find_node_by_type(NULL, "memory");
|
||||||
|
if (!node) {
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return of_property_read_bool(node, "linux,usable-memory");
|
||||||
|
}
|
||||||
|
|
||||||
/* atmu setup for fsl pci/pcie controller */
|
/* atmu setup for fsl pci/pcie controller */
|
||||||
static void setup_pci_atmu(struct pci_controller *hose)
|
static void setup_pci_atmu(struct pci_controller *hose)
|
||||||
{
|
{
|
||||||
|
@ -192,6 +205,16 @@ static void setup_pci_atmu(struct pci_controller *hose)
|
||||||
const char *name = hose->dn->full_name;
|
const char *name = hose->dn->full_name;
|
||||||
const u64 *reg;
|
const u64 *reg;
|
||||||
int len;
|
int len;
|
||||||
|
bool setup_inbound;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is kdump, we don't want to trigger a bunch of PCI
|
||||||
|
* errors by closing the window on in-flight DMA.
|
||||||
|
*
|
||||||
|
* We still run most of the function's logic so that things like
|
||||||
|
* hose->dma_window_size still get set.
|
||||||
|
*/
|
||||||
|
setup_inbound = !is_kdump();
|
||||||
|
|
||||||
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
|
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
|
||||||
if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_2_2) {
|
if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_2_2) {
|
||||||
|
@ -204,8 +227,11 @@ static void setup_pci_atmu(struct pci_controller *hose)
|
||||||
/* Disable all windows (except powar0 since it's ignored) */
|
/* Disable all windows (except powar0 since it's ignored) */
|
||||||
for(i = 1; i < 5; i++)
|
for(i = 1; i < 5; i++)
|
||||||
out_be32(&pci->pow[i].powar, 0);
|
out_be32(&pci->pow[i].powar, 0);
|
||||||
|
|
||||||
|
if (setup_inbound) {
|
||||||
for (i = start_idx; i < end_idx; i++)
|
for (i = start_idx; i < end_idx; i++)
|
||||||
out_be32(&pci->piw[i].piwar, 0);
|
out_be32(&pci->piw[i].piwar, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup outbound MEM window */
|
/* Setup outbound MEM window */
|
||||||
for(i = 0, j = 1; i < 3; i++) {
|
for(i = 0, j = 1; i < 3; i++) {
|
||||||
|
@ -278,6 +304,7 @@ static void setup_pci_atmu(struct pci_controller *hose)
|
||||||
|
|
||||||
/* Setup inbound mem window */
|
/* Setup inbound mem window */
|
||||||
mem = memblock_end_of_DRAM();
|
mem = memblock_end_of_DRAM();
|
||||||
|
pr_info("%s: end of DRAM %llx\n", __func__, mem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The msi-address-64 property, if it exists, indicates the physical
|
* The msi-address-64 property, if it exists, indicates the physical
|
||||||
|
@ -320,12 +347,14 @@ static void setup_pci_atmu(struct pci_controller *hose)
|
||||||
|
|
||||||
piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
|
piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
|
||||||
|
|
||||||
|
if (setup_inbound) {
|
||||||
/* Setup inbound memory window */
|
/* Setup inbound memory window */
|
||||||
out_be32(&pci->piw[win_idx].pitar, 0x00000000);
|
out_be32(&pci->piw[win_idx].pitar, 0x00000000);
|
||||||
out_be32(&pci->piw[win_idx].piwbar, 0x00000000);
|
out_be32(&pci->piw[win_idx].piwbar, 0x00000000);
|
||||||
out_be32(&pci->piw[win_idx].piwar, piwar);
|
out_be32(&pci->piw[win_idx].piwar, piwar);
|
||||||
win_idx--;
|
}
|
||||||
|
|
||||||
|
win_idx--;
|
||||||
hose->dma_window_base_cur = 0x00000000;
|
hose->dma_window_base_cur = 0x00000000;
|
||||||
hose->dma_window_size = (resource_size_t)sz;
|
hose->dma_window_size = (resource_size_t)sz;
|
||||||
|
|
||||||
|
@ -343,6 +372,7 @@ static void setup_pci_atmu(struct pci_controller *hose)
|
||||||
|
|
||||||
piwar = (piwar & ~PIWAR_SZ_MASK) | (mem_log - 1);
|
piwar = (piwar & ~PIWAR_SZ_MASK) | (mem_log - 1);
|
||||||
|
|
||||||
|
if (setup_inbound) {
|
||||||
/* Setup inbound memory window */
|
/* Setup inbound memory window */
|
||||||
out_be32(&pci->piw[win_idx].pitar, 0x00000000);
|
out_be32(&pci->piw[win_idx].pitar, 0x00000000);
|
||||||
out_be32(&pci->piw[win_idx].piwbear,
|
out_be32(&pci->piw[win_idx].piwbear,
|
||||||
|
@ -350,6 +380,7 @@ static void setup_pci_atmu(struct pci_controller *hose)
|
||||||
out_be32(&pci->piw[win_idx].piwbar,
|
out_be32(&pci->piw[win_idx].piwbar,
|
||||||
pci64_dma_offset >> 12);
|
pci64_dma_offset >> 12);
|
||||||
out_be32(&pci->piw[win_idx].piwar, piwar);
|
out_be32(&pci->piw[win_idx].piwar, piwar);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* install our own dma_set_mask handler to fixup dma_ops
|
* install our own dma_set_mask handler to fixup dma_ops
|
||||||
|
@ -362,12 +393,15 @@ static void setup_pci_atmu(struct pci_controller *hose)
|
||||||
} else {
|
} else {
|
||||||
u64 paddr = 0;
|
u64 paddr = 0;
|
||||||
|
|
||||||
|
if (setup_inbound) {
|
||||||
/* Setup inbound memory window */
|
/* Setup inbound memory window */
|
||||||
out_be32(&pci->piw[win_idx].pitar, paddr >> 12);
|
out_be32(&pci->piw[win_idx].pitar, paddr >> 12);
|
||||||
out_be32(&pci->piw[win_idx].piwbar, paddr >> 12);
|
out_be32(&pci->piw[win_idx].piwbar, paddr >> 12);
|
||||||
out_be32(&pci->piw[win_idx].piwar, (piwar | (mem_log - 1)));
|
out_be32(&pci->piw[win_idx].piwar,
|
||||||
win_idx--;
|
(piwar | (mem_log - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
win_idx--;
|
||||||
paddr += 1ull << mem_log;
|
paddr += 1ull << mem_log;
|
||||||
sz -= 1ull << mem_log;
|
sz -= 1ull << mem_log;
|
||||||
|
|
||||||
|
@ -375,11 +409,15 @@ static void setup_pci_atmu(struct pci_controller *hose)
|
||||||
mem_log = ilog2(sz);
|
mem_log = ilog2(sz);
|
||||||
piwar |= (mem_log - 1);
|
piwar |= (mem_log - 1);
|
||||||
|
|
||||||
out_be32(&pci->piw[win_idx].pitar, paddr >> 12);
|
if (setup_inbound) {
|
||||||
out_be32(&pci->piw[win_idx].piwbar, paddr >> 12);
|
out_be32(&pci->piw[win_idx].pitar,
|
||||||
|
paddr >> 12);
|
||||||
|
out_be32(&pci->piw[win_idx].piwbar,
|
||||||
|
paddr >> 12);
|
||||||
out_be32(&pci->piw[win_idx].piwar, piwar);
|
out_be32(&pci->piw[win_idx].piwar, piwar);
|
||||||
win_idx--;
|
}
|
||||||
|
|
||||||
|
win_idx--;
|
||||||
paddr += 1ull << mem_log;
|
paddr += 1ull << mem_log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue