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.coff
|
||||
zImage.holly
|
||||
zImage.iseries
|
||||
zImage.*lds
|
||||
zImage.miboot
|
||||
zImage.pmac
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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_ */
|
||||
|
|
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -69,6 +69,7 @@ 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);
|
||||
|
@ -76,10 +77,17 @@ struct vio_driver {
|
|||
* 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);
|
||||
|
|
|
@ -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();
|
||||
|
@ -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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
ip = mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
|
||||
return ip;
|
||||
/* Processor doesn't support sampling non marked events */
|
||||
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)
|
||||
|
|
|
@ -607,6 +607,7 @@ static struct power_pmu power4_pmu = {
|
|||
.n_generic = ARRAY_SIZE(p4_generic_events),
|
||||
.generic_events = p4_generic_events,
|
||||
.cache_events = &power4_cache_events,
|
||||
.flags = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
|
||||
};
|
||||
|
||||
static int __init init_power4_pmu(void)
|
||||
|
|
|
@ -487,6 +487,7 @@ static struct power_pmu ppc970_pmu = {
|
|||
.n_generic = ARRAY_SIZE(ppc970_generic_events),
|
||||
.generic_events = ppc970_generic_events,
|
||||
.cache_events = &ppc970_cache_events,
|
||||
.flags = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
|
||||
};
|
||||
|
||||
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;
|
||||
u64 hpte_v, hpte_r, slot;
|
||||
|
||||
/* same as iseries */
|
||||
if (vflags & HPTE_V_SECONDARY)
|
||||
return -1;
|
||||
|
||||
|
@ -319,7 +318,6 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
|
|||
unsigned long lpar_rc;
|
||||
u64 hpte_v, hpte_r, slot;
|
||||
|
||||
/* same as iseries */
|
||||
if (vflags & HPTE_V_SECONDARY)
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -984,7 +984,8 @@ int __exit eeh_ops_unregister(const char *name)
|
|||
*/
|
||||
void __init eeh_init(void)
|
||||
{
|
||||
struct device_node *phb, *np;
|
||||
struct pci_controller *hose, *tmp;
|
||||
struct device_node *phb;
|
||||
int ret;
|
||||
|
||||
/* call platform initialization function */
|
||||
|
@ -1000,19 +1001,9 @@ void __init eeh_init(void)
|
|||
|
||||
raw_spin_lock_init(&confirm_error_lock);
|
||||
|
||||
np = of_find_node_by_path("/rtas");
|
||||
if (np == NULL)
|
||||
return;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Enable EEH for all adapters */
|
||||
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
|
||||
phb = hose->dn;
|
||||
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 */
|
||||
dn->edev = edev;
|
||||
PCI_DN(dn)->edev = edev;
|
||||
edev->dn = dn;
|
||||
edev->phb = phb;
|
||||
|
||||
|
|
|
@ -63,72 +63,8 @@ EXPORT_SYMBOL_GPL(pseries_ioei_notifier_list);
|
|||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @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)
|
||||
{
|
||||
struct pseries_elog_section *sect;
|
||||
struct pseries_errorlog *sect;
|
||||
|
||||
/* We should only ever get called for io-event interrupts, but if
|
||||
* 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;
|
||||
}
|
||||
|
||||
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)) {
|
||||
printk_once(KERN_WARNING "io_event_irq: RTAS extended event "
|
||||
"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,
|
||||
struct ddw_query_response *query)
|
||||
{
|
||||
struct device_node *dn;
|
||||
struct pci_dn *pcidn;
|
||||
struct eeh_dev *edev;
|
||||
u32 cfg_addr;
|
||||
u64 buid;
|
||||
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
|
||||
* dma-window property
|
||||
*/
|
||||
dn = pci_device_to_OF_node(dev);
|
||||
pcidn = PCI_DN(dn);
|
||||
cfg_addr = pcidn->eeh_config_addr;
|
||||
if (pcidn->eeh_pe_config_addr)
|
||||
cfg_addr = pcidn->eeh_pe_config_addr;
|
||||
buid = pcidn->phb->buid;
|
||||
edev = pci_dev_to_eeh_dev(dev);
|
||||
cfg_addr = edev->config_addr;
|
||||
if (edev->pe_config_addr)
|
||||
cfg_addr = edev->pe_config_addr;
|
||||
buid = edev->phb->buid;
|
||||
|
||||
ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
|
||||
cfg_addr, BUID_HI(buid), BUID_LO(buid));
|
||||
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,
|
||||
int window_shift)
|
||||
{
|
||||
struct device_node *dn;
|
||||
struct pci_dn *pcidn;
|
||||
struct eeh_dev *edev;
|
||||
u32 cfg_addr;
|
||||
u64 buid;
|
||||
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
|
||||
* dma-window property
|
||||
*/
|
||||
dn = pci_device_to_OF_node(dev);
|
||||
pcidn = PCI_DN(dn);
|
||||
cfg_addr = pcidn->eeh_config_addr;
|
||||
if (pcidn->eeh_pe_config_addr)
|
||||
cfg_addr = pcidn->eeh_pe_config_addr;
|
||||
buid = pcidn->phb->buid;
|
||||
edev = pci_dev_to_eeh_dev(dev);
|
||||
cfg_addr = edev->config_addr;
|
||||
if (edev->pe_config_addr)
|
||||
cfg_addr = edev->pe_config_addr;
|
||||
buid = edev->phb->buid;
|
||||
|
||||
do {
|
||||
/* 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
|
||||
*/
|
||||
|
||||
/* 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/ioport.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/fs.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/rtas.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/firmware.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 DEFINE_PER_CPU(__u64, mce_data_buf);
|
||||
|
||||
static int ras_get_sensor_state_token;
|
||||
static int ras_check_exception_token;
|
||||
|
||||
#define EPOW_SENSOR_TOKEN 9
|
||||
|
@ -75,7 +52,6 @@ static int __init init_ras_IRQ(void)
|
|||
{
|
||||
struct device_node *np;
|
||||
|
||||
ras_get_sensor_state_token = rtas_token("get-sensor-state");
|
||||
ras_check_exception_token = rtas_token("check-exception");
|
||||
|
||||
/* Internal Errors */
|
||||
|
@ -95,26 +71,126 @@ static int __init init_ras_IRQ(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
__initcall(init_ras_IRQ);
|
||||
subsys_initcall(init_ras_IRQ);
|
||||
|
||||
/*
|
||||
* Handle power subsystem events (EPOW).
|
||||
*
|
||||
* Presently we just log the event has occurred. This should be fixed
|
||||
* to examine the type of power failure and take appropriate action where
|
||||
* the time horizon permits something useful to be done.
|
||||
*/
|
||||
#define EPOW_SHUTDOWN_NORMAL 1
|
||||
#define EPOW_SHUTDOWN_ON_UPS 2
|
||||
#define EPOW_SHUTDOWN_LOSS_OF_CRITICAL_FUNCTIONS 3
|
||||
#define EPOW_SHUTDOWN_AMBIENT_TEMPERATURE_TOO_HIGH 4
|
||||
|
||||
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)
|
||||
{
|
||||
int status = 0xdeadbeef;
|
||||
int state = 0;
|
||||
int status;
|
||||
int state;
|
||||
int critical;
|
||||
|
||||
status = rtas_call(ras_get_sensor_state_token, 2, 2, &state,
|
||||
EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX);
|
||||
status = rtas_get_sensor(EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX, &state);
|
||||
|
||||
if (state > 3)
|
||||
critical = 1; /* Time Critical */
|
||||
critical = 1; /* Time Critical */
|
||||
else
|
||||
critical = 0;
|
||||
|
||||
|
@ -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,
|
||||
RTAS_VECTOR_EXTERNAL_INTERRUPT,
|
||||
virq_to_hw(irq),
|
||||
RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
|
||||
RTAS_EPOW_WARNING,
|
||||
critical, __pa(&ras_log_buf),
|
||||
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);
|
||||
|
||||
rtas_parse_epow_errlog((struct rtas_error_log *)ras_log_buf);
|
||||
|
||||
spin_unlock(&ras_log_buf_lock);
|
||||
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)
|
||||
{
|
||||
struct rtas_error_log *rtas_elog;
|
||||
int status = 0xdeadbeef;
|
||||
int status;
|
||||
int fatal;
|
||||
|
||||
spin_lock(&ras_log_buf_lock);
|
||||
|
@ -158,7 +230,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
|
|||
status = rtas_call(ras_check_exception_token, 6, 1, NULL,
|
||||
RTAS_VECTOR_EXTERNAL_INTERRUPT,
|
||||
virq_to_hw(irq),
|
||||
RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
|
||||
RTAS_INTERNAL_ERROR, 1 /* Time Critical */,
|
||||
__pa(&ras_log_buf),
|
||||
rtas_get_error_log_max());
|
||||
|
||||
|
@ -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);
|
||||
|
||||
if (fatal) {
|
||||
udbg_printf("Fatal HW Error <0x%lx 0x%x>\n",
|
||||
*((unsigned long *)&ras_log_buf), status);
|
||||
printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
|
||||
*((unsigned long *)&ras_log_buf), status);
|
||||
|
||||
#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
|
||||
pr_emerg("Fatal hardware error reported by firmware");
|
||||
pr_emerg("Check RTAS error log for details");
|
||||
pr_emerg("Immediate power off");
|
||||
emergency_sync();
|
||||
kernel_power_off();
|
||||
} else {
|
||||
udbg_printf("Recoverable HW Error <0x%lx 0x%x>\n",
|
||||
*((unsigned long *)&ras_log_buf), status);
|
||||
printk(KERN_WARNING
|
||||
"Warning: Recoverable hardware error <0x%lx 0x%x>\n",
|
||||
*((unsigned long *)&ras_log_buf), status);
|
||||
pr_err("Recoverable hardware error reported by firmware");
|
||||
}
|
||||
|
||||
spin_unlock(&ras_log_buf_lock);
|
||||
|
|
|
@ -284,6 +284,7 @@ struct vio_dev {
|
|||
};
|
||||
|
||||
struct vio_driver {
|
||||
const char *name;
|
||||
struct list_head node;
|
||||
const struct vio_device_id *id_table;
|
||||
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); \
|
||||
} 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);
|
||||
|
||||
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,
|
||||
.probe = ds_probe,
|
||||
.remove = ds_remove,
|
||||
.driver = {
|
||||
.name = "ds",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
.name = "ds",
|
||||
};
|
||||
|
||||
static int __init ds_init(void)
|
||||
|
|
|
@ -119,13 +119,17 @@ static struct bus_type vio_bus_type = {
|
|||
.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.name = viodrv->name;
|
||||
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);
|
||||
|
||||
void vio_unregister_driver(struct vio_driver *viodrv)
|
||||
{
|
||||
|
|
|
@ -839,10 +839,7 @@ static struct vio_driver vdc_port_driver = {
|
|||
.id_table = vdc_port_match,
|
||||
.probe = vdc_port_probe,
|
||||
.remove = vdc_port_remove,
|
||||
.driver = {
|
||||
.name = "vdc_port",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
.name = "vdc_port",
|
||||
};
|
||||
|
||||
static int __init vdc_init(void)
|
||||
|
|
|
@ -1616,11 +1616,8 @@ static struct vio_driver ibmveth_driver = {
|
|||
.probe = ibmveth_probe,
|
||||
.remove = ibmveth_remove,
|
||||
.get_desired_dma = ibmveth_get_desired_dma,
|
||||
.driver = {
|
||||
.name = ibmveth_driver_name,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &ibmveth_pm_ops,
|
||||
}
|
||||
.name = ibmveth_driver_name,
|
||||
.pm = &ibmveth_pm_ops,
|
||||
};
|
||||
|
||||
static int __init ibmveth_module_init(void)
|
||||
|
|
|
@ -1259,10 +1259,7 @@ static struct vio_driver vnet_port_driver = {
|
|||
.id_table = vnet_port_match,
|
||||
.probe = vnet_port_probe,
|
||||
.remove = vnet_port_remove,
|
||||
.driver = {
|
||||
.name = "vnet_port",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
.name = "vnet_port",
|
||||
};
|
||||
|
||||
static int __init vnet_init(void)
|
||||
|
|
|
@ -4890,11 +4890,8 @@ static struct vio_driver ibmvfc_driver = {
|
|||
.probe = ibmvfc_probe,
|
||||
.remove = ibmvfc_remove,
|
||||
.get_desired_dma = ibmvfc_get_desired_dma,
|
||||
.driver = {
|
||||
.name = IBMVFC_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &ibmvfc_pm_ops,
|
||||
}
|
||||
.name = IBMVFC_NAME,
|
||||
.pm = &ibmvfc_pm_ops,
|
||||
};
|
||||
|
||||
static struct fc_function_template ibmvfc_transport_functions = {
|
||||
|
|
|
@ -2061,11 +2061,8 @@ static struct vio_driver ibmvscsi_driver = {
|
|||
.probe = ibmvscsi_probe,
|
||||
.remove = ibmvscsi_remove,
|
||||
.get_desired_dma = ibmvscsi_get_desired_dma,
|
||||
.driver = {
|
||||
.name = "ibmvscsi",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &ibmvscsi_pm_ops,
|
||||
}
|
||||
.name = "ibmvscsi",
|
||||
.pm = &ibmvscsi_pm_ops,
|
||||
};
|
||||
|
||||
static struct srp_function_template ibmvscsi_transport_functions = {
|
||||
|
|
|
@ -918,10 +918,7 @@ static struct vio_driver ibmvstgt_driver = {
|
|||
.id_table = ibmvstgt_device_table,
|
||||
.probe = ibmvstgt_probe,
|
||||
.remove = ibmvstgt_remove,
|
||||
.driver = {
|
||||
.name = "ibmvscsis",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
.name = "ibmvscsis",
|
||||
};
|
||||
|
||||
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 = {
|
||||
.id_table = hvc_driver_table,
|
||||
.probe = hvc_vio_probe,
|
||||
.remove = __devexit_p(hvc_vio_remove),
|
||||
.driver = {
|
||||
.name = hvc_driver_name,
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
.remove = hvc_vio_remove,
|
||||
.name = hvc_driver_name,
|
||||
};
|
||||
|
||||
static int __init hvc_vio_init(void)
|
||||
|
|
|
@ -879,10 +879,7 @@ static struct vio_driver hvcs_vio_driver = {
|
|||
.id_table = hvcs_driver_table,
|
||||
.probe = hvcs_probe,
|
||||
.remove = __devexit_p(hvcs_remove),
|
||||
.driver = {
|
||||
.name = hvcs_driver_name,
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
.name = hvcs_driver_name,
|
||||
};
|
||||
|
||||
/* Only called from hvcs_get_pi please */
|
||||
|
|
|
@ -58,9 +58,6 @@ struct device_node {
|
|||
struct kref kref;
|
||||
unsigned long _flags;
|
||||
void *data;
|
||||
#if defined(CONFIG_EEH)
|
||||
struct eeh_dev *edev;
|
||||
#endif
|
||||
#if defined(CONFIG_SPARC)
|
||||
char *path_component_name;
|
||||
unsigned int unique_id;
|
||||
|
@ -75,13 +72,6 @@ struct of_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
|
||||
extern struct device_node *of_node_get(struct device_node *node);
|
||||
extern void of_node_put(struct device_node *node);
|
||||
|
|
Loading…
Reference in a new issue