Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/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
This commit is contained in:
		
				commit
				
					
						47b816ff7d
					
				
			
		
					 38 changed files with 320 additions and 272 deletions
				
			
		
							
								
								
									
										1
									
								
								arch/powerpc/boot/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								arch/powerpc/boot/.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -27,7 +27,6 @@ zImage.bin.*
 | 
				
			||||||
zImage.chrp
 | 
					zImage.chrp
 | 
				
			||||||
zImage.coff
 | 
					zImage.coff
 | 
				
			||||||
zImage.holly
 | 
					zImage.holly
 | 
				
			||||||
zImage.iseries
 | 
					 | 
				
			||||||
zImage.*lds
 | 
					zImage.*lds
 | 
				
			||||||
zImage.miboot
 | 
					zImage.miboot
 | 
				
			||||||
zImage.pmac
 | 
					zImage.pmac
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,7 +112,6 @@ extern void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,
 | 
				
			||||||
			     struct dma_attrs *attrs);
 | 
								     struct dma_attrs *attrs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void iommu_init_early_pSeries(void);
 | 
					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_dart(void);
 | 
				
			||||||
extern void iommu_init_early_pasemi(void);
 | 
					extern void iommu_init_early_pasemi(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,12 +27,6 @@ extern atomic_t ppc_n_lost_interrupts;
 | 
				
			||||||
/* This number is used when no interrupt has been assigned */
 | 
					/* This number is used when no interrupt has been assigned */
 | 
				
			||||||
#define NO_IRQ			(0)
 | 
					#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 */
 | 
					/* Total number of virq in the platform */
 | 
				
			||||||
#define NR_IRQS		CONFIG_NR_IRQS
 | 
					#define NR_IRQS		CONFIG_NR_IRQS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,9 +99,7 @@ struct machdep_calls {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void		(*init_IRQ)(void);
 | 
						void		(*init_IRQ)(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Return an irq, or NO_IRQ to indicate there are none pending.
 | 
						/* 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. */
 | 
					 | 
				
			||||||
	unsigned int	(*get_irq)(void);
 | 
						unsigned int	(*get_irq)(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* PCI stuff */
 | 
						/* PCI stuff */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_native(void);
 | 
				
			||||||
extern void hpte_init_lpar(void);
 | 
					extern void hpte_init_lpar(void);
 | 
				
			||||||
extern void hpte_init_iSeries(void);
 | 
					 | 
				
			||||||
extern void hpte_init_beat(void);
 | 
					extern void hpte_init_beat(void);
 | 
				
			||||||
extern void hpte_init_beat_v3(void);
 | 
					extern void hpte_init_beat_v3(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -325,9 +324,6 @@ extern void slb_set_size(u16 size);
 | 
				
			||||||
 * WARNING - If you change these you must make sure the asm
 | 
					 * WARNING - If you change these you must make sure the asm
 | 
				
			||||||
 * implementations in slb_allocate (slb_low.S), do_stab_bolted
 | 
					 * implementations in slb_allocate (slb_low.S), do_stab_bolted
 | 
				
			||||||
 * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
 | 
					 * (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 */
 | 
					#define VSID_MULTIPLIER_256M	ASM_CONST(200730139)	/* 28-bit prime */
 | 
				
			||||||
| 
						 | 
					@ -484,14 +480,6 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
 | 
				
			||||||
			     | (ea >> SID_SHIFT_1T), 1T);
 | 
								     | (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 /* __ASSEMBLY__ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _ASM_POWERPC_MMU_HASH64_H_ */
 | 
					#endif /* _ASM_POWERPC_MMU_HASH64_H_ */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,14 +155,7 @@ struct pci_dn {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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
 | 
				
			||||||
	int	class_code;		/* pci device class */
 | 
						struct eeh_dev *edev;		/* eeh device */
 | 
				
			||||||
	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 */
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#define IODA_INVALID_PE		(-1)
 | 
					#define IODA_INVALID_PE		(-1)
 | 
				
			||||||
#ifdef CONFIG_PPC_POWERNV
 | 
					#ifdef CONFIG_PPC_POWERNV
 | 
				
			||||||
| 
						 | 
					@ -185,6 +178,13 @@ static inline int pci_device_from_OF_node(struct device_node *np,
 | 
				
			||||||
	return 0;
 | 
						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 */
 | 
					/** Find the bus corresponding to the indicated device node */
 | 
				
			||||||
extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 | 
					extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +47,8 @@ struct power_pmu {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define PPMU_LIMITED_PMC5_6	1	/* PMC5/6 have limited function */
 | 
					#define PPMU_LIMITED_PMC5_6	1	/* PMC5/6 have limited function */
 | 
				
			||||||
#define PPMU_ALT_SIPR		2	/* uses alternate posn for SIPR/HV */
 | 
					#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()
 | 
					 * Values for flags to get_alternatives()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,6 @@ struct rtas_suspend_me_data {
 | 
				
			||||||
/* RTAS event classes */
 | 
					/* RTAS event classes */
 | 
				
			||||||
#define RTAS_INTERNAL_ERROR		0x80000000 /* set bit 0 */
 | 
					#define RTAS_INTERNAL_ERROR		0x80000000 /* set bit 0 */
 | 
				
			||||||
#define RTAS_EPOW_WARNING		0x40000000 /* set bit 1 */
 | 
					#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_HOTPLUG_EVENTS		0x10000000 /* set bit 3 */
 | 
				
			||||||
#define RTAS_IO_EVENTS			0x08000000 /* set bit 4 */
 | 
					#define RTAS_IO_EVENTS			0x08000000 /* set bit 4 */
 | 
				
			||||||
#define RTAS_EVENT_SCAN_ALL_EVENTS	0xffffffff
 | 
					#define RTAS_EVENT_SCAN_ALL_EVENTS	0xffffffff
 | 
				
			||||||
| 
						 | 
					@ -204,6 +203,39 @@ struct rtas_ext_event_log_v6 {
 | 
				
			||||||
					/* Variable length.		*/
 | 
										/* 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
 | 
					 * This can be set by the rtas_flash module so that it can get called
 | 
				
			||||||
 * as the absolutely last thing before the kernel terminates.
 | 
					 * as the absolutely last thing before the kernel terminates.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 void smp_muxed_ipi_message_pass(int cpu, int msg);
 | 
				
			||||||
extern irqreturn_t smp_ipi_demux(void);
 | 
					extern irqreturn_t smp_ipi_demux(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void smp_init_iSeries(void);
 | 
					 | 
				
			||||||
void smp_init_pSeries(void);
 | 
					void smp_init_pSeries(void);
 | 
				
			||||||
void smp_init_cell(void);
 | 
					void smp_init_cell(void);
 | 
				
			||||||
void smp_init_celleb(void);
 | 
					void smp_init_celleb(void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_pmac_realmode(void);
 | 
				
			||||||
extern void __init udbg_init_maple_realmode(void);
 | 
					extern void __init udbg_init_maple_realmode(void);
 | 
				
			||||||
extern void __init udbg_init_pas_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_panel(void);
 | 
				
			||||||
extern void __init udbg_init_rtas_console(void);
 | 
					extern void __init udbg_init_rtas_console(void);
 | 
				
			||||||
extern void __init udbg_init_debug_beat(void);
 | 
					extern void __init udbg_init_debug_beat(void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,6 +69,7 @@ struct vio_dev {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct vio_driver {
 | 
					struct vio_driver {
 | 
				
			||||||
 | 
						const char *name;
 | 
				
			||||||
	const struct vio_device_id *id_table;
 | 
						const struct vio_device_id *id_table;
 | 
				
			||||||
	int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
 | 
						int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
 | 
				
			||||||
	int (*remove)(struct vio_dev *dev);
 | 
						int (*remove)(struct vio_dev *dev);
 | 
				
			||||||
| 
						 | 
					@ -76,10 +77,17 @@ struct vio_driver {
 | 
				
			||||||
	 * be loaded in a CMO environment if it uses DMA.
 | 
						 * be loaded in a CMO environment if it uses DMA.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	unsigned long (*get_desired_dma)(struct vio_dev *dev);
 | 
						unsigned long (*get_desired_dma)(struct vio_dev *dev);
 | 
				
			||||||
 | 
						const struct dev_pm_ops *pm;
 | 
				
			||||||
	struct device_driver driver;
 | 
						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 void vio_unregister_driver(struct vio_driver *drv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int vio_cmo_entitlement_update(size_t);
 | 
					extern int vio_cmo_entitlement_update(size_t);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
						 * we are checking the "new" CPU instead of the old one. This
 | 
				
			||||||
	 * is only a problem if an event happened on the "old" CPU.
 | 
						 * is only a problem if an event happened on the "old" CPU.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * External interrupt events on non-iseries will have caused
 | 
						 * External interrupt events will have caused interrupts to
 | 
				
			||||||
	 * interrupts to be hard-disabled, so there is no problem, we
 | 
						 * be hard-disabled, so there is no problem, we
 | 
				
			||||||
	 * cannot have preempted.
 | 
						 * cannot have preempted.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	irq_happened = get_irq_happened();
 | 
						irq_happened = get_irq_happened();
 | 
				
			||||||
| 
						 | 
					@ -445,9 +445,9 @@ void do_IRQ(struct pt_regs *regs)
 | 
				
			||||||
	may_hard_irq_enable();
 | 
						may_hard_irq_enable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* And finally process it */
 | 
						/* And finally process it */
 | 
				
			||||||
	if (irq != NO_IRQ && irq != NO_IRQ_IGNORE)
 | 
						if (irq != NO_IRQ)
 | 
				
			||||||
		handle_one_irq(irq);
 | 
							handle_one_irq(irq);
 | 
				
			||||||
	else if (irq != NO_IRQ_IGNORE)
 | 
						else
 | 
				
			||||||
		__get_cpu_var(irq_stat).spurious_irqs++;
 | 
							__get_cpu_var(irq_stat).spurious_irqs++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	irq_exit();
 | 
						irq_exit();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -447,7 +447,7 @@ static void __init __attribute__((noreturn)) prom_panic(const char *reason)
 | 
				
			||||||
	if (RELOC(of_platform) == PLATFORM_POWERMAC)
 | 
						if (RELOC(of_platform) == PLATFORM_POWERMAC)
 | 
				
			||||||
		asm("trap\n");
 | 
							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);
 | 
						call_prom("exit", 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (;;)			/* should never get here */
 | 
						for (;;)			/* should never get here */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -868,6 +868,40 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#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)
 | 
					asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rtas_args args;
 | 
						struct rtas_args args;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,9 +46,6 @@ void __init udbg_early_init(void)
 | 
				
			||||||
#elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE)
 | 
					#elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE)
 | 
				
			||||||
	/* Maple real mode debug */
 | 
						/* Maple real mode debug */
 | 
				
			||||||
	udbg_init_maple_realmode();
 | 
						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)
 | 
					#elif defined(CONFIG_PPC_EARLY_DEBUG_BEAT)
 | 
				
			||||||
	udbg_init_debug_beat();
 | 
						udbg_init_debug_beat();
 | 
				
			||||||
#elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE)
 | 
					#elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -721,10 +721,10 @@ static int __init vdso_init(void)
 | 
				
			||||||
	vdso_data->version.minor = SYSTEMCFG_MINOR;
 | 
						vdso_data->version.minor = SYSTEMCFG_MINOR;
 | 
				
			||||||
	vdso_data->processor = mfspr(SPRN_PVR);
 | 
						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
 | 
						 * in LPAR bit if necessary
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	vdso_data->platform = machine_is(iseries) ? 0x200 : 0x100;
 | 
						vdso_data->platform = 0x100;
 | 
				
			||||||
	if (firmware_has_feature(FW_FEATURE_LPAR))
 | 
						if (firmware_has_feature(FW_FEATURE_LPAR))
 | 
				
			||||||
		vdso_data->platform |= 1;
 | 
							vdso_data->platform |= 1;
 | 
				
			||||||
	vdso_data->physicalMemorySize = memblock_phys_mem_size();
 | 
						vdso_data->physicalMemorySize = memblock_phys_mem_size();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1159,17 +1159,21 @@ static int vio_bus_remove(struct device *dev)
 | 
				
			||||||
 * vio_register_driver: - Register a new vio driver
 | 
					 * vio_register_driver: - Register a new vio driver
 | 
				
			||||||
 * @drv:	The vio_driver structure to be registered.
 | 
					 * @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__,
 | 
						pr_debug("%s: driver %s registering\n", __func__, viodrv->name);
 | 
				
			||||||
		viodrv->driver.name);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* fill in 'struct driver' fields */
 | 
						/* fill in 'struct driver' fields */
 | 
				
			||||||
 | 
						viodrv->driver.name = viodrv->name;
 | 
				
			||||||
 | 
						viodrv->driver.pm = viodrv->pm;
 | 
				
			||||||
	viodrv->driver.bus = &vio_bus_type;
 | 
						viodrv->driver.bus = &vio_bus_type;
 | 
				
			||||||
 | 
						viodrv->driver.owner = owner;
 | 
				
			||||||
 | 
						viodrv->driver.mod_name = mod_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return driver_register(&viodrv->driver);
 | 
						return driver_register(&viodrv->driver);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(vio_register_driver);
 | 
					EXPORT_SYMBOL(__vio_register_driver);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * vio_unregister_driver - Remove registration of vio driver.
 | 
					 * vio_unregister_driver - Remove registration of vio driver.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,14 +116,45 @@ static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
 | 
				
			||||||
		*addrp = mfspr(SPRN_SDAR);
 | 
							*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)
 | 
					static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long mmcra = regs->dsisr;
 | 
						unsigned long mmcra = regs->dsisr;
 | 
				
			||||||
	unsigned long sihv = MMCRA_SIHV;
 | 
						unsigned long sihv = MMCRA_SIHV;
 | 
				
			||||||
	unsigned long sipr = MMCRA_SIPR;
 | 
						unsigned long sipr = MMCRA_SIPR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Not a PMU interrupt: Make up flags from regs->msr */
 | 
				
			||||||
	if (TRAP(regs) != 0xf00)
 | 
						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) {
 | 
						if (ppmu->flags & PPMU_ALT_SIPR) {
 | 
				
			||||||
		sihv = POWER6_MMCRA_SIHV;
 | 
							sihv = POWER6_MMCRA_SIHV;
 | 
				
			||||||
| 
						 | 
					@ -1299,13 +1330,18 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
unsigned long perf_instruction_pointer(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)
 | 
						if (TRAP(regs) != 0xf00)
 | 
				
			||||||
		return regs->nip;	/* not a PMU interrupt */
 | 
							return regs->nip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ip = mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
 | 
						/* Processor doesn't support sampling non marked events */
 | 
				
			||||||
	return ip;
 | 
						if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
 | 
				
			||||||
 | 
						    !(mmcra & MMCRA_SAMPLE_ENABLE))
 | 
				
			||||||
 | 
							return regs->nip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool pmc_overflow(unsigned long val)
 | 
					static bool pmc_overflow(unsigned long val)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -607,6 +607,7 @@ static struct power_pmu power4_pmu = {
 | 
				
			||||||
	.n_generic		= ARRAY_SIZE(p4_generic_events),
 | 
						.n_generic		= ARRAY_SIZE(p4_generic_events),
 | 
				
			||||||
	.generic_events		= p4_generic_events,
 | 
						.generic_events		= p4_generic_events,
 | 
				
			||||||
	.cache_events		= &power4_cache_events,
 | 
						.cache_events		= &power4_cache_events,
 | 
				
			||||||
 | 
						.flags			= PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init init_power4_pmu(void)
 | 
					static int __init init_power4_pmu(void)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -487,6 +487,7 @@ static struct power_pmu ppc970_pmu = {
 | 
				
			||||||
	.n_generic		= ARRAY_SIZE(ppc970_generic_events),
 | 
						.n_generic		= ARRAY_SIZE(ppc970_generic_events),
 | 
				
			||||||
	.generic_events		= ppc970_generic_events,
 | 
						.generic_events		= ppc970_generic_events,
 | 
				
			||||||
	.cache_events		= &ppc970_cache_events,
 | 
						.cache_events		= &ppc970_cache_events,
 | 
				
			||||||
 | 
						.flags			= PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init init_ppc970_pmu(void)
 | 
					static int __init init_ppc970_pmu(void)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,6 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group,
 | 
				
			||||||
	unsigned long lpar_rc;
 | 
						unsigned long lpar_rc;
 | 
				
			||||||
	u64 hpte_v, hpte_r, slot;
 | 
						u64 hpte_v, hpte_r, slot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* same as iseries */
 | 
					 | 
				
			||||||
	if (vflags & HPTE_V_SECONDARY)
 | 
						if (vflags & HPTE_V_SECONDARY)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -319,7 +318,6 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
 | 
				
			||||||
	unsigned long lpar_rc;
 | 
						unsigned long lpar_rc;
 | 
				
			||||||
	u64 hpte_v, hpte_r, slot;
 | 
						u64 hpte_v, hpte_r, slot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* same as iseries */
 | 
					 | 
				
			||||||
	if (vflags & HPTE_V_SECONDARY)
 | 
						if (vflags & HPTE_V_SECONDARY)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -984,7 +984,8 @@ int __exit eeh_ops_unregister(const char *name)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void __init eeh_init(void)
 | 
					void __init eeh_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device_node *phb, *np;
 | 
						struct pci_controller *hose, *tmp;
 | 
				
			||||||
 | 
						struct device_node *phb;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* call platform initialization function */
 | 
						/* call platform initialization function */
 | 
				
			||||||
| 
						 | 
					@ -1000,19 +1001,9 @@ void __init eeh_init(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	raw_spin_lock_init(&confirm_error_lock);
 | 
						raw_spin_lock_init(&confirm_error_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	np = of_find_node_by_path("/rtas");
 | 
						/* Enable EEH for all adapters */
 | 
				
			||||||
	if (np == NULL)
 | 
						list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 | 
				
			||||||
		return;
 | 
							phb = hose->dn;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Enable EEH for all adapters.  Note that eeh requires buid's */
 | 
					 | 
				
			||||||
	for (phb = of_find_node_by_name(NULL, "pci"); phb;
 | 
					 | 
				
			||||||
	     phb = of_find_node_by_name(phb, "pci")) {
 | 
					 | 
				
			||||||
		unsigned long buid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		buid = get_phb_buid(phb);
 | 
					 | 
				
			||||||
		if (buid == 0 || !of_node_to_eeh_dev(phb))
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		traverse_pci_devices(phb, eeh_early_enable, NULL);
 | 
							traverse_pci_devices(phb, eeh_early_enable, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ void * __devinit eeh_dev_init(struct device_node *dn, void *data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Associate EEH device with OF node */
 | 
						/* Associate EEH device with OF node */
 | 
				
			||||||
	dn->edev  = edev;
 | 
						PCI_DN(dn)->edev = edev;
 | 
				
			||||||
	edev->dn  = dn;
 | 
						edev->dn  = dn;
 | 
				
			||||||
	edev->phb = phb;
 | 
						edev->phb = phb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,72 +63,8 @@ EXPORT_SYMBOL_GPL(pseries_ioei_notifier_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ioei_check_exception_token;
 | 
					static int ioei_check_exception_token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* 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_elog_section {
 | 
					 | 
				
			||||||
	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	*/
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static char ioei_rtas_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
 | 
					static char ioei_rtas_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Find data portion of a specific section in RTAS extended event log.
 | 
					 | 
				
			||||||
 * @elog: RTAS error/event log.
 | 
					 | 
				
			||||||
 * @sect_id: secsion ID.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Return:
 | 
					 | 
				
			||||||
 *	pointer to the section data of the specified section
 | 
					 | 
				
			||||||
 *	NULL if not found
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static struct pseries_elog_section *find_xelog_section(struct rtas_error_log *elog,
 | 
					 | 
				
			||||||
						       uint16_t sect_id)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct rtas_ext_event_log_v6 *xelog =
 | 
					 | 
				
			||||||
		(struct rtas_ext_event_log_v6 *) elog->buffer;
 | 
					 | 
				
			||||||
	struct pseries_elog_section *sect;
 | 
					 | 
				
			||||||
	unsigned char *p, *log_end;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Check that we understand the format */
 | 
					 | 
				
			||||||
	if (elog->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
 | 
					 | 
				
			||||||
	    xelog->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
 | 
					 | 
				
			||||||
	    xelog->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log_end = elog->buffer + elog->extended_log_length;
 | 
					 | 
				
			||||||
	p = xelog->vendor_log;
 | 
					 | 
				
			||||||
	while (p < log_end) {
 | 
					 | 
				
			||||||
		sect = (struct pseries_elog_section *)p;
 | 
					 | 
				
			||||||
		if (sect->id == sect_id)
 | 
					 | 
				
			||||||
			return sect;
 | 
					 | 
				
			||||||
		p += sect->length;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Find the data portion of an IO Event section from event log.
 | 
					 * Find the data portion of an IO Event section from event log.
 | 
				
			||||||
 * @elog: RTAS error/event log.
 | 
					 * @elog: RTAS error/event log.
 | 
				
			||||||
| 
						 | 
					@ -138,7 +74,7 @@ static struct pseries_elog_section *find_xelog_section(struct rtas_error_log *el
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog)
 | 
					static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pseries_elog_section *sect;
 | 
						struct pseries_errorlog *sect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We should only ever get called for io-event interrupts, but if
 | 
						/* We should only ever get called for io-event interrupts, but if
 | 
				
			||||||
	 * we do get called for another type then something went wrong so
 | 
						 * we do get called for another type then something went wrong so
 | 
				
			||||||
| 
						 | 
					@ -152,7 +88,7 @@ static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sect = find_xelog_section(elog, PSERIES_ELOG_SECT_ID_IO_EVENT);
 | 
						sect = get_pseries_errorlog(elog, PSERIES_ELOG_SECT_ID_IO_EVENT);
 | 
				
			||||||
	if (unlikely(!sect)) {
 | 
						if (unlikely(!sect)) {
 | 
				
			||||||
		printk_once(KERN_WARNING "io_event_irq: RTAS extended event "
 | 
							printk_once(KERN_WARNING "io_event_irq: RTAS extended event "
 | 
				
			||||||
			    "log does not contain an IO Event section. "
 | 
								    "log does not contain an IO Event section. "
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -809,8 +809,7 @@ machine_arch_initcall(pseries, find_existing_ddw_windows);
 | 
				
			||||||
static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 | 
					static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 | 
				
			||||||
			struct ddw_query_response *query)
 | 
								struct ddw_query_response *query)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device_node *dn;
 | 
						struct eeh_dev *edev;
 | 
				
			||||||
	struct pci_dn *pcidn;
 | 
					 | 
				
			||||||
	u32 cfg_addr;
 | 
						u32 cfg_addr;
 | 
				
			||||||
	u64 buid;
 | 
						u64 buid;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -821,12 +820,12 @@ static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 | 
				
			||||||
	 * Retrieve them from the pci device, not the node with the
 | 
						 * Retrieve them from the pci device, not the node with the
 | 
				
			||||||
	 * dma-window property
 | 
						 * dma-window property
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	dn = pci_device_to_OF_node(dev);
 | 
						edev = pci_dev_to_eeh_dev(dev);
 | 
				
			||||||
	pcidn = PCI_DN(dn);
 | 
						cfg_addr = edev->config_addr;
 | 
				
			||||||
	cfg_addr = pcidn->eeh_config_addr;
 | 
						if (edev->pe_config_addr)
 | 
				
			||||||
	if (pcidn->eeh_pe_config_addr)
 | 
							cfg_addr = edev->pe_config_addr;
 | 
				
			||||||
		cfg_addr = pcidn->eeh_pe_config_addr;
 | 
						buid = edev->phb->buid;
 | 
				
			||||||
	buid = pcidn->phb->buid;
 | 
					
 | 
				
			||||||
	ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
 | 
						ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
 | 
				
			||||||
		  cfg_addr, BUID_HI(buid), BUID_LO(buid));
 | 
							  cfg_addr, BUID_HI(buid), BUID_LO(buid));
 | 
				
			||||||
	dev_info(&dev->dev, "ibm,query-pe-dma-windows(%x) %x %x %x"
 | 
						dev_info(&dev->dev, "ibm,query-pe-dma-windows(%x) %x %x %x"
 | 
				
			||||||
| 
						 | 
					@ -839,8 +838,7 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 | 
				
			||||||
			struct ddw_create_response *create, int page_shift,
 | 
								struct ddw_create_response *create, int page_shift,
 | 
				
			||||||
			int window_shift)
 | 
								int window_shift)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device_node *dn;
 | 
						struct eeh_dev *edev;
 | 
				
			||||||
	struct pci_dn *pcidn;
 | 
					 | 
				
			||||||
	u32 cfg_addr;
 | 
						u32 cfg_addr;
 | 
				
			||||||
	u64 buid;
 | 
						u64 buid;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -851,12 +849,11 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 | 
				
			||||||
	 * Retrieve them from the pci device, not the node with the
 | 
						 * Retrieve them from the pci device, not the node with the
 | 
				
			||||||
	 * dma-window property
 | 
						 * dma-window property
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	dn = pci_device_to_OF_node(dev);
 | 
						edev = pci_dev_to_eeh_dev(dev);
 | 
				
			||||||
	pcidn = PCI_DN(dn);
 | 
						cfg_addr = edev->config_addr;
 | 
				
			||||||
	cfg_addr = pcidn->eeh_config_addr;
 | 
						if (edev->pe_config_addr)
 | 
				
			||||||
	if (pcidn->eeh_pe_config_addr)
 | 
							cfg_addr = edev->pe_config_addr;
 | 
				
			||||||
		cfg_addr = pcidn->eeh_pe_config_addr;
 | 
						buid = edev->phb->buid;
 | 
				
			||||||
	buid = pcidn->phb->buid;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		/* extra outputs are LIOBN and dma-addr (hi, lo) */
 | 
							/* extra outputs are LIOBN and dma-addr (hi, lo) */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,37 +16,15 @@
 | 
				
			||||||
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 | 
					 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Change Activity:
 | 
					 | 
				
			||||||
 * 2001/09/21 : engebret : Created with minimal EPOW and HW exception support.
 | 
					 | 
				
			||||||
 * End Change Activity
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <linux/errno.h>
 | 
					 | 
				
			||||||
#include <linux/threads.h>
 | 
					 | 
				
			||||||
#include <linux/kernel_stat.h>
 | 
					 | 
				
			||||||
#include <linux/signal.h>
 | 
					 | 
				
			||||||
#include <linux/sched.h>
 | 
					#include <linux/sched.h>
 | 
				
			||||||
#include <linux/ioport.h>
 | 
					 | 
				
			||||||
#include <linux/interrupt.h>
 | 
					#include <linux/interrupt.h>
 | 
				
			||||||
#include <linux/timex.h>
 | 
					 | 
				
			||||||
#include <linux/init.h>
 | 
					 | 
				
			||||||
#include <linux/delay.h>
 | 
					 | 
				
			||||||
#include <linux/irq.h>
 | 
					#include <linux/irq.h>
 | 
				
			||||||
#include <linux/random.h>
 | 
					#include <linux/of.h>
 | 
				
			||||||
#include <linux/sysrq.h>
 | 
					#include <linux/fs.h>
 | 
				
			||||||
#include <linux/bitops.h>
 | 
					#include <linux/reboot.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <asm/uaccess.h>
 | 
					 | 
				
			||||||
#include <asm/system.h>
 | 
					 | 
				
			||||||
#include <asm/io.h>
 | 
					 | 
				
			||||||
#include <asm/pgtable.h>
 | 
					 | 
				
			||||||
#include <asm/irq.h>
 | 
					 | 
				
			||||||
#include <asm/cache.h>
 | 
					 | 
				
			||||||
#include <asm/prom.h>
 | 
					 | 
				
			||||||
#include <asm/ptrace.h>
 | 
					 | 
				
			||||||
#include <asm/machdep.h>
 | 
					#include <asm/machdep.h>
 | 
				
			||||||
#include <asm/rtas.h>
 | 
					#include <asm/rtas.h>
 | 
				
			||||||
#include <asm/udbg.h>
 | 
					 | 
				
			||||||
#include <asm/firmware.h>
 | 
					#include <asm/firmware.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "pseries.h"
 | 
					#include "pseries.h"
 | 
				
			||||||
| 
						 | 
					@ -57,7 +35,6 @@ static DEFINE_SPINLOCK(ras_log_buf_lock);
 | 
				
			||||||
static char global_mce_data_buf[RTAS_ERROR_LOG_MAX];
 | 
					static char global_mce_data_buf[RTAS_ERROR_LOG_MAX];
 | 
				
			||||||
static DEFINE_PER_CPU(__u64, mce_data_buf);
 | 
					static DEFINE_PER_CPU(__u64, mce_data_buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ras_get_sensor_state_token;
 | 
					 | 
				
			||||||
static int ras_check_exception_token;
 | 
					static int ras_check_exception_token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EPOW_SENSOR_TOKEN	9
 | 
					#define EPOW_SENSOR_TOKEN	9
 | 
				
			||||||
| 
						 | 
					@ -75,7 +52,6 @@ static int __init init_ras_IRQ(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device_node *np;
 | 
						struct device_node *np;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ras_get_sensor_state_token = rtas_token("get-sensor-state");
 | 
					 | 
				
			||||||
	ras_check_exception_token = rtas_token("check-exception");
 | 
						ras_check_exception_token = rtas_token("check-exception");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Internal Errors */
 | 
						/* Internal Errors */
 | 
				
			||||||
| 
						 | 
					@ -95,23 +71,123 @@ static int __init init_ras_IRQ(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
__initcall(init_ras_IRQ);
 | 
					subsys_initcall(init_ras_IRQ);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					#define EPOW_SHUTDOWN_NORMAL				1
 | 
				
			||||||
 * Handle power subsystem events (EPOW).
 | 
					#define EPOW_SHUTDOWN_ON_UPS				2
 | 
				
			||||||
 *
 | 
					#define EPOW_SHUTDOWN_LOSS_OF_CRITICAL_FUNCTIONS	3
 | 
				
			||||||
 * Presently we just log the event has occurred.  This should be fixed
 | 
					#define EPOW_SHUTDOWN_AMBIENT_TEMPERATURE_TOO_HIGH	4
 | 
				
			||||||
 * to examine the type of power failure and take appropriate action where
 | 
					
 | 
				
			||||||
 * the time horizon permits something useful to be done.
 | 
					static void handle_system_shutdown(char event_modifier)
 | 
				
			||||||
 */
 | 
					{
 | 
				
			||||||
 | 
						switch (event_modifier) {
 | 
				
			||||||
 | 
						case EPOW_SHUTDOWN_NORMAL:
 | 
				
			||||||
 | 
							pr_emerg("Firmware initiated power off");
 | 
				
			||||||
 | 
							orderly_poweroff(1);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case EPOW_SHUTDOWN_ON_UPS:
 | 
				
			||||||
 | 
							pr_emerg("Loss of power reported by firmware, system is "
 | 
				
			||||||
 | 
								"running on UPS/battery");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case EPOW_SHUTDOWN_LOSS_OF_CRITICAL_FUNCTIONS:
 | 
				
			||||||
 | 
							pr_emerg("Loss of system critical functions reported by "
 | 
				
			||||||
 | 
								"firmware");
 | 
				
			||||||
 | 
							pr_emerg("Check RTAS error log for details");
 | 
				
			||||||
 | 
							orderly_poweroff(1);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case EPOW_SHUTDOWN_AMBIENT_TEMPERATURE_TOO_HIGH:
 | 
				
			||||||
 | 
							pr_emerg("Ambient temperature too high reported by firmware");
 | 
				
			||||||
 | 
							pr_emerg("Check RTAS error log for details");
 | 
				
			||||||
 | 
							orderly_poweroff(1);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							pr_err("Unknown power/cooling shutdown event (modifier %d)",
 | 
				
			||||||
 | 
								event_modifier);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct epow_errorlog {
 | 
				
			||||||
 | 
						unsigned char sensor_value;
 | 
				
			||||||
 | 
						unsigned char event_modifier;
 | 
				
			||||||
 | 
						unsigned char extended_modifier;
 | 
				
			||||||
 | 
						unsigned char reserved;
 | 
				
			||||||
 | 
						unsigned char platform_reason;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EPOW_RESET			0
 | 
				
			||||||
 | 
					#define EPOW_WARN_COOLING		1
 | 
				
			||||||
 | 
					#define EPOW_WARN_POWER			2
 | 
				
			||||||
 | 
					#define EPOW_SYSTEM_SHUTDOWN		3
 | 
				
			||||||
 | 
					#define EPOW_SYSTEM_HALT		4
 | 
				
			||||||
 | 
					#define EPOW_MAIN_ENCLOSURE		5
 | 
				
			||||||
 | 
					#define EPOW_POWER_OFF			7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rtas_parse_epow_errlog(struct rtas_error_log *log)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct pseries_errorlog *pseries_log;
 | 
				
			||||||
 | 
						struct epow_errorlog *epow_log;
 | 
				
			||||||
 | 
						char action_code;
 | 
				
			||||||
 | 
						char modifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pseries_log = get_pseries_errorlog(log, PSERIES_ELOG_SECT_ID_EPOW);
 | 
				
			||||||
 | 
						if (pseries_log == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						epow_log = (struct epow_errorlog *)pseries_log->data;
 | 
				
			||||||
 | 
						action_code = epow_log->sensor_value & 0xF;	/* bottom 4 bits */
 | 
				
			||||||
 | 
						modifier = epow_log->event_modifier & 0xF;	/* bottom 4 bits */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (action_code) {
 | 
				
			||||||
 | 
						case EPOW_RESET:
 | 
				
			||||||
 | 
							pr_err("Non critical power or cooling issue cleared");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case EPOW_WARN_COOLING:
 | 
				
			||||||
 | 
							pr_err("Non critical cooling issue reported by firmware");
 | 
				
			||||||
 | 
							pr_err("Check RTAS error log for details");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case EPOW_WARN_POWER:
 | 
				
			||||||
 | 
							pr_err("Non critical power issue reported by firmware");
 | 
				
			||||||
 | 
							pr_err("Check RTAS error log for details");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case EPOW_SYSTEM_SHUTDOWN:
 | 
				
			||||||
 | 
							handle_system_shutdown(epow_log->event_modifier);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case EPOW_SYSTEM_HALT:
 | 
				
			||||||
 | 
							pr_emerg("Firmware initiated power off");
 | 
				
			||||||
 | 
							orderly_poweroff(1);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case EPOW_MAIN_ENCLOSURE:
 | 
				
			||||||
 | 
						case EPOW_POWER_OFF:
 | 
				
			||||||
 | 
							pr_emerg("Critical power/cooling issue reported by firmware");
 | 
				
			||||||
 | 
							pr_emerg("Check RTAS error log for details");
 | 
				
			||||||
 | 
							pr_emerg("Immediate power off");
 | 
				
			||||||
 | 
							emergency_sync();
 | 
				
			||||||
 | 
							kernel_power_off();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							pr_err("Unknown power/cooling event (action code %d)",
 | 
				
			||||||
 | 
								action_code);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Handle environmental and power warning (EPOW) interrupts. */
 | 
				
			||||||
static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
 | 
					static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int status = 0xdeadbeef;
 | 
						int status;
 | 
				
			||||||
	int state = 0;
 | 
						int state;
 | 
				
			||||||
	int critical;
 | 
						int critical;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status = rtas_call(ras_get_sensor_state_token, 2, 2, &state,
 | 
						status = rtas_get_sensor(EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX, &state);
 | 
				
			||||||
			   EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (state > 3)
 | 
						if (state > 3)
 | 
				
			||||||
		critical = 1;		/* Time Critical */
 | 
							critical = 1;		/* Time Critical */
 | 
				
			||||||
| 
						 | 
					@ -123,18 +199,14 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
 | 
				
			||||||
	status = rtas_call(ras_check_exception_token, 6, 1, NULL,
 | 
						status = rtas_call(ras_check_exception_token, 6, 1, NULL,
 | 
				
			||||||
			   RTAS_VECTOR_EXTERNAL_INTERRUPT,
 | 
								   RTAS_VECTOR_EXTERNAL_INTERRUPT,
 | 
				
			||||||
			   virq_to_hw(irq),
 | 
								   virq_to_hw(irq),
 | 
				
			||||||
			   RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
 | 
								   RTAS_EPOW_WARNING,
 | 
				
			||||||
			   critical, __pa(&ras_log_buf),
 | 
								   critical, __pa(&ras_log_buf),
 | 
				
			||||||
				rtas_get_error_log_max());
 | 
									rtas_get_error_log_max());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udbg_printf("EPOW <0x%lx 0x%x 0x%x>\n",
 | 
					 | 
				
			||||||
		    *((unsigned long *)&ras_log_buf), status, state);
 | 
					 | 
				
			||||||
	printk(KERN_WARNING "EPOW <0x%lx 0x%x 0x%x>\n",
 | 
					 | 
				
			||||||
	       *((unsigned long *)&ras_log_buf), status, state);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* format and print the extended information */
 | 
					 | 
				
			||||||
	log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);
 | 
						log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rtas_parse_epow_errlog((struct rtas_error_log *)ras_log_buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock(&ras_log_buf_lock);
 | 
						spin_unlock(&ras_log_buf_lock);
 | 
				
			||||||
	return IRQ_HANDLED;
 | 
						return IRQ_HANDLED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -150,7 +222,7 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
 | 
				
			||||||
static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
 | 
					static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rtas_error_log *rtas_elog;
 | 
						struct rtas_error_log *rtas_elog;
 | 
				
			||||||
	int status = 0xdeadbeef;
 | 
						int status;
 | 
				
			||||||
	int fatal;
 | 
						int fatal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock(&ras_log_buf_lock);
 | 
						spin_lock(&ras_log_buf_lock);
 | 
				
			||||||
| 
						 | 
					@ -173,24 +245,13 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
 | 
				
			||||||
	log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, fatal);
 | 
						log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, fatal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fatal) {
 | 
						if (fatal) {
 | 
				
			||||||
		udbg_printf("Fatal HW Error <0x%lx 0x%x>\n",
 | 
							pr_emerg("Fatal hardware error reported by firmware");
 | 
				
			||||||
			    *((unsigned long *)&ras_log_buf), status);
 | 
							pr_emerg("Check RTAS error log for details");
 | 
				
			||||||
		printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
 | 
							pr_emerg("Immediate power off");
 | 
				
			||||||
		       *((unsigned long *)&ras_log_buf), status);
 | 
							emergency_sync();
 | 
				
			||||||
 | 
							kernel_power_off();
 | 
				
			||||||
#ifndef DEBUG_RTAS_POWER_OFF
 | 
					 | 
				
			||||||
		/* Don't actually power off when debugging so we can test
 | 
					 | 
				
			||||||
		 * without actually failing while injecting errors.
 | 
					 | 
				
			||||||
		 * Error data will not be logged to syslog.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		ppc_md.power_off();
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		udbg_printf("Recoverable HW Error <0x%lx 0x%x>\n",
 | 
							pr_err("Recoverable hardware error reported by firmware");
 | 
				
			||||||
			    *((unsigned long *)&ras_log_buf), status);
 | 
					 | 
				
			||||||
		printk(KERN_WARNING
 | 
					 | 
				
			||||||
		       "Warning: Recoverable hardware error <0x%lx 0x%x>\n",
 | 
					 | 
				
			||||||
		       *((unsigned long *)&ras_log_buf), status);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock(&ras_log_buf_lock);
 | 
						spin_unlock(&ras_log_buf_lock);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -284,6 +284,7 @@ struct vio_dev {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct vio_driver {
 | 
					struct vio_driver {
 | 
				
			||||||
 | 
						const char			*name;
 | 
				
			||||||
	struct list_head		node;
 | 
						struct list_head		node;
 | 
				
			||||||
	const struct vio_device_id	*id_table;
 | 
						const struct vio_device_id	*id_table;
 | 
				
			||||||
	int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
 | 
						int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
 | 
				
			||||||
| 
						 | 
					@ -371,7 +372,13 @@ do {	if (vio->debug & VIO_DEBUG_##TYPE) \
 | 
				
			||||||
		       vio->vdev->channel_id, ## a); \
 | 
							       vio->vdev->channel_id, ## a); \
 | 
				
			||||||
} while (0)
 | 
					} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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 void vio_unregister_driver(struct vio_driver *drv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
 | 
					static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1244,10 +1244,7 @@ static struct vio_driver ds_driver = {
 | 
				
			||||||
	.id_table	= ds_match,
 | 
						.id_table	= ds_match,
 | 
				
			||||||
	.probe		= ds_probe,
 | 
						.probe		= ds_probe,
 | 
				
			||||||
	.remove		= ds_remove,
 | 
						.remove		= ds_remove,
 | 
				
			||||||
	.driver		= {
 | 
					 | 
				
			||||||
	.name		= "ds",
 | 
						.name		= "ds",
 | 
				
			||||||
		.owner	= THIS_MODULE,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init ds_init(void)
 | 
					static int __init ds_init(void)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,13 +119,17 @@ static struct bus_type vio_bus_type = {
 | 
				
			||||||
	.remove		= vio_device_remove,
 | 
						.remove		= vio_device_remove,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int vio_register_driver(struct vio_driver *viodrv)
 | 
					int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
 | 
				
			||||||
 | 
								const char *mod_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	viodrv->driver.bus = &vio_bus_type;
 | 
						viodrv->driver.bus = &vio_bus_type;
 | 
				
			||||||
 | 
						viodrv->driver.name = viodrv->name;
 | 
				
			||||||
 | 
						viodrv->driver.owner = owner;
 | 
				
			||||||
 | 
						viodrv->driver.mod_name = mod_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return driver_register(&viodrv->driver);
 | 
						return driver_register(&viodrv->driver);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(vio_register_driver);
 | 
					EXPORT_SYMBOL(__vio_register_driver);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void vio_unregister_driver(struct vio_driver *viodrv)
 | 
					void vio_unregister_driver(struct vio_driver *viodrv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -839,10 +839,7 @@ static struct vio_driver vdc_port_driver = {
 | 
				
			||||||
	.id_table	= vdc_port_match,
 | 
						.id_table	= vdc_port_match,
 | 
				
			||||||
	.probe		= vdc_port_probe,
 | 
						.probe		= vdc_port_probe,
 | 
				
			||||||
	.remove		= vdc_port_remove,
 | 
						.remove		= vdc_port_remove,
 | 
				
			||||||
	.driver		= {
 | 
					 | 
				
			||||||
	.name		= "vdc_port",
 | 
						.name		= "vdc_port",
 | 
				
			||||||
		.owner	= THIS_MODULE,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init vdc_init(void)
 | 
					static int __init vdc_init(void)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1616,11 +1616,8 @@ static struct vio_driver ibmveth_driver = {
 | 
				
			||||||
	.probe		= ibmveth_probe,
 | 
						.probe		= ibmveth_probe,
 | 
				
			||||||
	.remove		= ibmveth_remove,
 | 
						.remove		= ibmveth_remove,
 | 
				
			||||||
	.get_desired_dma = ibmveth_get_desired_dma,
 | 
						.get_desired_dma = ibmveth_get_desired_dma,
 | 
				
			||||||
	.driver		= {
 | 
					 | 
				
			||||||
	.name		= ibmveth_driver_name,
 | 
						.name		= ibmveth_driver_name,
 | 
				
			||||||
		.owner	= THIS_MODULE,
 | 
					 | 
				
			||||||
	.pm		= &ibmveth_pm_ops,
 | 
						.pm		= &ibmveth_pm_ops,
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init ibmveth_module_init(void)
 | 
					static int __init ibmveth_module_init(void)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1259,10 +1259,7 @@ static struct vio_driver vnet_port_driver = {
 | 
				
			||||||
	.id_table	= vnet_port_match,
 | 
						.id_table	= vnet_port_match,
 | 
				
			||||||
	.probe		= vnet_port_probe,
 | 
						.probe		= vnet_port_probe,
 | 
				
			||||||
	.remove		= vnet_port_remove,
 | 
						.remove		= vnet_port_remove,
 | 
				
			||||||
	.driver		= {
 | 
					 | 
				
			||||||
	.name		= "vnet_port",
 | 
						.name		= "vnet_port",
 | 
				
			||||||
		.owner	= THIS_MODULE,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init vnet_init(void)
 | 
					static int __init vnet_init(void)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4890,11 +4890,8 @@ static struct vio_driver ibmvfc_driver = {
 | 
				
			||||||
	.probe = ibmvfc_probe,
 | 
						.probe = ibmvfc_probe,
 | 
				
			||||||
	.remove = ibmvfc_remove,
 | 
						.remove = ibmvfc_remove,
 | 
				
			||||||
	.get_desired_dma = ibmvfc_get_desired_dma,
 | 
						.get_desired_dma = ibmvfc_get_desired_dma,
 | 
				
			||||||
	.driver = {
 | 
					 | 
				
			||||||
	.name = IBMVFC_NAME,
 | 
						.name = IBMVFC_NAME,
 | 
				
			||||||
		.owner = THIS_MODULE,
 | 
					 | 
				
			||||||
	.pm = &ibmvfc_pm_ops,
 | 
						.pm = &ibmvfc_pm_ops,
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct fc_function_template ibmvfc_transport_functions = {
 | 
					static struct fc_function_template ibmvfc_transport_functions = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2061,11 +2061,8 @@ static struct vio_driver ibmvscsi_driver = {
 | 
				
			||||||
	.probe = ibmvscsi_probe,
 | 
						.probe = ibmvscsi_probe,
 | 
				
			||||||
	.remove = ibmvscsi_remove,
 | 
						.remove = ibmvscsi_remove,
 | 
				
			||||||
	.get_desired_dma = ibmvscsi_get_desired_dma,
 | 
						.get_desired_dma = ibmvscsi_get_desired_dma,
 | 
				
			||||||
	.driver = {
 | 
					 | 
				
			||||||
	.name = "ibmvscsi",
 | 
						.name = "ibmvscsi",
 | 
				
			||||||
		.owner = THIS_MODULE,
 | 
					 | 
				
			||||||
	.pm = &ibmvscsi_pm_ops,
 | 
						.pm = &ibmvscsi_pm_ops,
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct srp_function_template ibmvscsi_transport_functions = {
 | 
					static struct srp_function_template ibmvscsi_transport_functions = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -918,10 +918,7 @@ static struct vio_driver ibmvstgt_driver = {
 | 
				
			||||||
	.id_table = ibmvstgt_device_table,
 | 
						.id_table = ibmvstgt_device_table,
 | 
				
			||||||
	.probe = ibmvstgt_probe,
 | 
						.probe = ibmvstgt_probe,
 | 
				
			||||||
	.remove = ibmvstgt_remove,
 | 
						.remove = ibmvstgt_remove,
 | 
				
			||||||
	.driver = {
 | 
					 | 
				
			||||||
	.name = "ibmvscsis",
 | 
						.name = "ibmvscsis",
 | 
				
			||||||
		.owner = THIS_MODULE,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int get_system_info(void)
 | 
					static int get_system_info(void)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -310,11 +310,8 @@ static int __devexit hvc_vio_remove(struct vio_dev *vdev)
 | 
				
			||||||
static struct vio_driver hvc_vio_driver = {
 | 
					static struct vio_driver hvc_vio_driver = {
 | 
				
			||||||
	.id_table	= hvc_driver_table,
 | 
						.id_table	= hvc_driver_table,
 | 
				
			||||||
	.probe		= hvc_vio_probe,
 | 
						.probe		= hvc_vio_probe,
 | 
				
			||||||
	.remove		= __devexit_p(hvc_vio_remove),
 | 
						.remove		= hvc_vio_remove,
 | 
				
			||||||
	.driver		= {
 | 
					 | 
				
			||||||
	.name		= hvc_driver_name,
 | 
						.name		= hvc_driver_name,
 | 
				
			||||||
		.owner	= THIS_MODULE,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init hvc_vio_init(void)
 | 
					static int __init hvc_vio_init(void)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -879,10 +879,7 @@ static struct vio_driver hvcs_vio_driver = {
 | 
				
			||||||
	.id_table	= hvcs_driver_table,
 | 
						.id_table	= hvcs_driver_table,
 | 
				
			||||||
	.probe		= hvcs_probe,
 | 
						.probe		= hvcs_probe,
 | 
				
			||||||
	.remove		= __devexit_p(hvcs_remove),
 | 
						.remove		= __devexit_p(hvcs_remove),
 | 
				
			||||||
	.driver		= {
 | 
					 | 
				
			||||||
	.name		= hvcs_driver_name,
 | 
						.name		= hvcs_driver_name,
 | 
				
			||||||
		.owner	= THIS_MODULE,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Only called from hvcs_get_pi please */
 | 
					/* Only called from hvcs_get_pi please */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,9 +58,6 @@ struct device_node {
 | 
				
			||||||
	struct	kref kref;
 | 
						struct	kref kref;
 | 
				
			||||||
	unsigned long _flags;
 | 
						unsigned long _flags;
 | 
				
			||||||
	void	*data;
 | 
						void	*data;
 | 
				
			||||||
#if defined(CONFIG_EEH)
 | 
					 | 
				
			||||||
	struct eeh_dev *edev;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#if defined(CONFIG_SPARC)
 | 
					#if defined(CONFIG_SPARC)
 | 
				
			||||||
	char	*path_component_name;
 | 
						char	*path_component_name;
 | 
				
			||||||
	unsigned int unique_id;
 | 
						unsigned int unique_id;
 | 
				
			||||||
| 
						 | 
					@ -75,13 +72,6 @@ struct of_phandle_args {
 | 
				
			||||||
	uint32_t args[MAX_PHANDLE_ARGS];
 | 
						uint32_t args[MAX_PHANDLE_ARGS];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(CONFIG_EEH)
 | 
					 | 
				
			||||||
static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return dn->edev;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_OF_DYNAMIC
 | 
					#ifdef CONFIG_OF_DYNAMIC
 | 
				
			||||||
extern struct device_node *of_node_get(struct device_node *node);
 | 
					extern struct device_node *of_node_get(struct device_node *node);
 | 
				
			||||||
extern void of_node_put(struct device_node *node);
 | 
					extern void of_node_put(struct device_node *node);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue