提交 c818c778 编写于 作者: L Linus Torvalds

Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc

Pull powerpc updates from Benjamin Herrenschmidt:
 "Here are a few more powerpc bits that I would like in 3.10.

  Mostly remaining bolts & screw tightening of power8 support such as
  actually exposing the new features via the previously added AT_HWCAP2,
  and a few fixes, some of them for problems exposed recently like
  irqdomain warnings or sysfs access permission issues, some exposed by
  power8 hardware.

  The only change outside of arch/powerpc is a small one to irqdomain.c
  to allow silent failure to fix a problem on Cell where we get a dozen
  WARN_ON's tripping at boot for what is basically a normal case."

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  powerpc: Make hard_irq_disable() do the right thing vs. irq tracing
  powerpc/topology: Fix spurr attribute permission
  powerpc/pci: Support per-aperture memory offset
  powerpc/cell/iommu: Improve error message for missing node
  powerpc/cell/spufs: Fix status attribute permission
  irqdomain: Allow quiet failure mode
  powerpc/pnv: Fix "compatible" property for P8 PHB
  powerpc/pci: Don't add bogus empty resources to PHBs
  powerpc/powerpnv: Properly handle failure starting CPUs
  powerpc/cputable: Advertise support for ISEL/HTM/DSCR/TAR on POWER8
  powerpc/cputable: Advertise ISEL support on appropriate embedded processors
  powerpc/cputable: Advertise DSCR support on P7/P7+
  powerpc/cputable: Reserve bits in HWCAP2 for new features
  powerpc/pseries: Perform proper max_bus_speed detection
  powerpc/pseries: Force 32 bit MSIs for devices that require it
  powerpc/tm: Fix null pointer deference in flush_hash_page
  powerpc/powernv: Defer OPAL exception handler registration
  powerpc: Emulate non privileged DSCR read and write
...@@ -224,8 +224,10 @@ extern const char *powerpc_base_platform; ...@@ -224,8 +224,10 @@ extern const char *powerpc_base_platform;
/* We only set the TM feature if the kernel was compiled with TM supprt */ /* We only set the TM feature if the kernel was compiled with TM supprt */
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
#define CPU_FTR_TM_COMP CPU_FTR_TM #define CPU_FTR_TM_COMP CPU_FTR_TM
#define PPC_FEATURE2_HTM_COMP PPC_FEATURE2_HTM
#else #else
#define CPU_FTR_TM_COMP 0 #define CPU_FTR_TM_COMP 0
#define PPC_FEATURE2_HTM_COMP 0
#endif #endif
/* We need to mark all pages as being coherent if we're SMP or we have a /* We need to mark all pages as being coherent if we're SMP or we have a
......
...@@ -95,15 +95,13 @@ static inline bool arch_irqs_disabled(void) ...@@ -95,15 +95,13 @@ static inline bool arch_irqs_disabled(void)
#define __hard_irq_disable() __mtmsrd(local_paca->kernel_msr, 1) #define __hard_irq_disable() __mtmsrd(local_paca->kernel_msr, 1)
#endif #endif
static inline void hard_irq_disable(void) #define hard_irq_disable() do { \
{ __hard_irq_disable(); \
__hard_irq_disable(); if (local_paca->soft_enabled) \
get_paca()->soft_enabled = 0; trace_hardirqs_off(); \
get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; get_paca()->soft_enabled = 0; \
} get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; \
} while(0)
/* include/linux/interrupt.h needs hard_irq_disable to be a macro */
#define hard_irq_disable hard_irq_disable
static inline bool lazy_irq_pending(void) static inline bool lazy_irq_pending(void)
{ {
......
...@@ -29,6 +29,7 @@ struct rtc_time; ...@@ -29,6 +29,7 @@ struct rtc_time;
struct file; struct file;
struct pci_controller; struct pci_controller;
struct kimage; struct kimage;
struct pci_host_bridge;
struct machdep_calls { struct machdep_calls {
char *name; char *name;
...@@ -108,6 +109,8 @@ struct machdep_calls { ...@@ -108,6 +109,8 @@ struct machdep_calls {
void (*pcibios_fixup)(void); void (*pcibios_fixup)(void);
int (*pci_probe_mode)(struct pci_bus *); int (*pci_probe_mode)(struct pci_bus *);
void (*pci_irq_fixup)(struct pci_dev *dev); void (*pci_irq_fixup)(struct pci_dev *dev);
int (*pcibios_root_bridge_prepare)(struct pci_host_bridge
*bridge);
/* To setup PHBs when using automatic OF platform driver for PCI */ /* To setup PHBs when using automatic OF platform driver for PCI */
int (*pci_setup_phb)(struct pci_controller *host); int (*pci_setup_phb)(struct pci_controller *host);
......
...@@ -39,11 +39,6 @@ struct pci_controller { ...@@ -39,11 +39,6 @@ struct pci_controller {
resource_size_t io_base_phys; resource_size_t io_base_phys;
resource_size_t pci_io_size; resource_size_t pci_io_size;
/* Some machines (PReP) have a non 1:1 mapping of
* the PCI memory space in the CPU bus space
*/
resource_size_t pci_mem_offset;
/* Some machines have a special region to forward the ISA /* Some machines have a special region to forward the ISA
* "memory" cycles such as VGA memory regions. Left to 0 * "memory" cycles such as VGA memory regions. Left to 0
* if unsupported * if unsupported
...@@ -86,6 +81,7 @@ struct pci_controller { ...@@ -86,6 +81,7 @@ struct pci_controller {
*/ */
struct resource io_resource; struct resource io_resource;
struct resource mem_resources[3]; struct resource mem_resources[3];
resource_size_t mem_offset[3];
int global_number; /* PCI domain number */ int global_number; /* PCI domain number */
resource_size_t dma_window_base_cur; resource_size_t dma_window_base_cur;
...@@ -163,6 +159,8 @@ struct pci_dn { ...@@ -163,6 +159,8 @@ struct pci_dn {
int pci_ext_config_space; /* for pci devices */ int pci_ext_config_space; /* for pci devices */
int force_32bit_msi:1;
struct pci_dev *pcidev; /* back-pointer to the pci device */ struct pci_dev *pcidev; /* back-pointer to the pci device */
#ifdef CONFIG_EEH #ifdef CONFIG_EEH
struct eeh_dev *edev; /* eeh device */ struct eeh_dev *edev; /* eeh device */
......
...@@ -115,6 +115,10 @@ ...@@ -115,6 +115,10 @@
#define PPC_INST_MFSPR_DSCR_MASK 0xfc1fffff #define PPC_INST_MFSPR_DSCR_MASK 0xfc1fffff
#define PPC_INST_MTSPR_DSCR 0x7c1103a6 #define PPC_INST_MTSPR_DSCR 0x7c1103a6
#define PPC_INST_MTSPR_DSCR_MASK 0xfc1fffff #define PPC_INST_MTSPR_DSCR_MASK 0xfc1fffff
#define PPC_INST_MFSPR_DSCR_USER 0x7c0302a6
#define PPC_INST_MFSPR_DSCR_USER_MASK 0xfc1fffff
#define PPC_INST_MTSPR_DSCR_USER 0x7c0303a6
#define PPC_INST_MTSPR_DSCR_USER_MASK 0xfc1fffff
#define PPC_INST_SLBFEE 0x7c0007a7 #define PPC_INST_SLBFEE 0x7c0007a7
#define PPC_INST_STRING 0x7c00042a #define PPC_INST_STRING 0x7c00042a
......
#ifndef _UAPI__ASM_POWERPC_CPUTABLE_H #ifndef _UAPI__ASM_POWERPC_CPUTABLE_H
#define _UAPI__ASM_POWERPC_CPUTABLE_H #define _UAPI__ASM_POWERPC_CPUTABLE_H
/* in AT_HWCAP */
#define PPC_FEATURE_32 0x80000000 #define PPC_FEATURE_32 0x80000000
#define PPC_FEATURE_64 0x40000000 #define PPC_FEATURE_64 0x40000000
#define PPC_FEATURE_601_INSTR 0x20000000 #define PPC_FEATURE_601_INSTR 0x20000000
...@@ -33,4 +34,12 @@ ...@@ -33,4 +34,12 @@
#define PPC_FEATURE_TRUE_LE 0x00000002 #define PPC_FEATURE_TRUE_LE 0x00000002
#define PPC_FEATURE_PPC_LE 0x00000001 #define PPC_FEATURE_PPC_LE 0x00000001
/* in AT_HWCAP2 */
#define PPC_FEATURE2_ARCH_2_07 0x80000000
#define PPC_FEATURE2_HTM 0x40000000
#define PPC_FEATURE2_DSCR 0x20000000
#define PPC_FEATURE2_EBB 0x10000000
#define PPC_FEATURE2_ISEL 0x08000000
#define PPC_FEATURE2_TAR 0x04000000
#endif /* _UAPI__ASM_POWERPC_CPUTABLE_H */ #endif /* _UAPI__ASM_POWERPC_CPUTABLE_H */
...@@ -98,10 +98,14 @@ extern void __restore_cpu_e6500(void); ...@@ -98,10 +98,14 @@ extern void __restore_cpu_e6500(void);
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \
PPC_FEATURE_TRUE_LE | \ PPC_FEATURE_TRUE_LE | \
PPC_FEATURE_PSERIES_PERFMON_COMPAT) PPC_FEATURE_PSERIES_PERFMON_COMPAT)
#define COMMON_USER2_POWER7 (PPC_FEATURE2_DSCR)
#define COMMON_USER_POWER8 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_06 |\ #define COMMON_USER_POWER8 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_06 |\
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \
PPC_FEATURE_TRUE_LE | \ PPC_FEATURE_TRUE_LE | \
PPC_FEATURE_PSERIES_PERFMON_COMPAT) PPC_FEATURE_PSERIES_PERFMON_COMPAT)
#define COMMON_USER2_POWER8 (PPC_FEATURE2_ARCH_2_07 | \
PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_DSCR | \
PPC_FEATURE2_ISEL | PPC_FEATURE2_TAR)
#define COMMON_USER_PA6T (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\ #define COMMON_USER_PA6T (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\
PPC_FEATURE_TRUE_LE | \ PPC_FEATURE_TRUE_LE | \
PPC_FEATURE_HAS_ALTIVEC_COMP) PPC_FEATURE_HAS_ALTIVEC_COMP)
...@@ -428,6 +432,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -428,6 +432,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_name = "POWER7 (architected)", .cpu_name = "POWER7 (architected)",
.cpu_features = CPU_FTRS_POWER7, .cpu_features = CPU_FTRS_POWER7,
.cpu_user_features = COMMON_USER_POWER7, .cpu_user_features = COMMON_USER_POWER7,
.cpu_user_features2 = COMMON_USER2_POWER7,
.mmu_features = MMU_FTRS_POWER7, .mmu_features = MMU_FTRS_POWER7,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
...@@ -443,6 +448,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -443,6 +448,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_name = "POWER8 (architected)", .cpu_name = "POWER8 (architected)",
.cpu_features = CPU_FTRS_POWER8, .cpu_features = CPU_FTRS_POWER8,
.cpu_user_features = COMMON_USER_POWER8, .cpu_user_features = COMMON_USER_POWER8,
.cpu_user_features2 = COMMON_USER2_POWER8,
.mmu_features = MMU_FTRS_POWER8, .mmu_features = MMU_FTRS_POWER8,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
...@@ -458,6 +464,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -458,6 +464,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_name = "POWER7 (raw)", .cpu_name = "POWER7 (raw)",
.cpu_features = CPU_FTRS_POWER7, .cpu_features = CPU_FTRS_POWER7,
.cpu_user_features = COMMON_USER_POWER7, .cpu_user_features = COMMON_USER_POWER7,
.cpu_user_features2 = COMMON_USER2_POWER7,
.mmu_features = MMU_FTRS_POWER7, .mmu_features = MMU_FTRS_POWER7,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
...@@ -475,6 +482,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -475,6 +482,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_name = "POWER7+ (raw)", .cpu_name = "POWER7+ (raw)",
.cpu_features = CPU_FTRS_POWER7, .cpu_features = CPU_FTRS_POWER7,
.cpu_user_features = COMMON_USER_POWER7, .cpu_user_features = COMMON_USER_POWER7,
.cpu_user_features = COMMON_USER2_POWER7,
.mmu_features = MMU_FTRS_POWER7, .mmu_features = MMU_FTRS_POWER7,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
...@@ -492,6 +500,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -492,6 +500,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_name = "POWER8 (raw)", .cpu_name = "POWER8 (raw)",
.cpu_features = CPU_FTRS_POWER8, .cpu_features = CPU_FTRS_POWER8,
.cpu_user_features = COMMON_USER_POWER8, .cpu_user_features = COMMON_USER_POWER8,
.cpu_user_features2 = COMMON_USER2_POWER8,
.mmu_features = MMU_FTRS_POWER8, .mmu_features = MMU_FTRS_POWER8,
.icache_bsize = 128, .icache_bsize = 128,
.dcache_bsize = 128, .dcache_bsize = 128,
...@@ -1995,6 +2004,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -1995,6 +2004,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_user_features = COMMON_USER_BOOKE | .cpu_user_features = COMMON_USER_BOOKE |
PPC_FEATURE_HAS_SPE_COMP | PPC_FEATURE_HAS_SPE_COMP |
PPC_FEATURE_HAS_EFP_SINGLE_COMP, PPC_FEATURE_HAS_EFP_SINGLE_COMP,
.cpu_user_features2 = PPC_FEATURE2_ISEL,
.mmu_features = MMU_FTR_TYPE_FSL_E, .mmu_features = MMU_FTR_TYPE_FSL_E,
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
...@@ -2014,6 +2024,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -2014,6 +2024,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
PPC_FEATURE_HAS_SPE_COMP | PPC_FEATURE_HAS_SPE_COMP |
PPC_FEATURE_HAS_EFP_SINGLE_COMP | PPC_FEATURE_HAS_EFP_SINGLE_COMP |
PPC_FEATURE_HAS_EFP_DOUBLE_COMP, PPC_FEATURE_HAS_EFP_DOUBLE_COMP,
.cpu_user_features2 = PPC_FEATURE2_ISEL,
.mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS, .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS,
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
...@@ -2030,6 +2041,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -2030,6 +2041,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_name = "e500mc", .cpu_name = "e500mc",
.cpu_features = CPU_FTRS_E500MC, .cpu_features = CPU_FTRS_E500MC,
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.cpu_user_features2 = PPC_FEATURE2_ISEL,
.mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
MMU_FTR_USE_TLBILX, MMU_FTR_USE_TLBILX,
.icache_bsize = 64, .icache_bsize = 64,
...@@ -2048,6 +2060,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -2048,6 +2060,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_name = "e5500", .cpu_name = "e5500",
.cpu_features = CPU_FTRS_E5500, .cpu_features = CPU_FTRS_E5500,
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.cpu_user_features2 = PPC_FEATURE2_ISEL,
.mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
MMU_FTR_USE_TLBILX, MMU_FTR_USE_TLBILX,
.icache_bsize = 64, .icache_bsize = 64,
...@@ -2069,6 +2082,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -2069,6 +2082,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_features = CPU_FTRS_E6500, .cpu_features = CPU_FTRS_E6500,
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU |
PPC_FEATURE_HAS_ALTIVEC_COMP, PPC_FEATURE_HAS_ALTIVEC_COMP,
.cpu_user_features2 = PPC_FEATURE2_ISEL,
.mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
MMU_FTR_USE_TLBILX, MMU_FTR_USE_TLBILX,
.icache_bsize = 64, .icache_bsize = 64,
......
...@@ -786,22 +786,8 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, ...@@ -786,22 +786,8 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
hose->isa_mem_size = size; hose->isa_mem_size = size;
} }
/* We get the PCI/Mem offset from the first range or
* the, current one if the offset came from an ISA
* hole. If they don't match, bugger.
*/
if (memno == 0 ||
(isa_hole >= 0 && pci_addr != 0 &&
hose->pci_mem_offset == isa_mb))
hose->pci_mem_offset = cpu_addr - pci_addr;
else if (pci_addr != 0 &&
hose->pci_mem_offset != cpu_addr - pci_addr) {
printk(KERN_INFO
" \\--> Skipped (offset mismatch) !\n");
continue;
}
/* Build resource */ /* Build resource */
hose->mem_offset[memno] = cpu_addr - pci_addr;
res = &hose->mem_resources[memno++]; res = &hose->mem_resources[memno++];
res->flags = IORESOURCE_MEM; res->flags = IORESOURCE_MEM;
if (pci_space & 0x40000000) if (pci_space & 0x40000000)
...@@ -817,20 +803,6 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, ...@@ -817,20 +803,6 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
res->child = NULL; res->child = NULL;
} }
} }
/* If there's an ISA hole and the pci_mem_offset is -not- matching
* the ISA hole offset, then we need to remove the ISA hole from
* the resource list for that brige
*/
if (isa_hole >= 0 && hose->pci_mem_offset != isa_mb) {
unsigned int next = isa_hole + 1;
printk(KERN_INFO " Removing ISA hole at 0x%016llx\n", isa_mb);
if (next < memno)
memmove(&hose->mem_resources[isa_hole],
&hose->mem_resources[next],
sizeof(struct resource) * (memno - next));
hose->mem_resources[--memno].flags = 0;
}
} }
/* Decide whether to display the domain number in /proc */ /* Decide whether to display the domain number in /proc */
...@@ -845,6 +817,14 @@ int pci_proc_domain(struct pci_bus *bus) ...@@ -845,6 +817,14 @@ int pci_proc_domain(struct pci_bus *bus)
return 1; return 1;
} }
int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
{
if (ppc_md.pcibios_root_bridge_prepare)
return ppc_md.pcibios_root_bridge_prepare(bridge);
return 0;
}
/* This header fixup will do the resource fixup for all devices as they are /* This header fixup will do the resource fixup for all devices as they are
* probed, but not for bridge ranges * probed, but not for bridge ranges
*/ */
...@@ -908,6 +888,7 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus, ...@@ -908,6 +888,7 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
struct pci_controller *hose = pci_bus_to_host(bus); struct pci_controller *hose = pci_bus_to_host(bus);
struct pci_dev *dev = bus->self; struct pci_dev *dev = bus->self;
resource_size_t offset; resource_size_t offset;
struct pci_bus_region region;
u16 command; u16 command;
int i; int i;
...@@ -917,10 +898,10 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus, ...@@ -917,10 +898,10 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
/* Job is a bit different between memory and IO */ /* Job is a bit different between memory and IO */
if (res->flags & IORESOURCE_MEM) { if (res->flags & IORESOURCE_MEM) {
/* If the BAR is non-0 (res != pci_mem_offset) then it's probably been pcibios_resource_to_bus(dev, &region, res);
* initialized by somebody
*/ /* If the BAR is non-0 then it's probably been initialized */
if (res->start != hose->pci_mem_offset) if (region.start != 0)
return 0; return 0;
/* The BAR is 0, let's check if memory decoding is enabled on /* The BAR is 0, let's check if memory decoding is enabled on
...@@ -932,11 +913,11 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus, ...@@ -932,11 +913,11 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
/* Memory decoding is enabled and the BAR is 0. If any of the bridge /* Memory decoding is enabled and the BAR is 0. If any of the bridge
* resources covers that starting address (0 then it's good enough for * resources covers that starting address (0 then it's good enough for
* us for memory * us for memory space)
*/ */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if ((hose->mem_resources[i].flags & IORESOURCE_MEM) && if ((hose->mem_resources[i].flags & IORESOURCE_MEM) &&
hose->mem_resources[i].start == hose->pci_mem_offset) hose->mem_resources[i].start == hose->mem_offset[i])
return 0; return 0;
} }
...@@ -1373,10 +1354,9 @@ static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus) ...@@ -1373,10 +1354,9 @@ static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus)
no_io: no_io:
/* Check for memory */ /* Check for memory */
offset = hose->pci_mem_offset;
pr_debug("hose mem offset: %016llx\n", (unsigned long long)offset);
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
pres = &hose->mem_resources[i]; pres = &hose->mem_resources[i];
offset = hose->mem_offset[i];
if (!(pres->flags & IORESOURCE_MEM)) if (!(pres->flags & IORESOURCE_MEM))
continue; continue;
pr_debug("hose mem res: %pR\n", pres); pr_debug("hose mem res: %pR\n", pres);
...@@ -1516,6 +1496,7 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose, ...@@ -1516,6 +1496,7 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose,
struct list_head *resources) struct list_head *resources)
{ {
struct resource *res; struct resource *res;
resource_size_t offset;
int i; int i;
/* Hookup PHB IO resource */ /* Hookup PHB IO resource */
...@@ -1525,49 +1506,37 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose, ...@@ -1525,49 +1506,37 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose,
printk(KERN_WARNING "PCI: I/O resource not set for host" printk(KERN_WARNING "PCI: I/O resource not set for host"
" bridge %s (domain %d)\n", " bridge %s (domain %d)\n",
hose->dn->full_name, hose->global_number); hose->dn->full_name, hose->global_number);
#ifdef CONFIG_PPC32 } else {
/* Workaround for lack of IO resource only on 32-bit */ offset = pcibios_io_space_offset(hose);
res->start = (unsigned long)hose->io_base_virt - isa_io_base;
res->end = res->start + IO_SPACE_LIMIT;
res->flags = IORESOURCE_IO;
#endif /* CONFIG_PPC32 */
}
pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n", pr_debug("PCI: PHB IO resource = %08llx-%08llx [%lx] off 0x%08llx\n",
(unsigned long long)res->start, (unsigned long long)res->start,
(unsigned long long)res->end, (unsigned long long)res->end,
(unsigned long)res->flags); (unsigned long)res->flags,
pci_add_resource_offset(resources, res, pcibios_io_space_offset(hose)); (unsigned long long)offset);
pci_add_resource_offset(resources, res, offset);
}
/* Hookup PHB Memory resources */ /* Hookup PHB Memory resources */
for (i = 0; i < 3; ++i) { for (i = 0; i < 3; ++i) {
res = &hose->mem_resources[i]; res = &hose->mem_resources[i];
if (!res->flags) { if (!res->flags) {
if (i > 0)
continue;
printk(KERN_ERR "PCI: Memory resource 0 not set for " printk(KERN_ERR "PCI: Memory resource 0 not set for "
"host bridge %s (domain %d)\n", "host bridge %s (domain %d)\n",
hose->dn->full_name, hose->global_number); hose->dn->full_name, hose->global_number);
#ifdef CONFIG_PPC32 continue;
/* Workaround for lack of MEM resource only on 32-bit */
res->start = hose->pci_mem_offset;
res->end = (resource_size_t)-1LL;
res->flags = IORESOURCE_MEM;
#endif /* CONFIG_PPC32 */
} }
offset = hose->mem_offset[i];
pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", i,
pr_debug("PCI: PHB MEM resource %d = %08llx-%08llx [%lx] off 0x%08llx\n", i,
(unsigned long long)res->start, (unsigned long long)res->start,
(unsigned long long)res->end, (unsigned long long)res->end,
(unsigned long)res->flags); (unsigned long)res->flags,
pci_add_resource_offset(resources, res, hose->pci_mem_offset); (unsigned long long)offset);
}
pr_debug("PCI: PHB MEM offset = %016llx\n",
(unsigned long long)hose->pci_mem_offset);
pr_debug("PCI: PHB IO offset = %08lx\n",
(unsigned long)hose->io_base_virt - _IO_BASE);
pci_add_resource_offset(resources, res, offset);
}
} }
/* /*
......
...@@ -295,7 +295,7 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) ...@@ -295,7 +295,7 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
case IOBASE_BRIDGE_NUMBER: case IOBASE_BRIDGE_NUMBER:
return (long)hose->first_busno; return (long)hose->first_busno;
case IOBASE_MEMORY: case IOBASE_MEMORY:
return (long)hose->pci_mem_offset; return (long)hose->mem_offset[0];
case IOBASE_IO: case IOBASE_IO:
return (long)hose->io_base_phys; return (long)hose->io_base_phys;
case IOBASE_ISA_IO: case IOBASE_ISA_IO:
......
...@@ -246,7 +246,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, ...@@ -246,7 +246,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
case IOBASE_BRIDGE_NUMBER: case IOBASE_BRIDGE_NUMBER:
return (long)hose->first_busno; return (long)hose->first_busno;
case IOBASE_MEMORY: case IOBASE_MEMORY:
return (long)hose->pci_mem_offset; return (long)hose->mem_offset[0];
case IOBASE_IO: case IOBASE_IO:
return (long)hose->io_base_phys; return (long)hose->io_base_phys;
case IOBASE_ISA_IO: case IOBASE_ISA_IO:
......
...@@ -180,7 +180,7 @@ SYSFS_PMCSETUP(dscr, SPRN_DSCR); ...@@ -180,7 +180,7 @@ SYSFS_PMCSETUP(dscr, SPRN_DSCR);
SYSFS_PMCSETUP(pir, SPRN_PIR); SYSFS_PMCSETUP(pir, SPRN_PIR);
static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
static DEVICE_ATTR(spurr, 0600, show_spurr, NULL); static DEVICE_ATTR(spurr, 0400, show_spurr, NULL);
static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr);
static DEVICE_ATTR(purr, 0600, show_purr, store_purr); static DEVICE_ATTR(purr, 0600, show_purr, store_purr);
static DEVICE_ATTR(pir, 0400, show_pir, NULL); static DEVICE_ATTR(pir, 0400, show_pir, NULL);
......
...@@ -970,7 +970,10 @@ static int emulate_instruction(struct pt_regs *regs) ...@@ -970,7 +970,10 @@ static int emulate_instruction(struct pt_regs *regs)
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
/* Emulate the mfspr rD, DSCR. */ /* Emulate the mfspr rD, DSCR. */
if (((instword & PPC_INST_MFSPR_DSCR_MASK) == PPC_INST_MFSPR_DSCR) && if ((((instword & PPC_INST_MFSPR_DSCR_USER_MASK) ==
PPC_INST_MFSPR_DSCR_USER) ||
((instword & PPC_INST_MFSPR_DSCR_MASK) ==
PPC_INST_MFSPR_DSCR)) &&
cpu_has_feature(CPU_FTR_DSCR)) { cpu_has_feature(CPU_FTR_DSCR)) {
PPC_WARN_EMULATED(mfdscr, regs); PPC_WARN_EMULATED(mfdscr, regs);
rd = (instword >> 21) & 0x1f; rd = (instword >> 21) & 0x1f;
...@@ -978,7 +981,10 @@ static int emulate_instruction(struct pt_regs *regs) ...@@ -978,7 +981,10 @@ static int emulate_instruction(struct pt_regs *regs)
return 0; return 0;
} }
/* Emulate the mtspr DSCR, rD. */ /* Emulate the mtspr DSCR, rD. */
if (((instword & PPC_INST_MTSPR_DSCR_MASK) == PPC_INST_MTSPR_DSCR) && if ((((instword & PPC_INST_MTSPR_DSCR_USER_MASK) ==
PPC_INST_MTSPR_DSCR_USER) ||
((instword & PPC_INST_MTSPR_DSCR_MASK) ==
PPC_INST_MTSPR_DSCR)) &&
cpu_has_feature(CPU_FTR_DSCR)) { cpu_has_feature(CPU_FTR_DSCR)) {
PPC_WARN_EMULATED(mtdscr, regs); PPC_WARN_EMULATED(mtdscr, regs);
rd = (instword >> 21) & 0x1f; rd = (instword >> 21) & 0x1f;
......
...@@ -1230,6 +1230,7 @@ void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize, ...@@ -1230,6 +1230,7 @@ void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
* unmapping it first, it may see the speculated version. * unmapping it first, it may see the speculated version.
*/ */
if (local && cpu_has_feature(CPU_FTR_TM) && if (local && cpu_has_feature(CPU_FTR_TM) &&
current->thread.regs &&
MSR_TM_ACTIVE(current->thread.regs->msr)) { MSR_TM_ACTIVE(current->thread.regs->msr)) {
tm_enable(); tm_enable();
tm_abort(TM_CAUSE_TLBI); tm_abort(TM_CAUSE_TLBI);
......
...@@ -550,7 +550,7 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev) ...@@ -550,7 +550,7 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev)
*/ */
iommu = cell_iommu_for_node(dev_to_node(dev)); iommu = cell_iommu_for_node(dev_to_node(dev));
if (iommu == NULL || list_empty(&iommu->windows)) { if (iommu == NULL || list_empty(&iommu->windows)) {
printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n", dev_err(dev, "iommu: missing iommu for %s (node %d)\n",
of_node_full_name(dev->of_node), dev_to_node(dev)); of_node_full_name(dev->of_node), dev_to_node(dev));
return NULL; return NULL;
} }
......
...@@ -715,7 +715,7 @@ static ssize_t spu_stat_show(struct device *dev, ...@@ -715,7 +715,7 @@ static ssize_t spu_stat_show(struct device *dev,
spu->stats.libassist); spu->stats.libassist);
} }
static DEVICE_ATTR(stat, 0644, spu_stat_show, NULL); static DEVICE_ATTR(stat, 0444, spu_stat_show, NULL);
#ifdef CONFIG_KEXEC #ifdef CONFIG_KEXEC
......
...@@ -81,17 +81,6 @@ ...@@ -81,17 +81,6 @@
#define MPC10X_MAPB_PCI_MEM_OFFSET (MPC10X_MAPB_ISA_MEM_BASE - \ #define MPC10X_MAPB_PCI_MEM_OFFSET (MPC10X_MAPB_ISA_MEM_BASE - \
MPC10X_MAPB_PCI_MEM_START) MPC10X_MAPB_PCI_MEM_START)
/* Set hose members to values appropriate for the mem map used */
#define MPC10X_SETUP_HOSE(hose, map) { \
(hose)->pci_mem_offset = MPC10X_MAP##map##_PCI_MEM_OFFSET; \
(hose)->io_space.start = MPC10X_MAP##map##_PCI_IO_START; \
(hose)->io_space.end = MPC10X_MAP##map##_PCI_IO_END; \
(hose)->mem_space.start = MPC10X_MAP##map##_PCI_MEM_START; \
(hose)->mem_space.end = MPC10X_MAP##map##_PCI_MEM_END; \
(hose)->io_base_virt = (void *)MPC10X_MAP##map##_ISA_IO_BASE; \
}
/* Miscellaneous Configuration register offsets */ /* Miscellaneous Configuration register offsets */
#define MPC10X_CFG_PIR_REG 0x09 #define MPC10X_CFG_PIR_REG 0x09
#define MPC10X_CFG_PIR_HOST_BRIDGE 0x00 #define MPC10X_CFG_PIR_HOST_BRIDGE 0x00
......
...@@ -824,6 +824,7 @@ static void __init parse_region_decode(struct pci_controller *hose, ...@@ -824,6 +824,7 @@ static void __init parse_region_decode(struct pci_controller *hose,
hose->mem_resources[cur].name = hose->dn->full_name; hose->mem_resources[cur].name = hose->dn->full_name;
hose->mem_resources[cur].start = base; hose->mem_resources[cur].start = base;
hose->mem_resources[cur].end = end; hose->mem_resources[cur].end = end;
hose->mem_offset[cur] = 0;
DBG(" %d: 0x%08lx-0x%08lx\n", cur, base, end); DBG(" %d: 0x%08lx-0x%08lx\n", cur, base, end);
} else { } else {
DBG(" : -0x%08lx\n", end); DBG(" : -0x%08lx\n", end);
...@@ -866,7 +867,6 @@ static void __init setup_u3_ht(struct pci_controller* hose) ...@@ -866,7 +867,6 @@ static void __init setup_u3_ht(struct pci_controller* hose)
hose->io_resource.start = 0; hose->io_resource.start = 0;
hose->io_resource.end = 0x003fffff; hose->io_resource.end = 0x003fffff;
hose->io_resource.flags = IORESOURCE_IO; hose->io_resource.flags = IORESOURCE_IO;
hose->pci_mem_offset = 0;
hose->first_busno = 0; hose->first_busno = 0;
hose->last_busno = 0xef; hose->last_busno = 0xef;
......
...@@ -34,7 +34,6 @@ int __init early_init_dt_scan_opal(unsigned long node, ...@@ -34,7 +34,6 @@ int __init early_init_dt_scan_opal(unsigned long node,
{ {
const void *basep, *entryp; const void *basep, *entryp;
unsigned long basesz, entrysz; unsigned long basesz, entrysz;
u64 glue;
if (depth != 1 || strcmp(uname, "ibm,opal") != 0) if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
return 0; return 0;
...@@ -61,6 +60,16 @@ int __init early_init_dt_scan_opal(unsigned long node, ...@@ -61,6 +60,16 @@ int __init early_init_dt_scan_opal(unsigned long node,
printk("OPAL V1 detected !\n"); printk("OPAL V1 detected !\n");
} }
return 1;
}
static int __init opal_register_exception_handlers(void)
{
u64 glue;
if (!(powerpc_firmware_features & FW_FEATURE_OPAL))
return -ENODEV;
/* Hookup some exception handlers. We use the fwnmi area at 0x7000 /* Hookup some exception handlers. We use the fwnmi area at 0x7000
* to provide the glue space to OPAL * to provide the glue space to OPAL
*/ */
...@@ -74,9 +83,11 @@ int __init early_init_dt_scan_opal(unsigned long node, ...@@ -74,9 +83,11 @@ int __init early_init_dt_scan_opal(unsigned long node,
glue += 128; glue += 128;
opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
return 1; return 0;
} }
early_initcall(opal_register_exception_handlers);
int opal_get_chars(uint32_t vtermno, char *buf, int count) int opal_get_chars(uint32_t vtermno, char *buf, int count)
{ {
s64 len, rc; s64 len, rc;
......
...@@ -915,11 +915,14 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, ...@@ -915,11 +915,14 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose,
index++; index++;
} }
} else if (res->flags & IORESOURCE_MEM) { } else if (res->flags & IORESOURCE_MEM) {
/* WARNING: Assumes M32 is mem region 0 in PHB. We need to
* harden that algorithm when we start supporting M64
*/
region.start = res->start - region.start = res->start -
hose->pci_mem_offset - hose->mem_offset[0] -
phb->ioda.m32_pci_base; phb->ioda.m32_pci_base;
region.end = res->end - region.end = res->end -
hose->pci_mem_offset - hose->mem_offset[0] -
phb->ioda.m32_pci_base; phb->ioda.m32_pci_base;
index = region.start / phb->ioda.m32_segsize; index = region.start / phb->ioda.m32_segsize;
...@@ -1089,7 +1092,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) ...@@ -1089,7 +1092,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
/* Detect specific models for error handling */ /* Detect specific models for error handling */
if (of_device_is_compatible(np, "ibm,p7ioc-pciex")) if (of_device_is_compatible(np, "ibm,p7ioc-pciex"))
phb->model = PNV_PHB_MODEL_P7IOC; phb->model = PNV_PHB_MODEL_P7IOC;
else if (of_device_is_compatible(np, "ibm,p8-pciex")) else if (of_device_is_compatible(np, "ibm,power8-pciex"))
phb->model = PNV_PHB_MODEL_PHB3; phb->model = PNV_PHB_MODEL_PHB3;
else else
phb->model = PNV_PHB_MODEL_UNKNOWN; phb->model = PNV_PHB_MODEL_UNKNOWN;
...@@ -1115,8 +1118,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) ...@@ -1115,8 +1118,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
phb->ioda.m32_size += 0x10000; phb->ioda.m32_size += 0x10000;
phb->ioda.m32_segsize = phb->ioda.m32_size / phb->ioda.total_pe; phb->ioda.m32_segsize = phb->ioda.m32_size / phb->ioda.total_pe;
phb->ioda.m32_pci_base = hose->mem_resources[0].start - phb->ioda.m32_pci_base = hose->mem_resources[0].start - hose->mem_offset[0];
hose->pci_mem_offset;
phb->ioda.io_size = hose->pci_io_size; phb->ioda.io_size = hose->pci_io_size;
phb->ioda.io_segsize = phb->ioda.io_size / phb->ioda.total_pe; phb->ioda.io_segsize = phb->ioda.io_size / phb->ioda.total_pe;
phb->ioda.io_pci_base = 0; /* XXX calculate this ? */ phb->ioda.io_pci_base = 0; /* XXX calculate this ? */
......
...@@ -77,9 +77,11 @@ int pnv_smp_kick_cpu(int nr) ...@@ -77,9 +77,11 @@ int pnv_smp_kick_cpu(int nr)
if (!paca[nr].cpu_start && firmware_has_feature(FW_FEATURE_OPALv2)) { if (!paca[nr].cpu_start && firmware_has_feature(FW_FEATURE_OPALv2)) {
pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu); pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu);
rc = opal_start_cpu(pcpu, start_here); rc = opal_start_cpu(pcpu, start_here);
if (rc != OPAL_SUCCESS) if (rc != OPAL_SUCCESS) {
pr_warn("OPAL Error %ld starting CPU %d\n", pr_warn("OPAL Error %ld starting CPU %d\n",
rc, nr); rc, nr);
return -ENODEV;
}
} }
return smp_generic_kick_cpu(nr); return smp_generic_kick_cpu(nr);
} }
......
...@@ -24,6 +24,7 @@ static int query_token, change_token; ...@@ -24,6 +24,7 @@ static int query_token, change_token;
#define RTAS_RESET_FN 2 #define RTAS_RESET_FN 2
#define RTAS_CHANGE_MSI_FN 3 #define RTAS_CHANGE_MSI_FN 3
#define RTAS_CHANGE_MSIX_FN 4 #define RTAS_CHANGE_MSIX_FN 4
#define RTAS_CHANGE_32MSI_FN 5
static struct pci_dn *get_pdn(struct pci_dev *pdev) static struct pci_dn *get_pdn(struct pci_dev *pdev)
{ {
...@@ -58,7 +59,8 @@ static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs) ...@@ -58,7 +59,8 @@ static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs)
seq_num = 1; seq_num = 1;
do { do {
if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN) if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN ||
func == RTAS_CHANGE_32MSI_FN)
rc = rtas_call(change_token, 6, 4, rtas_ret, addr, rc = rtas_call(change_token, 6, 4, rtas_ret, addr,
BUID_HI(buid), BUID_LO(buid), BUID_HI(buid), BUID_LO(buid),
func, num_irqs, seq_num); func, num_irqs, seq_num);
...@@ -426,9 +428,12 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) ...@@ -426,9 +428,12 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
*/ */
again: again:
if (type == PCI_CAP_ID_MSI) { if (type == PCI_CAP_ID_MSI) {
rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); if (pdn->force_32bit_msi)
rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec);
else
rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
if (rc < 0) { if (rc < 0 && !pdn->force_32bit_msi) {
pr_debug("rtas_msi: trying the old firmware call.\n"); pr_debug("rtas_msi: trying the old firmware call.\n");
rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
} }
...@@ -512,3 +517,13 @@ static int rtas_msi_init(void) ...@@ -512,3 +517,13 @@ static int rtas_msi_init(void)
return 0; return 0;
} }
arch_initcall(rtas_msi_init); arch_initcall(rtas_msi_init);
static void quirk_radeon(struct pci_dev *dev)
{
struct pci_dn *pdn = get_pdn(dev);
if (pdn)
pdn->force_32bit_msi = 1;
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon);
...@@ -108,3 +108,56 @@ static void fixup_winbond_82c105(struct pci_dev* dev) ...@@ -108,3 +108,56 @@ static void fixup_winbond_82c105(struct pci_dev* dev)
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
fixup_winbond_82c105); fixup_winbond_82c105);
int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
{
struct device_node *dn, *pdn;
struct pci_bus *bus;
const uint32_t *pcie_link_speed_stats;
bus = bridge->bus;
dn = pcibios_get_phb_of_node(bus);
if (!dn)
return 0;
for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) {
pcie_link_speed_stats = (const uint32_t *) of_get_property(pdn,
"ibm,pcie-link-speed-stats", NULL);
if (pcie_link_speed_stats)
break;
}
of_node_put(pdn);
if (!pcie_link_speed_stats) {
pr_err("no ibm,pcie-link-speed-stats property\n");
return 0;
}
switch (pcie_link_speed_stats[0]) {
case 0x01:
bus->max_bus_speed = PCIE_SPEED_2_5GT;
break;
case 0x02:
bus->max_bus_speed = PCIE_SPEED_5_0GT;
break;
default:
bus->max_bus_speed = PCI_SPEED_UNKNOWN;
break;
}
switch (pcie_link_speed_stats[1]) {
case 0x01:
bus->cur_bus_speed = PCIE_SPEED_2_5GT;
break;
case 0x02:
bus->cur_bus_speed = PCIE_SPEED_5_0GT;
break;
default:
bus->cur_bus_speed = PCI_SPEED_UNKNOWN;
break;
}
return 0;
}
...@@ -63,4 +63,8 @@ extern int dlpar_detach_node(struct device_node *); ...@@ -63,4 +63,8 @@ extern int dlpar_detach_node(struct device_node *);
/* Snooze Delay, pseries_idle */ /* Snooze Delay, pseries_idle */
DECLARE_PER_CPU(long, smt_snooze_delay); DECLARE_PER_CPU(long, smt_snooze_delay);
/* PCI root bridge prepare function override for pseries */
struct pci_host_bridge;
int pseries_root_bridge_prepare(struct pci_host_bridge *bridge);
#endif /* _PSERIES_PSERIES_H */ #endif /* _PSERIES_PSERIES_H */
...@@ -466,6 +466,8 @@ static void __init pSeries_setup_arch(void) ...@@ -466,6 +466,8 @@ static void __init pSeries_setup_arch(void)
else else
ppc_md.enable_pmcs = power4_enable_pmcs; ppc_md.enable_pmcs = power4_enable_pmcs;
ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare;
if (firmware_has_feature(FW_FEATURE_SET_MODE)) { if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
long rc; long rc;
if ((rc = pSeries_enable_reloc_on_exc()) != H_SUCCESS) { if ((rc = pSeries_enable_reloc_on_exc()) != H_SUCCESS) {
......
...@@ -502,7 +502,7 @@ static void __init wsp_pcie_configure_hw(struct pci_controller *hose) ...@@ -502,7 +502,7 @@ static void __init wsp_pcie_configure_hw(struct pci_controller *hose)
(~(hose->mem_resources[0].end - (~(hose->mem_resources[0].end -
hose->mem_resources[0].start)) & 0x3ffffff0000ul); hose->mem_resources[0].start)) & 0x3ffffff0000ul);
out_be64(hose->cfg_data + PCIE_REG_M32A_START_ADDR, out_be64(hose->cfg_data + PCIE_REG_M32A_START_ADDR,
(hose->mem_resources[0].start - hose->pci_mem_offset) | 1); (hose->mem_resources[0].start - hose->mem_offset[0]) | 1);
/* Clear all TVT entries /* Clear all TVT entries
* *
......
...@@ -178,7 +178,7 @@ static void setup_pci_atmu(struct pci_controller *hose) ...@@ -178,7 +178,7 @@ static void setup_pci_atmu(struct pci_controller *hose)
struct ccsr_pci __iomem *pci = hose->private_data; struct ccsr_pci __iomem *pci = hose->private_data;
int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4; int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4;
u64 mem, sz, paddr_hi = 0; u64 mem, sz, paddr_hi = 0;
u64 paddr_lo = ULLONG_MAX; u64 offset = 0, paddr_lo = ULLONG_MAX;
u32 pcicsrbar = 0, pcicsrbar_sz; u32 pcicsrbar = 0, pcicsrbar_sz;
u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL | u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP; PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
...@@ -208,8 +208,9 @@ static void setup_pci_atmu(struct pci_controller *hose) ...@@ -208,8 +208,9 @@ static void setup_pci_atmu(struct pci_controller *hose)
paddr_lo = min(paddr_lo, (u64)hose->mem_resources[i].start); paddr_lo = min(paddr_lo, (u64)hose->mem_resources[i].start);
paddr_hi = max(paddr_hi, (u64)hose->mem_resources[i].end); paddr_hi = max(paddr_hi, (u64)hose->mem_resources[i].end);
n = setup_one_atmu(pci, j, &hose->mem_resources[i], /* We assume all memory resources have the same offset */
hose->pci_mem_offset); offset = hose->mem_offset[i];
n = setup_one_atmu(pci, j, &hose->mem_resources[i], offset);
if (n < 0 || j >= 5) { if (n < 0 || j >= 5) {
pr_err("Ran out of outbound PCI ATMUs for resource %d!\n", i); pr_err("Ran out of outbound PCI ATMUs for resource %d!\n", i);
...@@ -239,8 +240,8 @@ static void setup_pci_atmu(struct pci_controller *hose) ...@@ -239,8 +240,8 @@ static void setup_pci_atmu(struct pci_controller *hose)
} }
/* convert to pci address space */ /* convert to pci address space */
paddr_hi -= hose->pci_mem_offset; paddr_hi -= offset;
paddr_lo -= hose->pci_mem_offset; paddr_lo -= offset;
if (paddr_hi == paddr_lo) { if (paddr_hi == paddr_lo) {
pr_err("%s: No outbound window space\n", name); pr_err("%s: No outbound window space\n", name);
......
...@@ -1001,8 +1001,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq, ...@@ -1001,8 +1001,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
if (hw == mpic->spurious_vec) if (hw == mpic->spurious_vec)
return -EINVAL; return -EINVAL;
if (mpic->protected && test_bit(hw, mpic->protected)) if (mpic->protected && test_bit(hw, mpic->protected)) {
return -EINVAL; pr_warning("mpic: Mapping of source 0x%x failed, "
"source protected by firmware !\n",\
(unsigned int)hw);
return -EPERM;
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
else if (hw >= mpic->ipi_vecs[0]) { else if (hw >= mpic->ipi_vecs[0]) {
...@@ -1029,8 +1033,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq, ...@@ -1029,8 +1033,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
if (mpic_map_error_int(mpic, virq, hw)) if (mpic_map_error_int(mpic, virq, hw))
return 0; return 0;
if (hw >= mpic->num_sources) if (hw >= mpic->num_sources) {
pr_warning("mpic: Mapping of source 0x%x failed, "
"source out of range !\n",\
(unsigned int)hw);
return -EINVAL; return -EINVAL;
}
mpic_msi_reserve_hwirq(mpic, hw); mpic_msi_reserve_hwirq(mpic, hw);
......
...@@ -257,6 +257,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose, ...@@ -257,6 +257,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
/* Setup outbound memory windows */ /* Setup outbound memory windows */
for (i = j = 0; i < 3; i++) { for (i = j = 0; i < 3; i++) {
struct resource *res = &hose->mem_resources[i]; struct resource *res = &hose->mem_resources[i];
resource_size_t offset = hose->mem_offset[i];
/* we only care about memory windows */ /* we only care about memory windows */
if (!(res->flags & IORESOURCE_MEM)) if (!(res->flags & IORESOURCE_MEM))
...@@ -270,7 +271,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose, ...@@ -270,7 +271,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
/* Configure the resource */ /* Configure the resource */
if (ppc4xx_setup_one_pci_PMM(hose, reg, if (ppc4xx_setup_one_pci_PMM(hose, reg,
res->start, res->start,
res->start - hose->pci_mem_offset, res->start - offset,
resource_size(res), resource_size(res),
res->flags, res->flags,
j) == 0) { j) == 0) {
...@@ -279,7 +280,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose, ...@@ -279,7 +280,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
/* If the resource PCI address is 0 then we have our /* If the resource PCI address is 0 then we have our
* ISA memory hole * ISA memory hole
*/ */
if (res->start == hose->pci_mem_offset) if (res->start == offset)
found_isa_hole = 1; found_isa_hole = 1;
} }
} }
...@@ -457,6 +458,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose, ...@@ -457,6 +458,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
/* Setup outbound memory windows */ /* Setup outbound memory windows */
for (i = j = 0; i < 3; i++) { for (i = j = 0; i < 3; i++) {
struct resource *res = &hose->mem_resources[i]; struct resource *res = &hose->mem_resources[i];
resource_size_t offset = hose->mem_offset[i];
/* we only care about memory windows */ /* we only care about memory windows */
if (!(res->flags & IORESOURCE_MEM)) if (!(res->flags & IORESOURCE_MEM))
...@@ -470,7 +472,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose, ...@@ -470,7 +472,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
/* Configure the resource */ /* Configure the resource */
if (ppc4xx_setup_one_pcix_POM(hose, reg, if (ppc4xx_setup_one_pcix_POM(hose, reg,
res->start, res->start,
res->start - hose->pci_mem_offset, res->start - offset,
resource_size(res), resource_size(res),
res->flags, res->flags,
j) == 0) { j) == 0) {
...@@ -479,7 +481,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose, ...@@ -479,7 +481,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
/* If the resource PCI address is 0 then we have our /* If the resource PCI address is 0 then we have our
* ISA memory hole * ISA memory hole
*/ */
if (res->start == hose->pci_mem_offset) if (res->start == offset)
found_isa_hole = 1; found_isa_hole = 1;
} }
} }
...@@ -1792,6 +1794,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, ...@@ -1792,6 +1794,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
/* Setup outbound memory windows */ /* Setup outbound memory windows */
for (i = j = 0; i < 3; i++) { for (i = j = 0; i < 3; i++) {
struct resource *res = &hose->mem_resources[i]; struct resource *res = &hose->mem_resources[i];
resource_size_t offset = hose->mem_offset[i];
/* we only care about memory windows */ /* we only care about memory windows */
if (!(res->flags & IORESOURCE_MEM)) if (!(res->flags & IORESOURCE_MEM))
...@@ -1805,7 +1808,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, ...@@ -1805,7 +1808,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
/* Configure the resource */ /* Configure the resource */
if (ppc4xx_setup_one_pciex_POM(port, hose, mbase, if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,
res->start, res->start,
res->start - hose->pci_mem_offset, res->start - offset,
resource_size(res), resource_size(res),
res->flags, res->flags,
j) == 0) { j) == 0) {
...@@ -1814,7 +1817,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, ...@@ -1814,7 +1817,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
/* If the resource PCI address is 0 then we have our /* If the resource PCI address is 0 then we have our
* ISA memory hole * ISA memory hole
*/ */
if (res->start == hose->pci_mem_offset) if (res->start == offset)
found_isa_hole = 1; found_isa_hole = 1;
} }
} }
......
...@@ -462,9 +462,23 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, ...@@ -462,9 +462,23 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
if (domain->ops->map) { if (domain->ops->map) {
ret = domain->ops->map(domain, virq, hwirq); ret = domain->ops->map(domain, virq, hwirq);
if (ret != 0) { if (ret != 0) {
pr_err("irq-%i==>hwirq-0x%lx mapping failed: %d\n", /*
virq, hwirq, ret); * If map() returns -EPERM, this interrupt is protected
WARN_ON(1); * by the firmware or some other service and shall not
* be mapped.
*
* Since on some platforms we blindly try to map everything
* we end up with a log full of backtraces.
*
* So instead, we silently fail on -EPERM, it is the
* responsibility of the PIC driver to display a relevant
* message if needed.
*/
if (ret != -EPERM) {
pr_err("irq-%i==>hwirq-0x%lx mapping failed: %d\n",
virq, hwirq, ret);
WARN_ON(1);
}
irq_data->domain = NULL; irq_data->domain = NULL;
irq_data->hwirq = 0; irq_data->hwirq = 0;
goto err_unmap; goto err_unmap;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册