Commit e44af431 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: implement iommu=off for pseries

From: Anton Blanchard <anton@samba.org>

Implement iommu=off for pseries.  We limit memory to 2GB as pmac does,
however the default for < 2GB remains iommu=on unlike pmac.
parent 226bf386
......@@ -206,14 +206,16 @@ void __init fwnmi_init(void)
fwnmi_active = 1;
}
/* Early initialization. Relocation is on but do not reference unbolted pages */
void __init pSeries_init_early(void)
{
#ifdef CONFIG_PPC_PSERIES /* This ifdef should go away */
void *comport;
hpte_init_pSeries();
if (ppc64_iommu_off)
pci_dma_init_direct();
else
tce_init_pSeries();
#ifdef CONFIG_SMP
......@@ -227,7 +229,6 @@ void __init pSeries_init_early(void)
ppc_md.udbg_putc = udbg_putc;
ppc_md.udbg_getc = udbg_getc;
ppc_md.udbg_getc_poll = udbg_getc_poll;
#endif
}
void __init
......
......@@ -699,6 +699,7 @@ void __init pSeries_final_fixup(void)
phbs_fixup_io();
chrp_request_regions();
pci_fix_bus_sysdata();
if (!ppc64_iommu_off)
iommu_setup_pSeries();
}
......
......@@ -525,25 +525,16 @@ prom_initialize_naca(unsigned long mem)
return mem;
}
#ifdef CONFIG_PMAC_DART
static int dart_force_on;
#endif
static int iommu_force_on;
int ppc64_iommu_off;
static unsigned long __init
prom_initialize_lmb(unsigned long mem)
static void early_cmdline_parse(void)
{
phandle node;
char type[64];
unsigned long i, offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
struct systemcfg *_systemcfg = RELOC(systemcfg);
union lmb_reg_property reg;
unsigned long lmb_base, lmb_size;
unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
int nodart = 0;
#ifdef CONFIG_PMAC_DART
unsigned long offset = reloc_offset();
char *opt;
#ifndef CONFIG_PMAC_DART
struct systemcfg *_systemcfg = RELOC(systemcfg);
#endif
opt = strstr(RELOC(cmd_line), RELOC("iommu="));
if (opt) {
......@@ -554,16 +545,30 @@ prom_initialize_lmb(unsigned long mem)
while (*opt && *opt == ' ')
opt++;
if (!strncmp(opt, RELOC("off"), 3))
nodart = 1;
RELOC(ppc64_iommu_off) = 1;
else if (!strncmp(opt, RELOC("force"), 5))
RELOC(dart_force_on) = 1;
RELOC(iommu_force_on) = 1;
}
#else
nodart = 1;
#endif /* CONFIG_PMAC_DART */
if (nodart)
#ifndef CONFIG_PMAC_DART
if (_systemcfg->platform == PLATFORM_POWERMAC) {
RELOC(ppc64_iommu_off) = 1;
prom_print(RELOC("DART disabled on PowerMac !\n"));
}
#endif
}
static unsigned long __init
prom_initialize_lmb(unsigned long mem)
{
phandle node;
char type[64];
unsigned long i, offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
struct systemcfg *_systemcfg = RELOC(systemcfg);
union lmb_reg_property reg;
unsigned long lmb_base, lmb_size;
unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
lmb_init();
......@@ -589,11 +594,6 @@ prom_initialize_lmb(unsigned long mem)
lmb_base = ((unsigned long)reg.addrPM[i].address_hi) << 32;
lmb_base |= (unsigned long)reg.addrPM[i].address_lo;
lmb_size = reg.addrPM[i].size;
if (nodart && lmb_base > 0x80000000ull) {
prom_print(RELOC("Skipping memory above 2Gb for "
"now, DART support disabled\n"));
continue;
}
} else if (_prom->encode_phys_size == 32) {
lmb_base = reg.addr32[i].address;
lmb_size = reg.addr32[i].size;
......@@ -602,7 +602,16 @@ prom_initialize_lmb(unsigned long mem)
lmb_size = reg.addr64[i].size;
}
if ( lmb_add(lmb_base, lmb_size) < 0 )
/* We limit memory to 2GB if the IOMMU is off */
if (RELOC(ppc64_iommu_off)) {
if (lmb_base >= 0x80000000UL)
continue;
if ((lmb_base + lmb_size) > 0x80000000UL)
lmb_size = 0x80000000UL - lmb_base;
}
if (lmb_add(lmb_base, lmb_size) < 0)
prom_print(RELOC("Too many LMB's, discarding this one...\n"));
}
......@@ -780,7 +789,7 @@ void prom_initialize_dart_table(void)
/* Only reserve DART space if machine has more than 2GB of RAM
* or if requested with iommu=on on cmdline.
*/
if (lmb_end_of_DRAM() <= 0x80000000ull && !RELOC(dart_force_on))
if (lmb_end_of_DRAM() <= 0x80000000ull && !RELOC(iommu_force_on))
return;
/* 512 pages is max DART tablesize. */
......@@ -811,6 +820,9 @@ prom_initialize_tce_table(void)
struct of_tce_table *prom_tce_table = RELOC(of_tce_table);
unsigned long tce_entry, *tce_entryp;
if (RELOC(ppc64_iommu_off))
return;
#ifdef DEBUG_PROM
prom_print(RELOC("starting prom_initialize_tce_table\n"));
#endif
......@@ -1583,6 +1595,8 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
strlcpy(RELOC(cmd_line), p, sizeof(cmd_line));
}
early_cmdline_parse();
mem = prom_initialize_lmb(mem);
mem = prom_bi_rec_reserve(mem);
......
......@@ -152,4 +152,6 @@ extern void tce_init_iSeries(void);
extern void pci_iommu_init(void);
extern void pci_dma_init_direct(void);
extern int ppc64_iommu_off;
#endif
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