Skip to content

Commit

Permalink
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/…
Browse files Browse the repository at this point in the history
…benh/powerpc

Pull a few more things for powerpc by Benjamin Herrenschmidt:
 - Anton's did some recent improvements to EPOW event reporting on
   pSeries (power supply failures and such).  The patches are self
   contained enough and replace really nasty code so I felt it should
   still go in
 - I did the vio driver registration change Greg requested, I don't see
   the point of leaving that til the next merge window
 - The remaining EEH changes I said were still pending to get rid of the
   EEH references from the generic struct device_node
 - A few more iSeries removal bits
 - A perf bug fix on 970

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  powerpc/perf: Fix instruction address sampling on 970 and Power4
  powerpc+sparc/vio: Modernize driver registration
  powerpc: Random little legacy iSeries removal tidy ups
  powerpc: Remove NO_IRQ_IGNORE
  powerpc/pseries: Cut down on enthusiastic use of defines in RAS code
  powerpc/pseries: Clean up ras_error_interrupt code
  powerpc/pseries: Remove RTAS_POWERMGM_EVENTS
  powerpc/pseries: Use rtas_get_sensor in RAS code
  powerpc/pseries: Parse and handle EPOW interrupts
  powerpc: Make function that parses RTAS error logs global
  powerpc/eeh: Retrieve PHB from global list
  powerpc/eeh: Remove eeh information from pci_dn
  powerpc/eeh: Remove eeh device from OF node
  • Loading branch information
Linus Torvalds committed Mar 28, 2012
2 parents 2e7580b + 1ce447b commit 47b816f
Show file tree
Hide file tree
Showing 38 changed files with 321 additions and 273 deletions.
1 change: 0 additions & 1 deletion arch/powerpc/boot/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ zImage.bin.*
zImage.chrp
zImage.coff
zImage.holly
zImage.iseries
zImage.*lds
zImage.miboot
zImage.pmac
Expand Down
1 change: 0 additions & 1 deletion arch/powerpc/include/asm/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ extern void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,
struct dma_attrs *attrs);

extern void iommu_init_early_pSeries(void);
extern void iommu_init_early_iSeries(void);
extern void iommu_init_early_dart(void);
extern void iommu_init_early_pasemi(void);

Expand Down
6 changes: 0 additions & 6 deletions arch/powerpc/include/asm/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ extern atomic_t ppc_n_lost_interrupts;
/* This number is used when no interrupt has been assigned */
#define NO_IRQ (0)

/* This is a special irq number to return from get_irq() to tell that
* no interrupt happened _and_ ignore it (don't count it as bad). Some
* platforms like iSeries rely on that.
*/
#define NO_IRQ_IGNORE ((unsigned int)-1)

/* Total number of virq in the platform */
#define NR_IRQS CONFIG_NR_IRQS

Expand Down
4 changes: 1 addition & 3 deletions arch/powerpc/include/asm/machdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ struct machdep_calls {

void (*init_IRQ)(void);

/* Return an irq, or NO_IRQ to indicate there are none pending.
* If for some reason there is no irq, but the interrupt
* shouldn't be counted as spurious, return NO_IRQ_IGNORE. */
/* Return an irq, or NO_IRQ to indicate there are none pending. */
unsigned int (*get_irq)(void);

/* PCI stuff */
Expand Down
12 changes: 0 additions & 12 deletions arch/powerpc/include/asm/mmu-hash64.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,6 @@ extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);

extern void hpte_init_native(void);
extern void hpte_init_lpar(void);
extern void hpte_init_iSeries(void);
extern void hpte_init_beat(void);
extern void hpte_init_beat_v3(void);

Expand Down Expand Up @@ -325,9 +324,6 @@ extern void slb_set_size(u16 size);
* WARNING - If you change these you must make sure the asm
* implementations in slb_allocate (slb_low.S), do_stab_bolted
* (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
*
* You'll also need to change the precomputed VSID values in head.S
* which are used by the iSeries firmware.
*/

#define VSID_MULTIPLIER_256M ASM_CONST(200730139) /* 28-bit prime */
Expand Down Expand Up @@ -484,14 +480,6 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
| (ea >> SID_SHIFT_1T), 1T);
}

/*
* This is only used on legacy iSeries in lparmap.c,
* hence the 256MB segment assumption.
*/
#define VSID_SCRAMBLE(pvsid) (((pvsid) * VSID_MULTIPLIER_256M) % \
VSID_MODULUS_256M)
#define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea))

#endif /* __ASSEMBLY__ */

#endif /* _ASM_POWERPC_MMU_HASH64_H_ */
16 changes: 8 additions & 8 deletions arch/powerpc/include/asm/pci-bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,7 @@ struct pci_dn {

struct pci_dev *pcidev; /* back-pointer to the pci device */
#ifdef CONFIG_EEH
int class_code; /* pci device class */
int eeh_mode; /* See eeh.h for possible EEH_MODEs */
int eeh_config_addr;
int eeh_pe_config_addr; /* new-style partition endpoint address */
int eeh_check_count; /* # times driver ignored error */
int eeh_freeze_count; /* # times this device froze up. */
int eeh_false_positives; /* # times this device reported #ff's */
u32 config_space[16]; /* saved PCI config space */
struct eeh_dev *edev; /* eeh device */
#endif
#define IODA_INVALID_PE (-1)
#ifdef CONFIG_PPC_POWERNV
Expand All @@ -185,6 +178,13 @@ static inline int pci_device_from_OF_node(struct device_node *np,
return 0;
}

#if defined(CONFIG_EEH)
static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
{
return PCI_DN(dn)->edev;
}
#endif

/** Find the bus corresponding to the indicated device node */
extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);

Expand Down
2 changes: 2 additions & 0 deletions arch/powerpc/include/asm/perf_event_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ struct power_pmu {
*/
#define PPMU_LIMITED_PMC5_6 1 /* PMC5/6 have limited function */
#define PPMU_ALT_SIPR 2 /* uses alternate posn for SIPR/HV */
#define PPMU_NO_SIPR 4 /* no SIPR/HV in MMCRA at all */
#define PPMU_NO_CONT_SAMPLING 8 /* no continuous sampling */

/*
* Values for flags to get_alternatives()
Expand Down
34 changes: 33 additions & 1 deletion arch/powerpc/include/asm/rtas.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ struct rtas_suspend_me_data {
/* RTAS event classes */
#define RTAS_INTERNAL_ERROR 0x80000000 /* set bit 0 */
#define RTAS_EPOW_WARNING 0x40000000 /* set bit 1 */
#define RTAS_POWERMGM_EVENTS 0x20000000 /* set bit 2 */
#define RTAS_HOTPLUG_EVENTS 0x10000000 /* set bit 3 */
#define RTAS_IO_EVENTS 0x08000000 /* set bit 4 */
#define RTAS_EVENT_SCAN_ALL_EVENTS 0xffffffff
Expand Down Expand Up @@ -204,6 +203,39 @@ struct rtas_ext_event_log_v6 {
/* Variable length. */
};

/* pSeries event log format */

/* Two bytes ASCII section IDs */
#define PSERIES_ELOG_SECT_ID_PRIV_HDR (('P' << 8) | 'H')
#define PSERIES_ELOG_SECT_ID_USER_HDR (('U' << 8) | 'H')
#define PSERIES_ELOG_SECT_ID_PRIMARY_SRC (('P' << 8) | 'S')
#define PSERIES_ELOG_SECT_ID_EXTENDED_UH (('E' << 8) | 'H')
#define PSERIES_ELOG_SECT_ID_FAILING_MTMS (('M' << 8) | 'T')
#define PSERIES_ELOG_SECT_ID_SECONDARY_SRC (('S' << 8) | 'S')
#define PSERIES_ELOG_SECT_ID_DUMP_LOCATOR (('D' << 8) | 'H')
#define PSERIES_ELOG_SECT_ID_FW_ERROR (('S' << 8) | 'W')
#define PSERIES_ELOG_SECT_ID_IMPACT_PART_ID (('L' << 8) | 'P')
#define PSERIES_ELOG_SECT_ID_LOGIC_RESOURCE_ID (('L' << 8) | 'R')
#define PSERIES_ELOG_SECT_ID_HMC_ID (('H' << 8) | 'M')
#define PSERIES_ELOG_SECT_ID_EPOW (('E' << 8) | 'P')
#define PSERIES_ELOG_SECT_ID_IO_EVENT (('I' << 8) | 'E')
#define PSERIES_ELOG_SECT_ID_MANUFACT_INFO (('M' << 8) | 'I')
#define PSERIES_ELOG_SECT_ID_CALL_HOME (('C' << 8) | 'H')
#define PSERIES_ELOG_SECT_ID_USER_DEF (('U' << 8) | 'D')

/* Vendor specific Platform Event Log Format, Version 6, section header */
struct pseries_errorlog {
uint16_t id; /* 0x00 2-byte ASCII section ID */
uint16_t length; /* 0x02 Section length in bytes */
uint8_t version; /* 0x04 Section version */
uint8_t subtype; /* 0x05 Section subtype */
uint16_t creator_component; /* 0x06 Creator component ID */
uint8_t data[]; /* 0x08 Start of section data */
};

struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
uint16_t section_id);

/*
* This can be set by the rtas_flash module so that it can get called
* as the absolutely last thing before the kernel terminates.
Expand Down
1 change: 0 additions & 1 deletion arch/powerpc/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ extern void smp_muxed_ipi_set_data(int cpu, unsigned long data);
extern void smp_muxed_ipi_message_pass(int cpu, int msg);
extern irqreturn_t smp_ipi_demux(void);

void smp_init_iSeries(void);
void smp_init_pSeries(void);
void smp_init_cell(void);
void smp_init_celleb(void);
Expand Down
1 change: 0 additions & 1 deletion arch/powerpc/include/asm/udbg.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ extern void __init udbg_init_debug_lpar_hvsi(void);
extern void __init udbg_init_pmac_realmode(void);
extern void __init udbg_init_maple_realmode(void);
extern void __init udbg_init_pas_realmode(void);
extern void __init udbg_init_iseries(void);
extern void __init udbg_init_rtas_panel(void);
extern void __init udbg_init_rtas_console(void);
extern void __init udbg_init_debug_beat(void);
Expand Down
10 changes: 9 additions & 1 deletion arch/powerpc/include/asm/vio.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,25 @@ struct vio_dev {
};

struct vio_driver {
const char *name;
const struct vio_device_id *id_table;
int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
int (*remove)(struct vio_dev *dev);
/* A driver must have a get_desired_dma() function to
* be loaded in a CMO environment if it uses DMA.
*/
unsigned long (*get_desired_dma)(struct vio_dev *dev);
const struct dev_pm_ops *pm;
struct device_driver driver;
};

extern int vio_register_driver(struct vio_driver *drv);
extern int __vio_register_driver(struct vio_driver *drv, struct module *owner,
const char *mod_name);
/*
* vio_register_driver must be a macro so that KBUILD_MODNAME can be expanded
*/
#define vio_register_driver(driver) \
__vio_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
extern void vio_unregister_driver(struct vio_driver *drv);

extern int vio_cmo_entitlement_update(size_t);
Expand Down
8 changes: 4 additions & 4 deletions arch/powerpc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ notrace void arch_local_irq_restore(unsigned long en)
* we are checking the "new" CPU instead of the old one. This
* is only a problem if an event happened on the "old" CPU.
*
* External interrupt events on non-iseries will have caused
* interrupts to be hard-disabled, so there is no problem, we
* External interrupt events will have caused interrupts to
* be hard-disabled, so there is no problem, we
* cannot have preempted.
*/
irq_happened = get_irq_happened();
Expand Down Expand Up @@ -445,9 +445,9 @@ void do_IRQ(struct pt_regs *regs)
may_hard_irq_enable();

/* And finally process it */
if (irq != NO_IRQ && irq != NO_IRQ_IGNORE)
if (irq != NO_IRQ)
handle_one_irq(irq);
else if (irq != NO_IRQ_IGNORE)
else
__get_cpu_var(irq_stat).spurious_irqs++;

irq_exit();
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/prom_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ static void __init __attribute__((noreturn)) prom_panic(const char *reason)
if (RELOC(of_platform) == PLATFORM_POWERMAC)
asm("trap\n");

/* ToDo: should put up an SRC here on p/iSeries */
/* ToDo: should put up an SRC here on pSeries */
call_prom("exit", 0, 0);

for (;;) /* should never get here */
Expand Down
34 changes: 34 additions & 0 deletions arch/powerpc/kernel/rtas.c
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,40 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
}
#endif

/**
* Find a specific pseries error log in an RTAS extended event log.
* @log: RTAS error/event log
* @section_id: two character section identifier
*
* Returns a pointer to the specified errorlog or NULL if not found.
*/
struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
uint16_t section_id)
{
struct rtas_ext_event_log_v6 *ext_log =
(struct rtas_ext_event_log_v6 *)log->buffer;
struct pseries_errorlog *sect;
unsigned char *p, *log_end;

/* Check that we understand the format */
if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
return NULL;

log_end = log->buffer + log->extended_log_length;
p = ext_log->vendor_log;

while (p < log_end) {
sect = (struct pseries_errorlog *)p;
if (sect->id == section_id)
return sect;
p += sect->length;
}

return NULL;
}

asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
{
struct rtas_args args;
Expand Down
3 changes: 0 additions & 3 deletions arch/powerpc/kernel/udbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ void __init udbg_early_init(void)
#elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE)
/* Maple real mode debug */
udbg_init_maple_realmode();
#elif defined(CONFIG_PPC_EARLY_DEBUG_ISERIES)
/* For iSeries - hit Ctrl-x Ctrl-x to see the output */
udbg_init_iseries();
#elif defined(CONFIG_PPC_EARLY_DEBUG_BEAT)
udbg_init_debug_beat();
#elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE)
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,10 +721,10 @@ static int __init vdso_init(void)
vdso_data->version.minor = SYSTEMCFG_MINOR;
vdso_data->processor = mfspr(SPRN_PVR);
/*
* Fake the old platform number for pSeries and iSeries and add
* Fake the old platform number for pSeries and add
* in LPAR bit if necessary
*/
vdso_data->platform = machine_is(iseries) ? 0x200 : 0x100;
vdso_data->platform = 0x100;
if (firmware_has_feature(FW_FEATURE_LPAR))
vdso_data->platform |= 1;
vdso_data->physicalMemorySize = memblock_phys_mem_size();
Expand Down
12 changes: 8 additions & 4 deletions arch/powerpc/kernel/vio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1159,17 +1159,21 @@ static int vio_bus_remove(struct device *dev)
* vio_register_driver: - Register a new vio driver
* @drv: The vio_driver structure to be registered.
*/
int vio_register_driver(struct vio_driver *viodrv)
int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
const char *mod_name)
{
printk(KERN_DEBUG "%s: driver %s registering\n", __func__,
viodrv->driver.name);
pr_debug("%s: driver %s registering\n", __func__, viodrv->name);

/* fill in 'struct driver' fields */
viodrv->driver.name = viodrv->name;
viodrv->driver.pm = viodrv->pm;
viodrv->driver.bus = &vio_bus_type;
viodrv->driver.owner = owner;
viodrv->driver.mod_name = mod_name;

return driver_register(&viodrv->driver);
}
EXPORT_SYMBOL(vio_register_driver);
EXPORT_SYMBOL(__vio_register_driver);

/**
* vio_unregister_driver - Remove registration of vio driver.
Expand Down
46 changes: 41 additions & 5 deletions arch/powerpc/perf/core-book3s.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,45 @@ static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
*addrp = mfspr(SPRN_SDAR);
}

static inline u32 perf_flags_from_msr(struct pt_regs *regs)
{
if (regs->msr & MSR_PR)
return PERF_RECORD_MISC_USER;
if ((regs->msr & MSR_HV) && freeze_events_kernel != MMCR0_FCHV)
return PERF_RECORD_MISC_HYPERVISOR;
return PERF_RECORD_MISC_KERNEL;
}

static inline u32 perf_get_misc_flags(struct pt_regs *regs)
{
unsigned long mmcra = regs->dsisr;
unsigned long sihv = MMCRA_SIHV;
unsigned long sipr = MMCRA_SIPR;

/* Not a PMU interrupt: Make up flags from regs->msr */
if (TRAP(regs) != 0xf00)
return 0; /* not a PMU interrupt */
return perf_flags_from_msr(regs);

/*
* If we don't support continuous sampling and this
* is not a marked event, same deal
*/
if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
!(mmcra & MMCRA_SAMPLE_ENABLE))
return perf_flags_from_msr(regs);

/*
* If we don't have flags in MMCRA, rather than using
* the MSR, we intuit the flags from the address in
* SIAR which should give slightly more reliable
* results
*/
if (ppmu->flags & PPMU_NO_SIPR) {
unsigned long siar = mfspr(SPRN_SIAR);
if (siar >= PAGE_OFFSET)
return PERF_RECORD_MISC_KERNEL;
return PERF_RECORD_MISC_USER;
}

if (ppmu->flags & PPMU_ALT_SIPR) {
sihv = POWER6_MMCRA_SIHV;
Expand Down Expand Up @@ -1299,13 +1330,18 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
*/
unsigned long perf_instruction_pointer(struct pt_regs *regs)
{
unsigned long ip;
unsigned long mmcra = regs->dsisr;

/* Not a PMU interrupt */
if (TRAP(regs) != 0xf00)
return regs->nip; /* not a PMU interrupt */
return regs->nip;

/* Processor doesn't support sampling non marked events */
if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
!(mmcra & MMCRA_SAMPLE_ENABLE))
return regs->nip;

ip = mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
return ip;
return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
}

static bool pmc_overflow(unsigned long val)
Expand Down
Loading

0 comments on commit 47b816f

Please sign in to comment.