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,15 +206,17 @@ void __init fwnmi_init(void) ...@@ -206,15 +206,17 @@ void __init fwnmi_init(void)
fwnmi_active = 1; fwnmi_active = 1;
} }
/* Early initialization. Relocation is on but do not reference unbolted pages */ /* Early initialization. Relocation is on but do not reference unbolted pages */
void __init pSeries_init_early(void) void __init pSeries_init_early(void)
{ {
#ifdef CONFIG_PPC_PSERIES /* This ifdef should go away */
void *comport; void *comport;
hpte_init_pSeries(); hpte_init_pSeries();
tce_init_pSeries();
if (ppc64_iommu_off)
pci_dma_init_direct();
else
tce_init_pSeries();
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
smp_init_pSeries(); smp_init_pSeries();
...@@ -227,7 +229,6 @@ void __init pSeries_init_early(void) ...@@ -227,7 +229,6 @@ void __init pSeries_init_early(void)
ppc_md.udbg_putc = udbg_putc; ppc_md.udbg_putc = udbg_putc;
ppc_md.udbg_getc = udbg_getc; ppc_md.udbg_getc = udbg_getc;
ppc_md.udbg_getc_poll = udbg_getc_poll; ppc_md.udbg_getc_poll = udbg_getc_poll;
#endif
} }
void __init void __init
......
...@@ -699,7 +699,8 @@ void __init pSeries_final_fixup(void) ...@@ -699,7 +699,8 @@ void __init pSeries_final_fixup(void)
phbs_fixup_io(); phbs_fixup_io();
chrp_request_regions(); chrp_request_regions();
pci_fix_bus_sysdata(); pci_fix_bus_sysdata();
iommu_setup_pSeries(); if (!ppc64_iommu_off)
iommu_setup_pSeries();
} }
/*********************************************************************** /***********************************************************************
......
...@@ -525,25 +525,16 @@ prom_initialize_naca(unsigned long mem) ...@@ -525,25 +525,16 @@ prom_initialize_naca(unsigned long mem)
return mem; return mem;
} }
#ifdef CONFIG_PMAC_DART static int iommu_force_on;
static int dart_force_on; int ppc64_iommu_off;
#endif
static unsigned long __init static void early_cmdline_parse(void)
prom_initialize_lmb(unsigned long mem)
{ {
phandle node; unsigned long offset = reloc_offset();
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
char *opt; char *opt;
#ifndef CONFIG_PMAC_DART
struct systemcfg *_systemcfg = RELOC(systemcfg);
#endif
opt = strstr(RELOC(cmd_line), RELOC("iommu=")); opt = strstr(RELOC(cmd_line), RELOC("iommu="));
if (opt) { if (opt) {
...@@ -554,16 +545,30 @@ prom_initialize_lmb(unsigned long mem) ...@@ -554,16 +545,30 @@ prom_initialize_lmb(unsigned long mem)
while (*opt && *opt == ' ') while (*opt && *opt == ' ')
opt++; opt++;
if (!strncmp(opt, RELOC("off"), 3)) if (!strncmp(opt, RELOC("off"), 3))
nodart = 1; RELOC(ppc64_iommu_off) = 1;
else if (!strncmp(opt, RELOC("force"), 5)) 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")); 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(); lmb_init();
...@@ -589,11 +594,6 @@ prom_initialize_lmb(unsigned long mem) ...@@ -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_hi) << 32;
lmb_base |= (unsigned long)reg.addrPM[i].address_lo; lmb_base |= (unsigned long)reg.addrPM[i].address_lo;
lmb_size = reg.addrPM[i].size; 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) { } else if (_prom->encode_phys_size == 32) {
lmb_base = reg.addr32[i].address; lmb_base = reg.addr32[i].address;
lmb_size = reg.addr32[i].size; lmb_size = reg.addr32[i].size;
...@@ -602,7 +602,16 @@ prom_initialize_lmb(unsigned long mem) ...@@ -602,7 +602,16 @@ prom_initialize_lmb(unsigned long mem)
lmb_size = reg.addr64[i].size; 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")); prom_print(RELOC("Too many LMB's, discarding this one...\n"));
} }
...@@ -780,7 +789,7 @@ void prom_initialize_dart_table(void) ...@@ -780,7 +789,7 @@ void prom_initialize_dart_table(void)
/* Only reserve DART space if machine has more than 2GB of RAM /* Only reserve DART space if machine has more than 2GB of RAM
* or if requested with iommu=on on cmdline. * 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; return;
/* 512 pages is max DART tablesize. */ /* 512 pages is max DART tablesize. */
...@@ -811,6 +820,9 @@ prom_initialize_tce_table(void) ...@@ -811,6 +820,9 @@ prom_initialize_tce_table(void)
struct of_tce_table *prom_tce_table = RELOC(of_tce_table); struct of_tce_table *prom_tce_table = RELOC(of_tce_table);
unsigned long tce_entry, *tce_entryp; unsigned long tce_entry, *tce_entryp;
if (RELOC(ppc64_iommu_off))
return;
#ifdef DEBUG_PROM #ifdef DEBUG_PROM
prom_print(RELOC("starting prom_initialize_tce_table\n")); prom_print(RELOC("starting prom_initialize_tce_table\n"));
#endif #endif
...@@ -1583,6 +1595,8 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, ...@@ -1583,6 +1595,8 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
strlcpy(RELOC(cmd_line), p, sizeof(cmd_line)); strlcpy(RELOC(cmd_line), p, sizeof(cmd_line));
} }
early_cmdline_parse();
mem = prom_initialize_lmb(mem); mem = prom_initialize_lmb(mem);
mem = prom_bi_rec_reserve(mem); mem = prom_bi_rec_reserve(mem);
......
...@@ -152,4 +152,6 @@ extern void tce_init_iSeries(void); ...@@ -152,4 +152,6 @@ extern void tce_init_iSeries(void);
extern void pci_iommu_init(void); extern void pci_iommu_init(void);
extern void pci_dma_init_direct(void); extern void pci_dma_init_direct(void);
extern int ppc64_iommu_off;
#endif #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