From d04c56f73c30a5e593202ecfcf25ed43d42363a2 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 4 Oct 2006 16:47:49 +1000 Subject: [POWERPC] Lazy interrupt disabling for 64-bit machines This implements a lazy strategy for disabling interrupts. This means that local_irq_disable() et al. just clear the 'interrupts are enabled' flag in the paca. If an interrupt comes along, the interrupt entry code notices that interrupts are supposed to be disabled, and clears the EE bit in SRR1, clears the 'interrupts are hard-enabled' flag in the paca, and returns. This means that interrupts only actually get disabled in the processor when an interrupt comes along. When interrupts are enabled by local_irq_enable() et al., the code sets the interrupts-enabled flag in the paca, and then checks whether interrupts got hard-disabled. If so, it also sets the EE bit in the MSR to hard-enable the interrupts. This has the potential to improve performance, and also makes it easier to make a kernel that can boot on iSeries and on other 64-bit machines, since this lazy-disable strategy is very similar to the soft-disable strategy that iSeries already uses. This version renames paca->proc_enabled to paca->soft_enabled, and changes a couple of soft-disables in the kexec code to hard-disables, which should fix the crash that Michael Ellerman saw. This doesn't yet use a reserved CR field for the soft_enabled and hard_enabled flags. This applies on top of Stephen Rothwell's patches to make it possible to build a combined iSeries/other kernel. Signed-off-by: Paul Mackerras --- include/asm-powerpc/hw_irq.h | 31 +++++++++++++++++++++---------- include/asm-powerpc/paca.h | 3 ++- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h index d40359204ab..c4a1ab608f6 100644 --- a/include/asm-powerpc/hw_irq.h +++ b/include/asm-powerpc/hw_irq.h @@ -7,16 +7,30 @@ #ifdef __KERNEL__ #include +#include #include #include extern void timer_interrupt(struct pt_regs *); -#ifdef CONFIG_PPC_ISERIES +#ifdef CONFIG_PPC64 +#include + +static inline unsigned long local_get_flags(void) +{ + return get_paca()->soft_enabled; +} + +static inline unsigned long local_irq_disable(void) +{ + unsigned long flag = get_paca()->soft_enabled; + get_paca()->soft_enabled = 0; + barrier(); + return flag; +} -extern unsigned long local_get_flags(void); -extern unsigned long local_irq_disable(void); extern void local_irq_restore(unsigned long); +extern void iseries_handle_interrupts(void); #define local_irq_enable() local_irq_restore(1) #define local_save_flags(flags) ((flags) = local_get_flags()) @@ -24,17 +38,14 @@ extern void local_irq_restore(unsigned long); #define irqs_disabled() (local_get_flags() == 0) +#define hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1) +#define hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1) + #else #if defined(CONFIG_BOOKE) #define SET_MSR_EE(x) mtmsr(x) #define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") -#elif defined(__powerpc64__) -#define SET_MSR_EE(x) __mtmsrd(x, 1) -#define local_irq_restore(flags) do { \ - __asm__ __volatile__("": : :"memory"); \ - __mtmsrd((flags), 1); \ -} while(0) #else #define SET_MSR_EE(x) mtmsr(x) #define local_irq_restore(flags) mtmsr(flags) @@ -81,7 +92,7 @@ static inline void local_irq_save_ptr(unsigned long *flags) #define local_irq_save(flags) local_irq_save_ptr(&flags) #define irqs_disabled() ((mfmsr() & MSR_EE) == 0) -#endif /* CONFIG_PPC_ISERIES */ +#endif /* CONFIG_PPC64 */ #define mask_irq(irq) \ ({ \ diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index 0a4e5c93e8e..0d3adc09c84 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -93,7 +93,8 @@ struct paca_struct { u64 stab_rr; /* stab/slb round-robin counter */ u64 saved_r1; /* r1 save for RTAS calls */ u64 saved_msr; /* MSR saved here by enter_rtas */ - u8 proc_enabled; /* irq soft-enable flag */ + u8 soft_enabled; /* irq soft-enable flag */ + u8 hard_enabled; /* set if irqs are enabled in MSR */ u8 io_sync; /* writel() needs spin_unlock sync */ /* Stuff for accurate time accounting */ -- cgit v1.2.3-70-g09d2 From 0f03a43b8f0fc221986a46654282ec6a1e8c6d45 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 3 Oct 2006 16:57:44 +1000 Subject: [POWERPC] Remove todc code from ARCH=powerpc Apparently we've copied the todc drivers, for various RTCs used in embedded machines from ARCH=ppc to ARCH=powerpc, despite the fact that it's never used in the latter. This patch removes it. If we ever need these drivers (which we probably shouldn't now the RTC class stuff is in), we can transfer them one by one from ARCH=ppc, removing from the hideous abomination which is the todc "infrastructure". Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 6 - arch/powerpc/sysdev/Makefile | 1 - arch/powerpc/sysdev/todc.c | 392 ---------------------------------- include/asm-powerpc/todc.h | 487 ------------------------------------------- 4 files changed, 886 deletions(-) delete mode 100644 arch/powerpc/sysdev/todc.c delete mode 100644 include/asm-powerpc/todc.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 8b691046557..7107d472413 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -594,12 +594,6 @@ config TAU_AVERAGE If in doubt, say N here. -config PPC_TODC - depends on EMBEDDED6xx - bool "Generic Time-of-day Clock (TODC) support" - ---help--- - This adds support for many TODC/RTC chips. - endmenu source arch/powerpc/platforms/embedded6xx/Kconfig diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 91f052d8cce..f15af0e82f1 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -10,7 +10,6 @@ obj-$(CONFIG_40x) += dcr.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o -obj-$(CONFIG_PPC_TODC) += todc.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ diff --git a/arch/powerpc/sysdev/todc.c b/arch/powerpc/sysdev/todc.c deleted file mode 100644 index 0a65980efb5..00000000000 --- a/arch/powerpc/sysdev/todc.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818 - * Real Time Clocks/Timekeepers. - * - * Author: Mark A. Greer - * - * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * Depending on the hardware on your board and your board design, the - * RTC/NVRAM may be accessed either directly (like normal memory) or via - * address/data registers. If your board uses the direct method, set - * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and - * 'nvram_as1' NULL. If your board uses address/data regs to access nvram, - * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the - * address of the upper byte (leave NULL if using mc146818), and set - * 'nvram_data' to the address of the 8-bit data register. - * - * Note: Even though the documentation for the various RTC chips say that it - * take up to a second before it starts updating once the 'R' bit is - * cleared, they always seem to update even though we bang on it many - * times a second. This is true, except for the Dallas Semi 1746/1747 - * (possibly others). Those chips seem to have a real problem whenever - * we set the 'R' bit before reading them, they basically stop counting. - * --MAG - */ - -/* - * 'todc_info' should be initialized in your *_setup.c file to - * point to a fully initialized 'todc_info_t' structure. - * This structure holds all the register offsets for your particular - * TODC/RTC chip. - * TODC_ALLOC()/TODC_INIT() will allocate and initialize this table for you. - */ - -#ifdef RTC_FREQ_SELECT -#undef RTC_FREQ_SELECT -#define RTC_FREQ_SELECT control_b /* Register A */ -#endif - -#ifdef RTC_CONTROL -#undef RTC_CONTROL -#define RTC_CONTROL control_a /* Register B */ -#endif - -#ifdef RTC_INTR_FLAGS -#undef RTC_INTR_FLAGS -#define RTC_INTR_FLAGS watchdog /* Register C */ -#endif - -#ifdef RTC_VALID -#undef RTC_VALID -#define RTC_VALID interrupts /* Register D */ -#endif - -/* Access routines when RTC accessed directly (like normal memory) */ -u_char -todc_direct_read_val(int addr) -{ - return readb((void __iomem *)(todc_info->nvram_data + addr)); -} - -void -todc_direct_write_val(int addr, unsigned char val) -{ - writeb(val, (void __iomem *)(todc_info->nvram_data + addr)); - return; -} - -/* Access routines for accessing m48txx type chips via addr/data regs */ -u_char -todc_m48txx_read_val(int addr) -{ - outb(addr, todc_info->nvram_as0); - outb(addr>>todc_info->as0_bits, todc_info->nvram_as1); - return inb(todc_info->nvram_data); -} - -void -todc_m48txx_write_val(int addr, unsigned char val) -{ - outb(addr, todc_info->nvram_as0); - outb(addr>>todc_info->as0_bits, todc_info->nvram_as1); - outb(val, todc_info->nvram_data); - return; -} - -/* Access routines for accessing mc146818 type chips via addr/data regs */ -u_char -todc_mc146818_read_val(int addr) -{ - outb_p(addr, todc_info->nvram_as0); - return inb_p(todc_info->nvram_data); -} - -void -todc_mc146818_write_val(int addr, unsigned char val) -{ - outb_p(addr, todc_info->nvram_as0); - outb_p(val, todc_info->nvram_data); -} - - -/* - * Routines to make RTC chips with NVRAM buried behind an addr/data pair - * have the NVRAM and clock regs appear at the same level. - * The NVRAM will appear to start at addr 0 and the clock regs will appear - * to start immediately after the NVRAM (actually, start at offset - * todc_info->nvram_size). - */ -static inline u_char -todc_read_val(int addr) -{ - u_char val; - - if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) { - if (addr < todc_info->nvram_size) { /* NVRAM */ - ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr); - val = ppc_md.rtc_read_val(todc_info->nvram_data_reg); - } else { /* Clock Reg */ - addr -= todc_info->nvram_size; - val = ppc_md.rtc_read_val(addr); - } - } else - val = ppc_md.rtc_read_val(addr); - - return val; -} - -static inline void -todc_write_val(int addr, u_char val) -{ - if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) { - if (addr < todc_info->nvram_size) { /* NVRAM */ - ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr); - ppc_md.rtc_write_val(todc_info->nvram_data_reg, val); - } else { /* Clock Reg */ - addr -= todc_info->nvram_size; - ppc_md.rtc_write_val(addr, val); - } - } else - ppc_md.rtc_write_val(addr, val); -} - -/* - * TODC routines - * - * There is some ugly stuff in that there are assumptions for the mc146818. - * - * Assumptions: - * - todc_info->control_a has the offset as mc146818 Register B reg - * - todc_info->control_b has the offset as mc146818 Register A reg - * - m48txx control reg's write enable or 'W' bit is same as - * mc146818 Register B 'SET' bit (i.e., 0x80) - * - * These assumptions were made to make the code simpler. - */ -long __init -todc_time_init(void) -{ - u_char cntl_b; - - if (!ppc_md.rtc_read_val) - ppc_md.rtc_read_val = ppc_md.nvram_read_val; - if (!ppc_md.rtc_write_val) - ppc_md.rtc_write_val = ppc_md.nvram_write_val; - - cntl_b = todc_read_val(todc_info->control_b); - - if (todc_info->rtc_type == TODC_TYPE_MC146818) { - if ((cntl_b & 0x70) != 0x20) { - printk(KERN_INFO "TODC real-time-clock was stopped." - " Now starting..."); - cntl_b &= ~0x70; - cntl_b |= 0x20; - } - - todc_write_val(todc_info->control_b, cntl_b); - } else if (todc_info->rtc_type == TODC_TYPE_DS17285) { - u_char mode; - - mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A); - /* Make sure countdown clear is not set */ - mode &= ~0x40; - /* Enable oscillator, extended register set */ - mode |= 0x30; - todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode); - - } else if (todc_info->rtc_type == TODC_TYPE_DS1501) { - u_char month; - - todc_info->enable_read = TODC_DS1501_CNTL_B_TE; - todc_info->enable_write = TODC_DS1501_CNTL_B_TE; - - month = todc_read_val(todc_info->month); - - if ((month & 0x80) == 0x80) { - printk(KERN_INFO "TODC %s %s\n", - "real-time-clock was stopped.", - "Now starting..."); - month &= ~0x80; - todc_write_val(todc_info->month, month); - } - - cntl_b &= ~TODC_DS1501_CNTL_B_TE; - todc_write_val(todc_info->control_b, cntl_b); - } else { /* must be a m48txx type */ - u_char cntl_a; - - todc_info->enable_read = TODC_MK48TXX_CNTL_A_R; - todc_info->enable_write = TODC_MK48TXX_CNTL_A_W; - - cntl_a = todc_read_val(todc_info->control_a); - - /* Check & clear STOP bit in control B register */ - if (cntl_b & TODC_MK48TXX_DAY_CB) { - printk(KERN_INFO "TODC %s %s\n", - "real-time-clock was stopped.", - "Now starting..."); - - cntl_a |= todc_info->enable_write; - cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */ - - todc_write_val(todc_info->control_a, cntl_a); - todc_write_val(todc_info->control_b, cntl_b); - } - - /* Make sure READ & WRITE bits are cleared. */ - cntl_a &= ~(todc_info->enable_write | todc_info->enable_read); - todc_write_val(todc_info->control_a, cntl_a); - } - - return 0; -} - -/* - * There is some ugly stuff in that there are assumptions that for a mc146818, - * the todc_info->control_a has the offset of the mc146818 Register B reg and - * that the register'ss 'SET' bit is the same as the m48txx's write enable - * bit in the control register of the m48txx (i.e., 0x80). - * - * It was done to make the code look simpler. - */ -void -todc_get_rtc_time(struct rtc_time *tm) -{ - uint year = 0, mon = 0, mday = 0, hour = 0, min = 0, sec = 0; - uint limit, i; - u_char save_control, uip = 0; - extern void GregorianDay(struct rtc_time *); - - spin_lock(&rtc_lock); - save_control = todc_read_val(todc_info->control_a); - - if (todc_info->rtc_type != TODC_TYPE_MC146818) { - limit = 1; - - switch (todc_info->rtc_type) { - case TODC_TYPE_DS1553: - case TODC_TYPE_DS1557: - case TODC_TYPE_DS1743: - case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ - case TODC_TYPE_DS1747: - case TODC_TYPE_DS17285: - break; - default: - todc_write_val(todc_info->control_a, - (save_control | todc_info->enable_read)); - } - } else - limit = 100000000; - - for (i=0; irtc_type == TODC_TYPE_MC146818) - uip = todc_read_val(todc_info->RTC_FREQ_SELECT); - - sec = todc_read_val(todc_info->seconds) & 0x7f; - min = todc_read_val(todc_info->minutes) & 0x7f; - hour = todc_read_val(todc_info->hours) & 0x3f; - mday = todc_read_val(todc_info->day_of_month) & 0x3f; - mon = todc_read_val(todc_info->month) & 0x1f; - year = todc_read_val(todc_info->year) & 0xff; - - if (todc_info->rtc_type == TODC_TYPE_MC146818) { - uip |= todc_read_val(todc_info->RTC_FREQ_SELECT); - if ((uip & RTC_UIP) == 0) - break; - } - } - - if (todc_info->rtc_type != TODC_TYPE_MC146818) { - switch (todc_info->rtc_type) { - case TODC_TYPE_DS1553: - case TODC_TYPE_DS1557: - case TODC_TYPE_DS1743: - case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ - case TODC_TYPE_DS1747: - case TODC_TYPE_DS17285: - break; - default: - save_control &= ~(todc_info->enable_read); - todc_write_val(todc_info->control_a, save_control); - } - } - spin_unlock(&rtc_lock); - - if ((todc_info->rtc_type != TODC_TYPE_MC146818) - || ((save_control & RTC_DM_BINARY) == 0) - || RTC_ALWAYS_BCD) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(mday); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - - if ((year + 1900) < 1970) { - year += 100; - } - - tm->tm_sec = sec; - tm->tm_min = min; - tm->tm_hour = hour; - tm->tm_mday = mday; - tm->tm_mon = mon; - tm->tm_year = year; - - GregorianDay(tm); -} - -int -todc_set_rtc_time(struct rtc_time *tm) -{ - u_char save_control, save_freq_select = 0; - - spin_lock(&rtc_lock); - save_control = todc_read_val(todc_info->control_a); - - /* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */ - todc_write_val(todc_info->control_a, - (save_control | todc_info->enable_write)); - save_control &= ~(todc_info->enable_write); /* in case it was set */ - - if (todc_info->rtc_type == TODC_TYPE_MC146818) { - save_freq_select = todc_read_val(todc_info->RTC_FREQ_SELECT); - todc_write_val(todc_info->RTC_FREQ_SELECT, - save_freq_select | RTC_DIV_RESET2); - } - - if ((todc_info->rtc_type != TODC_TYPE_MC146818) - || ((save_control & RTC_DM_BINARY) == 0) - || RTC_ALWAYS_BCD) { - BIN_TO_BCD(tm->tm_sec); - BIN_TO_BCD(tm->tm_min); - BIN_TO_BCD(tm->tm_hour); - BIN_TO_BCD(tm->tm_mon); - BIN_TO_BCD(tm->tm_mday); - BIN_TO_BCD(tm->tm_year); - } - - todc_write_val(todc_info->seconds, tm->tm_sec); - todc_write_val(todc_info->minutes, tm->tm_min); - todc_write_val(todc_info->hours, tm->tm_hour); - todc_write_val(todc_info->month, tm->tm_mon); - todc_write_val(todc_info->day_of_month, tm->tm_mday); - todc_write_val(todc_info->year, tm->tm_year); - - todc_write_val(todc_info->control_a, save_control); - - if (todc_info->rtc_type == TODC_TYPE_MC146818) - todc_write_val(todc_info->RTC_FREQ_SELECT, save_freq_select); - - spin_unlock(&rtc_lock); - return 0; -} diff --git a/include/asm-powerpc/todc.h b/include/asm-powerpc/todc.h deleted file mode 100644 index 60a8c39b8c1..00000000000 --- a/include/asm-powerpc/todc.h +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Definitions for the M48Txx and mc146818 series of Time of day/Real Time - * Clock chips. - * - * Author: Mark A. Greer - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -/* - * Support for the M48T37/M48T59/.../mc146818 Real Time Clock chips. - * Purpose is to make one generic file that handles all of these chips instead - * of every platform implementing the same code over & over again. - */ - -#ifndef __PPC_KERNEL_TODC_H -#define __PPC_KERNEL_TODC_H - -typedef struct { - uint rtc_type; /* your particular chip */ - - /* - * Following are the addresses of the AS0, AS1, and DATA registers - * of these chips. Note that these are board-specific. - */ - unsigned int nvram_as0; - unsigned int nvram_as1; - unsigned int nvram_data; - - /* - * Define bits to stop external set of regs from changing so - * the chip can be read/written reliably. - */ - unsigned char enable_read; - unsigned char enable_write; - - /* - * Following is the number of AS0 address bits. This is normally - * 8 but some bad hardware routes address lines incorrectly. - */ - int as0_bits; - - int nvram_size; /* Size of NVRAM on chip */ - int sw_flags; /* Software control flags */ - - /* Following are the register offsets for the particular chip */ - int year; - int month; - int day_of_month; - int day_of_week; - int hours; - int minutes; - int seconds; - int control_b; - int control_a; - int watchdog; - int interrupts; - int alarm_date; - int alarm_hour; - int alarm_minutes; - int alarm_seconds; - int century; - int flags; - - /* - * Some RTC chips have their NVRAM buried behind a addr/data pair of - * regs on the first level/clock registers. The following fields - * are the addresses for those addr/data regs. - */ - int nvram_addr_reg; - int nvram_data_reg; -} todc_info_t; - -/* - * Define the types of TODC/RTC variants that are supported in - * arch/ppc/kernel/todc_time.c - * Make a new one of these for any chip somehow differs from what's already - * defined. That way, if you ever need to put in code to touch those - * bits/registers in todc_time.c, you can put it inside an - * 'if (todc_info->rtc_type == TODC_TYPE_XXX)' so you won't break - * anyone else. - */ -#define TODC_TYPE_MK48T35 1 -#define TODC_TYPE_MK48T37 2 -#define TODC_TYPE_MK48T59 3 -#define TODC_TYPE_DS1693 4 /* Dallas DS1693 RTC */ -#define TODC_TYPE_DS1743 5 /* Dallas DS1743 RTC */ -#define TODC_TYPE_DS1746 6 /* Dallas DS1746 RTC */ -#define TODC_TYPE_DS1747 7 /* Dallas DS1747 RTC */ -#define TODC_TYPE_DS1501 8 /* Dallas DS1501 RTC */ -#define TODC_TYPE_DS1643 9 /* Dallas DS1643 RTC */ -#define TODC_TYPE_PC97307 10 /* PC97307 internal RTC */ -#define TODC_TYPE_DS1557 11 /* Dallas DS1557 RTC */ -#define TODC_TYPE_DS17285 12 /* Dallas DS17285 RTC */ -#define TODC_TYPE_DS1553 13 /* Dallas DS1553 RTC */ -#define TODC_TYPE_MC146818 100 /* Leave room for m48txx's */ - -/* - * Bit to clear/set to enable reads/writes to the chip - */ -#define TODC_MK48TXX_CNTL_A_R 0x40 -#define TODC_MK48TXX_CNTL_A_W 0x80 -#define TODC_MK48TXX_DAY_CB 0x80 - -#define TODC_DS1501_CNTL_B_TE 0x80 - -/* - * Define flag bits used by todc routines. - */ -#define TODC_FLAG_2_LEVEL_NVRAM 0x00000001 - -/* - * Define the values for the various RTC's that should to into the todc_info - * table. - * Note: The XXX_NVRAM_SIZE, XXX_NVRAM_ADDR_REG, and XXX_NVRAM_DATA_REG only - * matter if XXX_SW_FLAGS has TODC_FLAG_2_LEVEL_NVRAM set. - */ -#define TODC_TYPE_MK48T35_NVRAM_SIZE 0x7ff8 -#define TODC_TYPE_MK48T35_SW_FLAGS 0 -#define TODC_TYPE_MK48T35_YEAR 0x7fff -#define TODC_TYPE_MK48T35_MONTH 0x7ffe -#define TODC_TYPE_MK48T35_DOM 0x7ffd /* Day of Month */ -#define TODC_TYPE_MK48T35_DOW 0x7ffc /* Day of Week */ -#define TODC_TYPE_MK48T35_HOURS 0x7ffb -#define TODC_TYPE_MK48T35_MINUTES 0x7ffa -#define TODC_TYPE_MK48T35_SECONDS 0x7ff9 -#define TODC_TYPE_MK48T35_CNTL_B 0x7ff9 -#define TODC_TYPE_MK48T35_CNTL_A 0x7ff8 -#define TODC_TYPE_MK48T35_WATCHDOG 0x0000 -#define TODC_TYPE_MK48T35_INTERRUPTS 0x0000 -#define TODC_TYPE_MK48T35_ALARM_DATE 0x0000 -#define TODC_TYPE_MK48T35_ALARM_HOUR 0x0000 -#define TODC_TYPE_MK48T35_ALARM_MINUTES 0x0000 -#define TODC_TYPE_MK48T35_ALARM_SECONDS 0x0000 -#define TODC_TYPE_MK48T35_CENTURY 0x0000 -#define TODC_TYPE_MK48T35_FLAGS 0x0000 -#define TODC_TYPE_MK48T35_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MK48T35_NVRAM_DATA_REG 0 - -#define TODC_TYPE_MK48T37_NVRAM_SIZE 0x7ff0 -#define TODC_TYPE_MK48T37_SW_FLAGS 0 -#define TODC_TYPE_MK48T37_YEAR 0x7fff -#define TODC_TYPE_MK48T37_MONTH 0x7ffe -#define TODC_TYPE_MK48T37_DOM 0x7ffd /* Day of Month */ -#define TODC_TYPE_MK48T37_DOW 0x7ffc /* Day of Week */ -#define TODC_TYPE_MK48T37_HOURS 0x7ffb -#define TODC_TYPE_MK48T37_MINUTES 0x7ffa -#define TODC_TYPE_MK48T37_SECONDS 0x7ff9 -#define TODC_TYPE_MK48T37_CNTL_B 0x7ff9 -#define TODC_TYPE_MK48T37_CNTL_A 0x7ff8 -#define TODC_TYPE_MK48T37_WATCHDOG 0x7ff7 -#define TODC_TYPE_MK48T37_INTERRUPTS 0x7ff6 -#define TODC_TYPE_MK48T37_ALARM_DATE 0x7ff5 -#define TODC_TYPE_MK48T37_ALARM_HOUR 0x7ff4 -#define TODC_TYPE_MK48T37_ALARM_MINUTES 0x7ff3 -#define TODC_TYPE_MK48T37_ALARM_SECONDS 0x7ff2 -#define TODC_TYPE_MK48T37_CENTURY 0x7ff1 -#define TODC_TYPE_MK48T37_FLAGS 0x7ff0 -#define TODC_TYPE_MK48T37_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MK48T37_NVRAM_DATA_REG 0 - -#define TODC_TYPE_MK48T59_NVRAM_SIZE 0x1ff0 -#define TODC_TYPE_MK48T59_SW_FLAGS 0 -#define TODC_TYPE_MK48T59_YEAR 0x1fff -#define TODC_TYPE_MK48T59_MONTH 0x1ffe -#define TODC_TYPE_MK48T59_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_MK48T59_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_MK48T59_HOURS 0x1ffb -#define TODC_TYPE_MK48T59_MINUTES 0x1ffa -#define TODC_TYPE_MK48T59_SECONDS 0x1ff9 -#define TODC_TYPE_MK48T59_CNTL_B 0x1ff9 -#define TODC_TYPE_MK48T59_CNTL_A 0x1ff8 -#define TODC_TYPE_MK48T59_WATCHDOG 0x1fff -#define TODC_TYPE_MK48T59_INTERRUPTS 0x1fff -#define TODC_TYPE_MK48T59_ALARM_DATE 0x1fff -#define TODC_TYPE_MK48T59_ALARM_HOUR 0x1fff -#define TODC_TYPE_MK48T59_ALARM_MINUTES 0x1fff -#define TODC_TYPE_MK48T59_ALARM_SECONDS 0x1fff -#define TODC_TYPE_MK48T59_CENTURY 0x1fff -#define TODC_TYPE_MK48T59_FLAGS 0x1fff -#define TODC_TYPE_MK48T59_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MK48T59_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1501_NVRAM_SIZE 0x100 -#define TODC_TYPE_DS1501_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM -#define TODC_TYPE_DS1501_YEAR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x06) -#define TODC_TYPE_DS1501_MONTH (TODC_TYPE_DS1501_NVRAM_SIZE + 0x05) -#define TODC_TYPE_DS1501_DOM (TODC_TYPE_DS1501_NVRAM_SIZE + 0x04) -#define TODC_TYPE_DS1501_DOW (TODC_TYPE_DS1501_NVRAM_SIZE + 0x03) -#define TODC_TYPE_DS1501_HOURS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x02) -#define TODC_TYPE_DS1501_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x01) -#define TODC_TYPE_DS1501_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x00) -#define TODC_TYPE_DS1501_CNTL_B (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f) -#define TODC_TYPE_DS1501_CNTL_A (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f) -#define TODC_TYPE_DS1501_WATCHDOG (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) -#define TODC_TYPE_DS1501_INTERRUPTS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) -#define TODC_TYPE_DS1501_ALARM_DATE (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0b) -#define TODC_TYPE_DS1501_ALARM_HOUR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0a) -#define TODC_TYPE_DS1501_ALARM_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x09) -#define TODC_TYPE_DS1501_ALARM_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x08) -#define TODC_TYPE_DS1501_CENTURY (TODC_TYPE_DS1501_NVRAM_SIZE + 0x07) -#define TODC_TYPE_DS1501_FLAGS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) -#define TODC_TYPE_DS1501_NVRAM_ADDR_REG 0x10 -#define TODC_TYPE_DS1501_NVRAM_DATA_REG 0x13 - -#define TODC_TYPE_DS1553_NVRAM_SIZE 0x1ff0 -#define TODC_TYPE_DS1553_SW_FLAGS 0 -#define TODC_TYPE_DS1553_YEAR 0x1fff -#define TODC_TYPE_DS1553_MONTH 0x1ffe -#define TODC_TYPE_DS1553_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_DS1553_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_DS1553_HOURS 0x1ffb -#define TODC_TYPE_DS1553_MINUTES 0x1ffa -#define TODC_TYPE_DS1553_SECONDS 0x1ff9 -#define TODC_TYPE_DS1553_CNTL_B 0x1ff9 -#define TODC_TYPE_DS1553_CNTL_A 0x1ff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1553_WATCHDOG 0x1ff7 -#define TODC_TYPE_DS1553_INTERRUPTS 0x1ff6 -#define TODC_TYPE_DS1553_ALARM_DATE 0x1ff5 -#define TODC_TYPE_DS1553_ALARM_HOUR 0x1ff4 -#define TODC_TYPE_DS1553_ALARM_MINUTES 0x1ff3 -#define TODC_TYPE_DS1553_ALARM_SECONDS 0x1ff2 -#define TODC_TYPE_DS1553_CENTURY 0x1ff8 -#define TODC_TYPE_DS1553_FLAGS 0x1ff0 -#define TODC_TYPE_DS1553_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1553_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1557_NVRAM_SIZE 0x7fff0 -#define TODC_TYPE_DS1557_SW_FLAGS 0 -#define TODC_TYPE_DS1557_YEAR 0x7ffff -#define TODC_TYPE_DS1557_MONTH 0x7fffe -#define TODC_TYPE_DS1557_DOM 0x7fffd /* Day of Month */ -#define TODC_TYPE_DS1557_DOW 0x7fffc /* Day of Week */ -#define TODC_TYPE_DS1557_HOURS 0x7fffb -#define TODC_TYPE_DS1557_MINUTES 0x7fffa -#define TODC_TYPE_DS1557_SECONDS 0x7fff9 -#define TODC_TYPE_DS1557_CNTL_B 0x7fff9 -#define TODC_TYPE_DS1557_CNTL_A 0x7fff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1557_WATCHDOG 0x7fff7 -#define TODC_TYPE_DS1557_INTERRUPTS 0x7fff6 -#define TODC_TYPE_DS1557_ALARM_DATE 0x7fff5 -#define TODC_TYPE_DS1557_ALARM_HOUR 0x7fff4 -#define TODC_TYPE_DS1557_ALARM_MINUTES 0x7fff3 -#define TODC_TYPE_DS1557_ALARM_SECONDS 0x7fff2 -#define TODC_TYPE_DS1557_CENTURY 0x7fff8 -#define TODC_TYPE_DS1557_FLAGS 0x7fff0 -#define TODC_TYPE_DS1557_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1557_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1643_NVRAM_SIZE 0x1ff8 -#define TODC_TYPE_DS1643_SW_FLAGS 0 -#define TODC_TYPE_DS1643_YEAR 0x1fff -#define TODC_TYPE_DS1643_MONTH 0x1ffe -#define TODC_TYPE_DS1643_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_DS1643_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_DS1643_HOURS 0x1ffb -#define TODC_TYPE_DS1643_MINUTES 0x1ffa -#define TODC_TYPE_DS1643_SECONDS 0x1ff9 -#define TODC_TYPE_DS1643_CNTL_B 0x1ff9 -#define TODC_TYPE_DS1643_CNTL_A 0x1ff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1643_WATCHDOG 0x1fff -#define TODC_TYPE_DS1643_INTERRUPTS 0x1fff -#define TODC_TYPE_DS1643_ALARM_DATE 0x1fff -#define TODC_TYPE_DS1643_ALARM_HOUR 0x1fff -#define TODC_TYPE_DS1643_ALARM_MINUTES 0x1fff -#define TODC_TYPE_DS1643_ALARM_SECONDS 0x1fff -#define TODC_TYPE_DS1643_CENTURY 0x1ff8 -#define TODC_TYPE_DS1643_FLAGS 0x1fff -#define TODC_TYPE_DS1643_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1643_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1693_NVRAM_SIZE 0 /* Not handled yet */ -#define TODC_TYPE_DS1693_SW_FLAGS 0 -#define TODC_TYPE_DS1693_YEAR 0x09 -#define TODC_TYPE_DS1693_MONTH 0x08 -#define TODC_TYPE_DS1693_DOM 0x07 /* Day of Month */ -#define TODC_TYPE_DS1693_DOW 0x06 /* Day of Week */ -#define TODC_TYPE_DS1693_HOURS 0x04 -#define TODC_TYPE_DS1693_MINUTES 0x02 -#define TODC_TYPE_DS1693_SECONDS 0x00 -#define TODC_TYPE_DS1693_CNTL_B 0x0b -#define TODC_TYPE_DS1693_CNTL_A 0x0a -#define TODC_TYPE_DS1693_WATCHDOG 0xff -#define TODC_TYPE_DS1693_INTERRUPTS 0xff -#define TODC_TYPE_DS1693_ALARM_DATE 0x49 -#define TODC_TYPE_DS1693_ALARM_HOUR 0x05 -#define TODC_TYPE_DS1693_ALARM_MINUTES 0x03 -#define TODC_TYPE_DS1693_ALARM_SECONDS 0x01 -#define TODC_TYPE_DS1693_CENTURY 0x48 -#define TODC_TYPE_DS1693_FLAGS 0xff -#define TODC_TYPE_DS1693_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1693_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1743_NVRAM_SIZE 0x1ff8 -#define TODC_TYPE_DS1743_SW_FLAGS 0 -#define TODC_TYPE_DS1743_YEAR 0x1fff -#define TODC_TYPE_DS1743_MONTH 0x1ffe -#define TODC_TYPE_DS1743_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_DS1743_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_DS1743_HOURS 0x1ffb -#define TODC_TYPE_DS1743_MINUTES 0x1ffa -#define TODC_TYPE_DS1743_SECONDS 0x1ff9 -#define TODC_TYPE_DS1743_CNTL_B 0x1ff9 -#define TODC_TYPE_DS1743_CNTL_A 0x1ff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1743_WATCHDOG 0x1fff -#define TODC_TYPE_DS1743_INTERRUPTS 0x1fff -#define TODC_TYPE_DS1743_ALARM_DATE 0x1fff -#define TODC_TYPE_DS1743_ALARM_HOUR 0x1fff -#define TODC_TYPE_DS1743_ALARM_MINUTES 0x1fff -#define TODC_TYPE_DS1743_ALARM_SECONDS 0x1fff -#define TODC_TYPE_DS1743_CENTURY 0x1ff8 -#define TODC_TYPE_DS1743_FLAGS 0x1fff -#define TODC_TYPE_DS1743_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1743_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1746_NVRAM_SIZE 0x1fff8 -#define TODC_TYPE_DS1746_SW_FLAGS 0 -#define TODC_TYPE_DS1746_YEAR 0x1ffff -#define TODC_TYPE_DS1746_MONTH 0x1fffe -#define TODC_TYPE_DS1746_DOM 0x1fffd /* Day of Month */ -#define TODC_TYPE_DS1746_DOW 0x1fffc /* Day of Week */ -#define TODC_TYPE_DS1746_HOURS 0x1fffb -#define TODC_TYPE_DS1746_MINUTES 0x1fffa -#define TODC_TYPE_DS1746_SECONDS 0x1fff9 -#define TODC_TYPE_DS1746_CNTL_B 0x1fff9 -#define TODC_TYPE_DS1746_CNTL_A 0x1fff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1746_WATCHDOG 0x00000 -#define TODC_TYPE_DS1746_INTERRUPTS 0x00000 -#define TODC_TYPE_DS1746_ALARM_DATE 0x00000 -#define TODC_TYPE_DS1746_ALARM_HOUR 0x00000 -#define TODC_TYPE_DS1746_ALARM_MINUTES 0x00000 -#define TODC_TYPE_DS1746_ALARM_SECONDS 0x00000 -#define TODC_TYPE_DS1746_CENTURY 0x00000 -#define TODC_TYPE_DS1746_FLAGS 0x00000 -#define TODC_TYPE_DS1746_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1746_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1747_NVRAM_SIZE 0x7fff8 -#define TODC_TYPE_DS1747_SW_FLAGS 0 -#define TODC_TYPE_DS1747_YEAR 0x7ffff -#define TODC_TYPE_DS1747_MONTH 0x7fffe -#define TODC_TYPE_DS1747_DOM 0x7fffd /* Day of Month */ -#define TODC_TYPE_DS1747_DOW 0x7fffc /* Day of Week */ -#define TODC_TYPE_DS1747_HOURS 0x7fffb -#define TODC_TYPE_DS1747_MINUTES 0x7fffa -#define TODC_TYPE_DS1747_SECONDS 0x7fff9 -#define TODC_TYPE_DS1747_CNTL_B 0x7fff9 -#define TODC_TYPE_DS1747_CNTL_A 0x7fff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1747_WATCHDOG 0x00000 -#define TODC_TYPE_DS1747_INTERRUPTS 0x00000 -#define TODC_TYPE_DS1747_ALARM_DATE 0x00000 -#define TODC_TYPE_DS1747_ALARM_HOUR 0x00000 -#define TODC_TYPE_DS1747_ALARM_MINUTES 0x00000 -#define TODC_TYPE_DS1747_ALARM_SECONDS 0x00000 -#define TODC_TYPE_DS1747_CENTURY 0x00000 -#define TODC_TYPE_DS1747_FLAGS 0x00000 -#define TODC_TYPE_DS1747_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1747_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS17285_NVRAM_SIZE (0x1000-0x80) /* 4Kx8 NVRAM (minus RTC regs) */ -#define TODC_TYPE_DS17285_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM -#define TODC_TYPE_DS17285_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x00) -#define TODC_TYPE_DS17285_ALARM_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x01) -#define TODC_TYPE_DS17285_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x02) -#define TODC_TYPE_DS17285_ALARM_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x03) -#define TODC_TYPE_DS17285_HOURS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x04) -#define TODC_TYPE_DS17285_ALARM_HOUR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x05) -#define TODC_TYPE_DS17285_DOW (TODC_TYPE_DS17285_NVRAM_SIZE + 0x06) -#define TODC_TYPE_DS17285_DOM (TODC_TYPE_DS17285_NVRAM_SIZE + 0x07) -#define TODC_TYPE_DS17285_MONTH (TODC_TYPE_DS17285_NVRAM_SIZE + 0x08) -#define TODC_TYPE_DS17285_YEAR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x09) -#define TODC_TYPE_DS17285_CNTL_A (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0A) -#define TODC_TYPE_DS17285_CNTL_B (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0B) -#define TODC_TYPE_DS17285_CNTL_C (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0C) -#define TODC_TYPE_DS17285_CNTL_D (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0D) -#define TODC_TYPE_DS17285_WATCHDOG 0 -#define TODC_TYPE_DS17285_INTERRUPTS 0 -#define TODC_TYPE_DS17285_ALARM_DATE 0 -#define TODC_TYPE_DS17285_CENTURY 0 -#define TODC_TYPE_DS17285_FLAGS 0 -#define TODC_TYPE_DS17285_NVRAM_ADDR_REG 0x50 -#define TODC_TYPE_DS17285_NVRAM_DATA_REG 0x53 - -#define TODC_TYPE_MC146818_NVRAM_SIZE 0 /* XXXX */ -#define TODC_TYPE_MC146818_SW_FLAGS 0 -#define TODC_TYPE_MC146818_YEAR 0x09 -#define TODC_TYPE_MC146818_MONTH 0x08 -#define TODC_TYPE_MC146818_DOM 0x07 /* Day of Month */ -#define TODC_TYPE_MC146818_DOW 0x06 /* Day of Week */ -#define TODC_TYPE_MC146818_HOURS 0x04 -#define TODC_TYPE_MC146818_MINUTES 0x02 -#define TODC_TYPE_MC146818_SECONDS 0x00 -#define TODC_TYPE_MC146818_CNTL_B 0x0a -#define TODC_TYPE_MC146818_CNTL_A 0x0b /* control_a R/W regs */ -#define TODC_TYPE_MC146818_WATCHDOG 0 -#define TODC_TYPE_MC146818_INTERRUPTS 0x0c -#define TODC_TYPE_MC146818_ALARM_DATE 0xff -#define TODC_TYPE_MC146818_ALARM_HOUR 0x05 -#define TODC_TYPE_MC146818_ALARM_MINUTES 0x03 -#define TODC_TYPE_MC146818_ALARM_SECONDS 0x01 -#define TODC_TYPE_MC146818_CENTURY 0xff -#define TODC_TYPE_MC146818_FLAGS 0xff -#define TODC_TYPE_MC146818_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MC146818_NVRAM_DATA_REG 0 - -#define TODC_TYPE_PC97307_NVRAM_SIZE 0 /* No NVRAM? */ -#define TODC_TYPE_PC97307_SW_FLAGS 0 -#define TODC_TYPE_PC97307_YEAR 0x09 -#define TODC_TYPE_PC97307_MONTH 0x08 -#define TODC_TYPE_PC97307_DOM 0x07 /* Day of Month */ -#define TODC_TYPE_PC97307_DOW 0x06 /* Day of Week */ -#define TODC_TYPE_PC97307_HOURS 0x04 -#define TODC_TYPE_PC97307_MINUTES 0x02 -#define TODC_TYPE_PC97307_SECONDS 0x00 -#define TODC_TYPE_PC97307_CNTL_B 0x0a -#define TODC_TYPE_PC97307_CNTL_A 0x0b /* control_a R/W regs */ -#define TODC_TYPE_PC97307_WATCHDOG 0x0c -#define TODC_TYPE_PC97307_INTERRUPTS 0x0d -#define TODC_TYPE_PC97307_ALARM_DATE 0xff -#define TODC_TYPE_PC97307_ALARM_HOUR 0x05 -#define TODC_TYPE_PC97307_ALARM_MINUTES 0x03 -#define TODC_TYPE_PC97307_ALARM_SECONDS 0x01 -#define TODC_TYPE_PC97307_CENTURY 0xff -#define TODC_TYPE_PC97307_FLAGS 0xff -#define TODC_TYPE_PC97307_NVRAM_ADDR_REG 0 -#define TODC_TYPE_PC97307_NVRAM_DATA_REG 0 - -/* - * Define macros to allocate and init the todc_info_t table that will - * be used by the todc_time.c routines. - */ -#define TODC_ALLOC() \ - static todc_info_t todc_info_alloc; \ - todc_info_t *todc_info = &todc_info_alloc; - -#define TODC_INIT(clock_type, as0, as1, data, bits) { \ - todc_info->rtc_type = clock_type; \ - \ - todc_info->nvram_as0 = (unsigned int)(as0); \ - todc_info->nvram_as1 = (unsigned int)(as1); \ - todc_info->nvram_data = (unsigned int)(data); \ - \ - todc_info->as0_bits = (bits); \ - \ - todc_info->nvram_size = clock_type ##_NVRAM_SIZE; \ - todc_info->sw_flags = clock_type ##_SW_FLAGS; \ - \ - todc_info->year = clock_type ##_YEAR; \ - todc_info->month = clock_type ##_MONTH; \ - todc_info->day_of_month = clock_type ##_DOM; \ - todc_info->day_of_week = clock_type ##_DOW; \ - todc_info->hours = clock_type ##_HOURS; \ - todc_info->minutes = clock_type ##_MINUTES; \ - todc_info->seconds = clock_type ##_SECONDS; \ - todc_info->control_b = clock_type ##_CNTL_B; \ - todc_info->control_a = clock_type ##_CNTL_A; \ - todc_info->watchdog = clock_type ##_WATCHDOG; \ - todc_info->interrupts = clock_type ##_INTERRUPTS; \ - todc_info->alarm_date = clock_type ##_ALARM_DATE; \ - todc_info->alarm_hour = clock_type ##_ALARM_HOUR; \ - todc_info->alarm_minutes = clock_type ##_ALARM_MINUTES; \ - todc_info->alarm_seconds = clock_type ##_ALARM_SECONDS; \ - todc_info->century = clock_type ##_CENTURY; \ - todc_info->flags = clock_type ##_FLAGS; \ - \ - todc_info->nvram_addr_reg = clock_type ##_NVRAM_ADDR_REG; \ - todc_info->nvram_data_reg = clock_type ##_NVRAM_DATA_REG; \ -} - -extern todc_info_t *todc_info; - -unsigned char todc_direct_read_val(int addr); -void todc_direct_write_val(int addr, unsigned char val); -unsigned char todc_m48txx_read_val(int addr); -void todc_m48txx_write_val(int addr, unsigned char val); -unsigned char todc_mc146818_read_val(int addr); -void todc_mc146818_write_val(int addr, unsigned char val); - -long todc_time_init(void); -void todc_get_rtc_time(struct rtc_time *); -int todc_set_rtc_time(struct rtc_time *); -void todc_calibrate_decr(void); - -#endif /* __PPC_KERNEL_TODC_H */ -- cgit v1.2.3-70-g09d2 From 035223fb28791f0eb0d5719727355d3f6817d228 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 5 Oct 2006 11:35:10 -0700 Subject: [POWERPC] Make pSeries_lpar_hpte_insert static Change the powerpc hpte_insert routines now called through ppc_md to static scope. Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_native_64.c | 2 +- arch/powerpc/platforms/pseries/lpar.c | 4 ++-- include/asm-powerpc/mmu.h | 15 --------------- 3 files changed, 3 insertions(+), 18 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index c90f124f3c7..6f1016acdbf 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -123,7 +123,7 @@ static inline void native_unlock_hpte(hpte_t *hptep) clear_bit(HPTE_LOCK_BIT, word); } -long native_hpte_insert(unsigned long hpte_group, unsigned long va, +static long native_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) { diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 1820a0b0a8c..721436db3ef 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -282,7 +282,7 @@ void vpa_init(int cpu) } } -long pSeries_lpar_hpte_insert(unsigned long hpte_group, +static long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) @@ -506,7 +506,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie * lock. */ -void pSeries_lpar_flush_hash_range(unsigned long number, int local) +static void pSeries_lpar_flush_hash_range(unsigned long number, int local) { int i; unsigned long flags = 0; diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index c3fc7a28e3c..41c8c9c5a25 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h @@ -248,21 +248,6 @@ extern void hpte_init_native(void); extern void hpte_init_lpar(void); extern void hpte_init_iSeries(void); -extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, - unsigned long rflags, - unsigned long vflags, int psize); - -extern long native_hpte_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, - unsigned long rflags, - unsigned long vflags, int psize); - -extern long iSeries_hpte_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, - unsigned long rflags, - unsigned long vflags, int psize); - extern void stabs_alloc(void); extern void slb_initialize(void); extern void slb_flush_and_rebolt(void); -- cgit v1.2.3-70-g09d2 From 24f43b33f74c8e8c8aabc40b728eaf9137802942 Mon Sep 17 00:00:00 2001 From: Masato Noguchi Date: Tue, 24 Oct 2006 18:31:14 +0200 Subject: [POWERPC] spufs: wrap mfc sdr access SPRN_SDR1 and the SPE's MFC SDR are hypervisor resources and are not accessible from a logical partition. This change adds an access wrapper. When running on bare H/W, the spufs needs to only set the SPE's MFC SDR to the value of the PPE's SPRN_SDR1 once at SPE initialization, so this change renames mfc_sdr_set() to mfc_sdr_setup() and moves the access of SPRN_SDR1 into the mmio wrapper. It also removes the now unneeded member mfc_sdr_RW from struct spu_priv1_collapsed. Signed-off-by: Masato Noguchi Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann -- Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 2 +- arch/powerpc/platforms/cell/spu_priv1_mmio.c | 6 +++--- arch/powerpc/platforms/cell/spufs/switch.c | 3 --- include/asm-powerpc/spu_csa.h | 1 - include/asm-powerpc/spu_priv1.h | 6 +++--- 5 files changed, 7 insertions(+), 11 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d0fb959e3ef..d41ad1d6c04 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -805,7 +805,7 @@ static int __init create_spu(struct device_node *spe) if (ret) goto out_unmap; spin_lock_init(&spu->register_lock); - spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1)); + spu_mfc_sdr_setup(spu); spu_mfc_sr1_set(spu, 0x33); mutex_lock(&spu_mutex); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index 71b69f0a1a4..90011f9aab3 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -84,9 +84,9 @@ static void mfc_dsisr_set(struct spu *spu, u64 dsisr) out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); } -static void mfc_sdr_set(struct spu *spu, u64 sdr) +static void mfc_sdr_setup(struct spu *spu) { - out_be64(&spu->priv1->mfc_sdr_RW, sdr); + out_be64(&spu->priv1->mfc_sdr_RW, mfspr(SPRN_SDR1)); } static void mfc_sr1_set(struct spu *spu, u64 sr1) @@ -146,7 +146,7 @@ const struct spu_priv1_ops spu_priv1_mmio_ops = .mfc_dar_get = mfc_dar_get, .mfc_dsisr_get = mfc_dsisr_get, .mfc_dsisr_set = mfc_dsisr_set, - .mfc_sdr_set = mfc_sdr_set, + .mfc_sdr_setup = mfc_sdr_setup, .mfc_sr1_set = mfc_sr1_set, .mfc_sr1_get = mfc_sr1_get, .mfc_tclass_id_set = mfc_tclass_id_set, diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 0f782ca662b..b85347ff6b2 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2165,9 +2165,6 @@ static void init_priv1(struct spu_state *csa) MFC_STATE1_PROBLEM_STATE_MASK | MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK; - /* Set storage description. */ - csa->priv1.mfc_sdr_RW = mfspr(SPRN_SDR1); - /* Enable OS-specific set of interrupts. */ csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR | CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR | diff --git a/include/asm-powerpc/spu_csa.h b/include/asm-powerpc/spu_csa.h index 964c2d38ccb..bdbf906a767 100644 --- a/include/asm-powerpc/spu_csa.h +++ b/include/asm-powerpc/spu_csa.h @@ -151,7 +151,6 @@ struct spu_priv1_collapsed { u64 mfc_fir_chkstp_enable_RW; u64 smf_sbi_signal_sel; u64 smf_ato_signal_sel; - u64 mfc_sdr_RW; u64 tlb_index_hint_RO; u64 tlb_index_W; u64 tlb_vpn_RW; diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h index 300c458b6d0..4f9a04db99f 100644 --- a/include/asm-powerpc/spu_priv1.h +++ b/include/asm-powerpc/spu_priv1.h @@ -37,7 +37,7 @@ struct spu_priv1_ops u64 (*mfc_dar_get) (struct spu *spu); u64 (*mfc_dsisr_get) (struct spu *spu); void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr); - void (*mfc_sdr_set) (struct spu *spu, u64 sdr); + void (*mfc_sdr_setup) (struct spu *spu); void (*mfc_sr1_set) (struct spu *spu, u64 sr1); u64 (*mfc_sr1_get) (struct spu *spu); void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id); @@ -112,9 +112,9 @@ spu_mfc_dsisr_set (struct spu *spu, u64 dsisr) } static inline void -spu_mfc_sdr_set (struct spu *spu, u64 sdr) +spu_mfc_sdr_setup (struct spu *spu) { - spu_priv1_ops->mfc_sdr_set(spu, sdr); + spu_priv1_ops->mfc_sdr_setup(spu); } static inline void -- cgit v1.2.3-70-g09d2 From cc21a66d7f727ab97b27af9cf763bc0b51510ffa Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 24 Oct 2006 18:31:15 +0200 Subject: [POWERPC] cell: remove unused struct spu variable Remove the mostly unused variable isrc from struct spu and a forgotten function declaration. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 21 +++------------------ include/asm-powerpc/spu.h | 1 - 2 files changed, 3 insertions(+), 19 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d41ad1d6c04..f6c94087db4 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -364,8 +364,7 @@ struct spu *spu_alloc_node(int node) if (!list_empty(&spu_list[node])) { spu = list_entry(spu_list[node].next, struct spu, list); list_del_init(&spu->list); - pr_debug("Got SPU %x %d %d\n", - spu->isrc, spu->number, spu->node); + pr_debug("Got SPU %d %d\n", spu->number, spu->node); spu_init_channels(spu); } mutex_unlock(&spu_mutex); @@ -591,7 +590,6 @@ static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np /* Add the node number */ isrc |= spu->node << IIC_IRQ_NODE_SHIFT; - spu->isrc = isrc; /* Now map interrupts of all 3 classes */ spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc); @@ -733,16 +731,6 @@ struct sysdev_class spu_sysdev_class = { set_kset_name("spu") }; -static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf) -{ - struct spu *spu = container_of(sysdev, struct spu, sysdev); - return sprintf(buf, "%d\n", spu->isrc); - -} -static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL); - -extern int attach_sysdev_to_node(struct sys_device *dev, int nid); - static int spu_create_sysdev(struct spu *spu) { int ret; @@ -756,8 +744,6 @@ static int spu_create_sysdev(struct spu *spu) return ret; } - if (spu->isrc != 0) - sysdev_create_file(&spu->sysdev, &attr_isrc); sysfs_add_device_to_node(&spu->sysdev, spu->nid); return 0; @@ -765,7 +751,6 @@ static int spu_create_sysdev(struct spu *spu) static void spu_destroy_sysdev(struct spu *spu) { - sysdev_remove_file(&spu->sysdev, &attr_isrc); sysfs_remove_device_from_node(&spu->sysdev, spu->nid); sysdev_unregister(&spu->sysdev); } @@ -821,8 +806,8 @@ static int __init create_spu(struct device_node *spe) list_add(&spu->list, &spu_list[spu->node]); mutex_unlock(&spu_mutex); - pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n", - spu->name, spu->isrc, spu->local_store, + pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n", + spu->name, spu->local_store, spu->problem, spu->priv1, spu->priv2, spu->number); goto out; diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index e73ea00efd8..cac4ad90a1d 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -118,7 +118,6 @@ struct spu { int number; int nid; unsigned int irqs[3]; - u32 isrc; u32 node; u64 flags; u64 dar; -- cgit v1.2.3-70-g09d2 From 5737edd1ddbde5ab7f63bb3cb36015edbdb7c295 Mon Sep 17 00:00:00 2001 From: Mark Nutter Date: Tue, 24 Oct 2006 18:31:16 +0200 Subject: [POWERPC] spufs: add support for nonschedulable contexts This adds two new flags to spu_create: SPU_CREATE_NONSCHED: create a context that is never moved away from an SPE once it has started running. This flag can only be used by tasks with the CAP_SYS_NICE capability. SPU_CREATE_ISOLATED: create a nonschedulable context that enters isolation mode upon first run. This requires the SPU_CREATE_NONSCHED flag. Signed-off-by: Jeremy Kerr Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/file.c | 22 +++++++++++++ arch/powerpc/platforms/cell/spufs/hw_ops.c | 5 ++- arch/powerpc/platforms/cell/spufs/inode.c | 17 +++++++++- arch/powerpc/platforms/cell/spufs/run.c | 10 ++++-- arch/powerpc/platforms/cell/spufs/spufs.h | 1 + arch/powerpc/platforms/cell/spufs/switch.c | 50 ++++++++++++++++++++++++++++-- include/asm-powerpc/spu.h | 5 ++- 7 files changed, 103 insertions(+), 7 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 0de8e114e6b..8ca330671ad 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -1531,3 +1531,25 @@ struct tree_descr spufs_dir_contents[] = { { "object-id", &spufs_object_id_ops, 0666, }, {}, }; + +struct tree_descr spufs_dir_nosched_contents[] = { + { "mem", &spufs_mem_fops, 0666, }, + { "mbox", &spufs_mbox_fops, 0444, }, + { "ibox", &spufs_ibox_fops, 0444, }, + { "wbox", &spufs_wbox_fops, 0222, }, + { "mbox_stat", &spufs_mbox_stat_fops, 0444, }, + { "ibox_stat", &spufs_ibox_stat_fops, 0444, }, + { "wbox_stat", &spufs_wbox_stat_fops, 0444, }, + { "signal1", &spufs_signal1_fops, 0666, }, + { "signal2", &spufs_signal2_fops, 0666, }, + { "signal1_type", &spufs_signal1_type, 0666, }, + { "signal2_type", &spufs_signal2_type, 0666, }, + { "mss", &spufs_mss_fops, 0666, }, + { "mfc", &spufs_mfc_fops, 0666, }, + { "cntl", &spufs_cntl_fops, 0666, }, + { "npc", &spufs_npc_ops, 0666, }, + { "psmap", &spufs_psmap_fops, 0666, }, + { "phys-id", &spufs_id_ops, 0666, }, + { "object-id", &spufs_object_id_ops, 0666, }, + {}, +}; diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index efc452e71ab..2ad534a04be 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -219,8 +219,11 @@ static char *spu_hw_get_ls(struct spu_context *ctx) static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val) { - eieio(); + spin_lock_irq(&ctx->spu->register_lock); + if (val & SPU_RUNCNTL_ISOLATE) + out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL); out_be32(&ctx->spu->problem->spu_runcntl_RW, val); + spin_unlock_irq(&ctx->spu->register_lock); } static void spu_hw_runcntl_stop(struct spu_context *ctx) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 427d00a4f6a..787ae71a685 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -258,7 +258,12 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, inode->i_op = &spufs_dir_inode_operations; inode->i_fop = &simple_dir_operations; - ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); + if (flags & SPU_CREATE_NOSCHED) + ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents, + mode, ctx); + else + ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); + if (ret) goto out_free_ctx; @@ -307,6 +312,16 @@ static int spufs_create_context(struct inode *inode, { int ret; + ret = -EPERM; + if ((flags & SPU_CREATE_NOSCHED) && + !capable(CAP_SYS_NICE)) + goto out_unlock; + + ret = -EINVAL; + if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE)) + == SPU_CREATE_ISOLATE) + goto out_unlock; + ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); if (ret) goto out_unlock; diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 63df8cf4ba1..0c03a04b6a3 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -51,11 +51,17 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat) static inline int spu_run_init(struct spu_context *ctx, u32 * npc) { int ret; + unsigned long runcntl = SPU_RUNCNTL_RUNNABLE; if ((ret = spu_acquire_runnable(ctx)) != 0) return ret; - ctx->ops->npc_write(ctx, *npc); - ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); + + if (ctx->flags & SPU_CREATE_ISOLATE) + runcntl |= SPU_RUNCNTL_ISOLATE; + else + ctx->ops->npc_write(ctx, *npc); + + ctx->ops->runcntl_write(ctx, runcntl); return 0; } diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index a0f55ca2d48..b17b809ecd7 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -135,6 +135,7 @@ struct spufs_inode_info { container_of(inode, struct spufs_inode_info, vfs_inode) extern struct tree_descr spufs_dir_contents[]; +extern struct tree_descr spufs_dir_nosched_contents[]; /* system call implementation */ long spufs_run_spu(struct file *file, diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index b85347ff6b2..b47fb50ac2c 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -1916,6 +1916,51 @@ static void save_lscsa(struct spu_state *prev, struct spu *spu) wait_spu_stopped(prev, spu); /* Step 57. */ } +static void force_spu_isolate_exit(struct spu *spu) +{ + struct spu_problem __iomem *prob = spu->problem; + struct spu_priv2 __iomem *priv2 = spu->priv2; + + /* Stop SPE execution and wait for completion. */ + out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); + iobarrier_rw(); + POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING); + + /* Restart SPE master runcntl. */ + spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK); + iobarrier_w(); + + /* Initiate isolate exit request and wait for completion. */ + out_be64(&priv2->spu_privcntl_RW, 4LL); + iobarrier_w(); + out_be32(&prob->spu_runcntl_RW, 2); + iobarrier_rw(); + POLL_WHILE_FALSE((in_be32(&prob->spu_status_R) + & SPU_STATUS_STOPPED_BY_STOP)); + + /* Reset load request to normal. */ + out_be64(&priv2->spu_privcntl_RW, SPU_PRIVCNT_LOAD_REQUEST_NORMAL); + iobarrier_w(); +} + +/** + * stop_spu_isolate + * Check SPU run-control state and force isolated + * exit function as necessary. + */ +static void stop_spu_isolate(struct spu *spu) +{ + struct spu_problem __iomem *prob = spu->problem; + + if (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE) { + /* The SPU is in isolated state; the only way + * to get it out is to perform an isolated + * exit (clean) operation. + */ + force_spu_isolate_exit(spu); + } +} + static void harvest(struct spu_state *prev, struct spu *spu) { /* @@ -1928,6 +1973,7 @@ static void harvest(struct spu_state *prev, struct spu *spu) inhibit_user_access(prev, spu); /* Step 3. */ terminate_spu_app(prev, spu); /* Step 4. */ set_switch_pending(prev, spu); /* Step 5. */ + stop_spu_isolate(spu); /* NEW. */ remove_other_spu_access(prev, spu); /* Step 6. */ suspend_mfc(prev, spu); /* Step 7. */ wait_suspend_mfc_complete(prev, spu); /* Step 8. */ @@ -2096,11 +2142,11 @@ int spu_save(struct spu_state *prev, struct spu *spu) acquire_spu_lock(spu); /* Step 1. */ rc = __do_spu_save(prev, spu); /* Steps 2-53. */ release_spu_lock(spu); - if (rc) { + if (rc != 0 && rc != 2 && rc != 6) { panic("%s failed on SPU[%d], rc=%d.\n", __func__, spu->number, rc); } - return rc; + return 0; } EXPORT_SYMBOL_GPL(spu_save); diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index cac4ad90a1d..a1cf476c66f 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -181,8 +181,10 @@ extern struct spufs_calls { */ #define SPU_CREATE_EVENTS_ENABLED 0x0001 #define SPU_CREATE_GANG 0x0002 +#define SPU_CREATE_NOSCHED 0x0004 +#define SPU_CREATE_ISOLATE 0x0008 -#define SPU_CREATE_FLAG_ALL 0x0003 /* mask of all valid flags */ +#define SPU_CREATE_FLAG_ALL 0x000f /* mask of all valid flags */ #ifdef CONFIG_SPU_FS_MODULE @@ -276,6 +278,7 @@ struct spu_problem { u32 spu_runcntl_RW; /* 0x401c */ #define SPU_RUNCNTL_STOP 0L #define SPU_RUNCNTL_RUNNABLE 1L +#define SPU_RUNCNTL_ISOLATE 2L u8 pad_0x4020_0x4024[0x4]; /* 0x4020 */ u32 spu_status_R; /* 0x4024 */ #define SPU_STOP_STATUS_SHIFT 16 -- cgit v1.2.3-70-g09d2 From eb758ce5b0d84e13cb643b6cc7cb429f6fa28258 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Tue, 24 Oct 2006 18:31:17 +0200 Subject: [POWERPC] spufs: "stautus" isnt a word. Signed-off-by: Jeremy Kerr Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/switch.c | 10 +++++----- include/asm-powerpc/spu.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index b47fb50ac2c..c08981ff7fc 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -102,7 +102,7 @@ static inline int check_spu_isolate(struct spu_state *csa, struct spu *spu) * saved at this time. */ isolate_state = SPU_STATUS_ISOLATED_STATE | - SPU_STATUS_ISOLATED_LOAD_STAUTUS | SPU_STATUS_ISOLATED_EXIT_STAUTUS; + SPU_STATUS_ISOLATED_LOAD_STATUS | SPU_STATUS_ISOLATED_EXIT_STATUS; return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0; } @@ -1046,12 +1046,12 @@ static inline int suspend_spe(struct spu_state *csa, struct spu *spu) */ if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) { if (in_be32(&prob->spu_status_R) & - SPU_STATUS_ISOLATED_EXIT_STAUTUS) { + SPU_STATUS_ISOLATED_EXIT_STATUS) { POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING); } if ((in_be32(&prob->spu_status_R) & - SPU_STATUS_ISOLATED_LOAD_STAUTUS) + SPU_STATUS_ISOLATED_LOAD_STATUS) || (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE)) { out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); @@ -1085,7 +1085,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu) */ if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) { if (in_be32(&prob->spu_status_R) & - SPU_STATUS_ISOLATED_EXIT_STAUTUS) { + SPU_STATUS_ISOLATED_EXIT_STATUS) { spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK); eieio(); @@ -1095,7 +1095,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu) SPU_STATUS_RUNNING); } if ((in_be32(&prob->spu_status_R) & - SPU_STATUS_ISOLATED_LOAD_STAUTUS) + SPU_STATUS_ISOLATED_LOAD_STATUS) || (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE)) { spu_mfc_sr1_set(spu, diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index a1cf476c66f..704e8a8d2eb 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -291,8 +291,8 @@ struct spu_problem { #define SPU_STATUS_INVALID_INSTR 0x20 #define SPU_STATUS_INVALID_CH 0x40 #define SPU_STATUS_ISOLATED_STATE 0x80 -#define SPU_STATUS_ISOLATED_LOAD_STAUTUS 0x200 -#define SPU_STATUS_ISOLATED_EXIT_STAUTUS 0x400 +#define SPU_STATUS_ISOLATED_LOAD_STATUS 0x200 +#define SPU_STATUS_ISOLATED_EXIT_STATUS 0x400 u8 pad_0x4028_0x402c[0x4]; /* 0x4028 */ u32 spu_spe_R; /* 0x402c */ u8 pad_0x4030_0x4034[0x4]; /* 0x4030 */ -- cgit v1.2.3-70-g09d2 From e570beb6bb1a623849901efbf939063ec4775c9e Mon Sep 17 00:00:00 2001 From: Christian Krafft Date: Tue, 24 Oct 2006 18:31:23 +0200 Subject: [POWERPC] cell: add support for registering sysfs attributes to spus In order to add sysfs attributes to all spu's, there is a need for a list of all available spu's. Adding the device_node makes also sense, as it is needed for proper register access. This patch also adds two functions to create and remove sysfs attributes and attribute_groups to all spus. That allows to group spu attributes in a subdirectory like: /sys/devices/system/spu/spuX/group_name/what_ever This will be used by cbe_thermal to group all attributes dealing with thermal support in one directory. Signed-off-by: Christian Krafft Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 58 ++++++++++++++++++++++++++++++++++ include/asm-powerpc/spu.h | 9 ++++++ 2 files changed, 67 insertions(+) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d78b0af038e..b75b091098e 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -333,6 +333,7 @@ static void spu_free_irqs(struct spu *spu) } static struct list_head spu_list[MAX_NUMNODES]; +static LIST_HEAD(spu_full_list); static DEFINE_MUTEX(spu_mutex); static void spu_init_channels(struct spu *spu) @@ -744,6 +745,57 @@ struct sysdev_class spu_sysdev_class = { set_kset_name("spu") }; +int spu_add_sysdev_attr(struct sysdev_attribute *attr) +{ + struct spu *spu; + mutex_lock(&spu_mutex); + + list_for_each_entry(spu, &spu_full_list, full_list) + sysdev_create_file(&spu->sysdev, attr); + + mutex_unlock(&spu_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(spu_add_sysdev_attr); + +int spu_add_sysdev_attr_group(struct attribute_group *attrs) +{ + struct spu *spu; + mutex_lock(&spu_mutex); + + list_for_each_entry(spu, &spu_full_list, full_list) + sysfs_create_group(&spu->sysdev.kobj, attrs); + + mutex_unlock(&spu_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group); + + +void spu_remove_sysdev_attr(struct sysdev_attribute *attr) +{ + struct spu *spu; + mutex_lock(&spu_mutex); + + list_for_each_entry(spu, &spu_full_list, full_list) + sysdev_remove_file(&spu->sysdev, attr); + + mutex_unlock(&spu_mutex); +} +EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr); + +void spu_remove_sysdev_attr_group(struct attribute_group *attrs) +{ + struct spu *spu; + mutex_lock(&spu_mutex); + + list_for_each_entry(spu, &spu_full_list, full_list) + sysfs_remove_group(&spu->sysdev.kobj, attrs); + + mutex_unlock(&spu_mutex); +} +EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group); + static int spu_create_sysdev(struct spu *spu) { int ret; @@ -817,6 +869,9 @@ static int __init create_spu(struct device_node *spe) goto out_free_irqs; list_add(&spu->list, &spu_list[spu->node]); + list_add(&spu->full_list, &spu_full_list); + spu->devnode = of_node_get(spe); + mutex_unlock(&spu_mutex); pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n", @@ -839,6 +894,9 @@ out: static void destroy_spu(struct spu *spu) { list_del_init(&spu->list); + list_del_init(&spu->full_list); + + of_node_put(spu->devnode); spu_destroy_sysdev(spu); spu_free_irqs(spu); diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index 704e8a8d2eb..ffa4df08360 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -115,6 +115,7 @@ struct spu { struct spu_priv2 __iomem *priv2; struct list_head list; struct list_head sched_list; + struct list_head full_list; int number; int nid; unsigned int irqs[3]; @@ -143,6 +144,8 @@ struct spu { char irq_c1[8]; char irq_c2[8]; + struct device_node *devnode; + struct sys_device sysdev; }; @@ -200,6 +203,12 @@ static inline void unregister_spu_syscalls(struct spufs_calls *calls) } #endif /* MODULE */ +int spu_add_sysdev_attr(struct sysdev_attribute *attr); +void spu_remove_sysdev_attr(struct sysdev_attribute *attr); + +int spu_add_sysdev_attr_group(struct attribute_group *attrs); +void spu_remove_sysdev_attr_group(struct attribute_group *attrs); + /* * Notifier blocks: -- cgit v1.2.3-70-g09d2 From ff8a8f25976aa58bbae7883405b00dcbaf4cc823 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 24 Oct 2006 18:31:27 +0200 Subject: [POWERPC] add support for stopping spus from xmon This patch adds support for stopping, and restarting, spus from xmon. We use the spu master runcntl bit to stop execution, this is apparently the "right" way to control spu execution and spufs will be changed in the future to use this bit. Testing has shown that to restart execution we have to turn the master runcntl bit on and also rewrite the spu runcntl bit, even if it is already set to 1 (running). Stopping spus is triggered by the xmon command 'ss' - "spus stop" perhaps. Restarting them is triggered via 'sr'. Restart doesn't start execution on spus unless they were running prior to being stopped by xmon. Walking the spu->full_list in xmon after a panic, would mean corruption of any spu struct would make all the others inaccessible. To avoid this, and also to make the next patch easier, we cache pointers to all spus during boot. We attempt to catch and recover from errors while stopping and restarting the spus, but as with most xmon functionality there are no guarantees that performing these operations won't crash xmon itself. Signed-off-by: Michael Ellerman Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 4 + arch/powerpc/xmon/xmon.c | 142 ++++++++++++++++++++++++++++++++- include/asm-powerpc/xmon.h | 2 + 3 files changed, 146 insertions(+), 2 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index b75b091098e..032bc923342 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "interrupt.h" @@ -943,6 +944,9 @@ static int __init init_spu_base(void) break; } } + + xmon_register_spus(&spu_full_list); + return ret; } module_init(init_spu_base); diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index f56ffef4def..6a2ed8b319f 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #ifdef CONFIG_PPC64 #include @@ -147,6 +149,8 @@ static void xmon_print_symbol(unsigned long address, const char *mid, const char *after); static const char *getvecname(unsigned long vec); +static int do_spu_cmd(void); + int xmon_no_auto_backtrace; extern int print_insn_powerpc(unsigned long, unsigned long, int); @@ -209,8 +213,12 @@ Commands:\n\ mi show information about memory allocation\n\ p call a procedure\n\ r print registers\n\ - s single step\n\ - S print special registers\n\ + s single step\n" +#ifdef CONFIG_PPC_CELL +" ss stop execution on all spus\n\ + sr restore execution on stopped spus\n" +#endif +" S print special registers\n\ t print backtrace\n\ x exit monitor and recover\n\ X exit monitor and dont recover\n" @@ -518,6 +526,7 @@ int xmon(struct pt_regs *excp) xmon_save_regs(®s); excp = ®s; } + return xmon_core(excp, 0); } EXPORT_SYMBOL(xmon); @@ -809,6 +818,8 @@ cmds(struct pt_regs *excp) cacheflush(); break; case 's': + if (do_spu_cmd() == 0) + break; if (do_step(excp)) return cmd; break; @@ -2630,3 +2641,130 @@ void __init xmon_setup(void) if (xmon_early) debugger(NULL); } + +#ifdef CONFIG_PPC_CELL + +struct spu_info { + struct spu *spu; + u64 saved_mfc_sr1_RW; + u32 saved_spu_runcntl_RW; + u8 stopped_ok; +}; + +#define XMON_NUM_SPUS 16 /* Enough for current hardware */ + +static struct spu_info spu_info[XMON_NUM_SPUS]; + +void xmon_register_spus(struct list_head *list) +{ + struct spu *spu; + + list_for_each_entry(spu, list, full_list) { + if (spu->number >= XMON_NUM_SPUS) { + WARN_ON(1); + continue; + } + + spu_info[spu->number].spu = spu; + spu_info[spu->number].stopped_ok = 0; + } +} + +static void stop_spus(void) +{ + struct spu *spu; + int i; + u64 tmp; + + for (i = 0; i < XMON_NUM_SPUS; i++) { + if (!spu_info[i].spu) + continue; + + if (setjmp(bus_error_jmp) == 0) { + catch_memory_errors = 1; + sync(); + + spu = spu_info[i].spu; + + spu_info[i].saved_spu_runcntl_RW = + in_be32(&spu->problem->spu_runcntl_RW); + + tmp = spu_mfc_sr1_get(spu); + spu_info[i].saved_mfc_sr1_RW = tmp; + + tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; + spu_mfc_sr1_set(spu, tmp); + + sync(); + __delay(200); + + spu_info[i].stopped_ok = 1; + printf("Stopped spu %.2d\n", i); + } else { + catch_memory_errors = 0; + printf("*** Error stopping spu %.2d\n", i); + } + catch_memory_errors = 0; + } +} + +static void restart_spus(void) +{ + struct spu *spu; + int i; + + for (i = 0; i < XMON_NUM_SPUS; i++) { + if (!spu_info[i].spu) + continue; + + if (!spu_info[i].stopped_ok) { + printf("*** Error, spu %d was not successfully stopped" + ", not restarting\n", i); + continue; + } + + if (setjmp(bus_error_jmp) == 0) { + catch_memory_errors = 1; + sync(); + + spu = spu_info[i].spu; + spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW); + out_be32(&spu->problem->spu_runcntl_RW, + spu_info[i].saved_spu_runcntl_RW); + + sync(); + __delay(200); + + printf("Restarted spu %.2d\n", i); + } else { + catch_memory_errors = 0; + printf("*** Error restarting spu %.2d\n", i); + } + catch_memory_errors = 0; + } +} + +static int do_spu_cmd(void) +{ + int cmd; + + cmd = inchar(); + switch (cmd) { + case 's': + stop_spus(); + break; + case 'r': + restart_spus(); + break; + default: + return -1; + } + + return 0; +} +#else /* ! CONFIG_PPC_CELL */ +static int do_spu_cmd(void) +{ + return -1; +} +#endif diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h index f1d337ed68d..88320a05f0a 100644 --- a/include/asm-powerpc/xmon.h +++ b/include/asm-powerpc/xmon.h @@ -14,8 +14,10 @@ #ifdef CONFIG_XMON extern void xmon_setup(void); +extern void xmon_register_spus(struct list_head *list); #else static inline void xmon_setup(void) { }; +static inline void xmon_register_spus(struct list_head *list) { }; #endif #endif /* __KERNEL __ */ -- cgit v1.2.3-70-g09d2 From 2b890bc2ce95e8c141b38ea86100826b46534295 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 6 Nov 2006 11:19:08 +0100 Subject: [PATCH] Remove dead code in iommu.h iommu_setup_pSeries() and iommu_setup_dart() are declared extern but are not implemented, so remove them. Remove ifdef around extern function declaration. Signed-off-by: Sascha Hauer Signed-off-by: Paul Mackerras --- include/asm-powerpc/iommu.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index a5e98641a2a..264ed624277 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -52,17 +52,9 @@ struct iommu_table { struct scatterlist; struct device_node; -#ifdef CONFIG_PPC_MULTIPLATFORM - -/* Walks all buses and creates iommu tables */ -extern void iommu_setup_pSeries(void); -extern void iommu_setup_dart(void); - /* Frees table for an individual device node */ extern void iommu_free_table(struct device_node *dn); -#endif /* CONFIG_PPC_MULTIPLATFORM */ - /* Initializes an iommu_table based in values set in the passed-in * structure */ -- cgit v1.2.3-70-g09d2 From 67764a03193d0246cf9bb491b41806508d415830 Mon Sep 17 00:00:00 2001 From: "s.hauer@pengutronix.de" Date: Thu, 2 Nov 2006 13:56:00 +0100 Subject: [PATCH] Remove unnecessary ifdef in include/asm-powerpc/pci.h Current kernels always have one of CONFIG_PPC_MULTIPLATFORM or CONFIG_PPC32 defined, so remove bogus ifdef. Signed-off-by: Sascha Hauer Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- include/asm-powerpc/pci.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index 46afd29b904..051694f14c3 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h @@ -238,12 +238,10 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file, unsigned long size, pgprot_t prot); -#if defined(CONFIG_PPC_MULTIPLATFORM) || defined(CONFIG_PPC32) #define HAVE_ARCH_PCI_RESOURCE_TO_USER extern void pci_resource_to_user(const struct pci_dev *dev, int bar, const struct resource *rsrc, resource_size_t *start, resource_size_t *end); -#endif /* CONFIG_PPC_MULTIPLATFORM || CONFIG_PPC32 */ #endif /* __KERNEL__ */ #endif /* __ASM_POWERPC_PCI_H */ -- cgit v1.2.3-70-g09d2 From 68e1300a55310a288b87f2a7d6045df0d0f802bc Mon Sep 17 00:00:00 2001 From: "s.hauer@pengutronix.de" Date: Thu, 2 Nov 2006 13:56:01 +0100 Subject: [PATCH] Remove _machine macro The _machine macro was once used for compatibility with ARCH=ppc drivers. It is unused in current kernels, so remove it. Signed-off-by: Sascha Hauer Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- include/asm-powerpc/processor.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index 6cb6fb19e57..a26c32ee552 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -53,10 +53,6 @@ extern unsigned char ucBoardRevMaj, ucBoardRevMin; #endif /* CONFIG_PPC_PREP */ -#ifndef CONFIG_PPC_MULTIPLATFORM -#define _machine 0 -#endif /* CONFIG_PPC_MULTIPLATFORM */ - #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */ /* -- cgit v1.2.3-70-g09d2 From 0f6c95dcabdaa8fdc95b125582bd12625adfbde6 Mon Sep 17 00:00:00 2001 From: Nicolas DET Date: Wed, 8 Nov 2006 17:14:43 +0100 Subject: [PATCH] Add MPC5200 Interrupt Controller support. This adds support for the MPC52xx Interrupt controller for ARCH=powerpc. It includes the main code in arch/powerpc/sysdev/ as well as a header file in include/asm-powerpc. Signed-off-by: Nicolas DET Acked-by: Sylvain Munaut Acked-by: Grant Likely Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/Makefile | 1 + arch/powerpc/sysdev/mpc52xx_pic.c | 538 ++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/mpc52xx.h | 287 ++++++++++++++++++++ 3 files changed, 826 insertions(+) create mode 100644 arch/powerpc/sysdev/mpc52xx_pic.c create mode 100644 include/asm-powerpc/mpc52xx.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index f15af0e82f1..5b87f7b42a1 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ +obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_pic.o ifeq ($(CONFIG_PPC_MERGE),y) obj-$(CONFIG_PPC_I8259) += i8259.o diff --git a/arch/powerpc/sysdev/mpc52xx_pic.c b/arch/powerpc/sysdev/mpc52xx_pic.c new file mode 100644 index 00000000000..6df51f04b8f --- /dev/null +++ b/arch/powerpc/sysdev/mpc52xx_pic.c @@ -0,0 +1,538 @@ +/* + * + * Programmable Interrupt Controller functions for the Freescale MPC52xx. + * + * Copyright (C) 2006 bplan GmbH + * + * Based on the code from the 2.4 kernel by + * Dale Farnsworth and Kent Borg. + * + * Copyright (C) 2004 Sylvain Munaut + * Copyright (C) 2003 Montavista Software, Inc + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * +*/ + +static struct mpc52xx_intr __iomem *intr; +static struct mpc52xx_sdma __iomem *sdma; +static struct irq_host *mpc52xx_irqhost = NULL; + +static unsigned char mpc52xx_map_senses[4] = { + IRQ_TYPE_LEVEL_HIGH, + IRQ_TYPE_EDGE_RISING, + IRQ_TYPE_EDGE_FALLING, + IRQ_TYPE_LEVEL_LOW, +}; + +/* + * +*/ + +static inline void io_be_setbit(u32 __iomem * addr, int bitno) +{ + out_be32(addr, in_be32(addr) | (1 << bitno)); +} + +static inline void io_be_clrbit(u32 __iomem * addr, int bitno) +{ + out_be32(addr, in_be32(addr) & ~(1 << bitno)); +} + +/* + * IRQ[0-3] interrupt irq_chip +*/ + +static void mpc52xx_extirq_mask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_clrbit(&intr->ctrl, 11 - l2irq); +} + +static void mpc52xx_extirq_unmask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_setbit(&intr->ctrl, 11 - l2irq); +} + +static void mpc52xx_extirq_ack(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_setbit(&intr->ctrl, 27 - l2irq); +} + +static struct irq_chip mpc52xx_extirq_irqchip = { + .typename = " MPC52xx IRQ[0-3] ", + .mask = mpc52xx_extirq_mask, + .unmask = mpc52xx_extirq_unmask, + .ack = mpc52xx_extirq_ack, +}; + +/* + * Main interrupt irq_chip +*/ + +static void mpc52xx_main_mask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_setbit(&intr->main_mask, 15 - l2irq); +} + +static void mpc52xx_main_unmask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_clrbit(&intr->main_mask, 15 - l2irq); +} + +static struct irq_chip mpc52xx_main_irqchip = { + .typename = "MPC52xx Main", + .mask = mpc52xx_main_mask, + .mask_ack = mpc52xx_main_mask, + .unmask = mpc52xx_main_unmask, +}; + +/* + * Peripherals interrupt irq_chip +*/ + +static void mpc52xx_periph_mask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_setbit(&intr->per_mask, 31 - l2irq); +} + +static void mpc52xx_periph_unmask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_clrbit(&intr->per_mask, 31 - l2irq); +} + +static struct irq_chip mpc52xx_periph_irqchip = { + .typename = "MPC52xx Peripherals", + .mask = mpc52xx_periph_mask, + .mask_ack = mpc52xx_periph_mask, + .unmask = mpc52xx_periph_unmask, +}; + +/* + * SDMA interrupt irq_chip +*/ + +static void mpc52xx_sdma_mask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_setbit(&sdma->IntMask, l2irq); +} + +static void mpc52xx_sdma_unmask(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + io_be_clrbit(&sdma->IntMask, l2irq); +} + +static void mpc52xx_sdma_ack(unsigned int virq) +{ + int irq; + int l2irq; + + irq = irq_map[virq].hwirq; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); + + out_be32(&sdma->IntPend, 1 << l2irq); +} + +static struct irq_chip mpc52xx_sdma_irqchip = { + .typename = "MPC52xx SDMA", + .mask = mpc52xx_sdma_mask, + .unmask = mpc52xx_sdma_unmask, + .ack = mpc52xx_sdma_ack, +}; + +/* + * irq_host +*/ + +static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node) +{ + pr_debug("%s: node=%p\n", __func__, node); + return mpc52xx_irqhost->host_data == node; +} + +static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct, + u32 * intspec, unsigned int intsize, + irq_hw_number_t * out_hwirq, + unsigned int *out_flags) +{ + int intrvect_l1; + int intrvect_l2; + int intrvect_type; + int intrvect_linux; + + if (intsize != 3) + return -1; + + intrvect_l1 = (int)intspec[0]; + intrvect_l2 = (int)intspec[1]; + intrvect_type = (int)intspec[2]; + + intrvect_linux = + (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK; + intrvect_linux |= + (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK; + + pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1, + intrvect_l2); + + *out_hwirq = intrvect_linux; + *out_flags = mpc52xx_map_senses[intrvect_type]; + + return 0; +} + +/* + * this function retrieves the correct IRQ type out + * of the MPC regs + * Only externals IRQs needs this +*/ +static int mpc52xx_irqx_gettype(int irq) +{ + int type; + u32 ctrl_reg; + + ctrl_reg = in_be32(&intr->ctrl); + type = (ctrl_reg >> (22 - irq * 2)) & 0x3; + + return mpc52xx_map_senses[type]; +} + +static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t irq) +{ + int l1irq; + int l2irq; + struct irq_chip *good_irqchip; + void *good_handle; + int type; + + l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET; + l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; + + /* + * Most of ours IRQs will be level low + * Only external IRQs on some platform may be others + */ + type = IRQ_TYPE_LEVEL_LOW; + + switch (l1irq) { + case MPC52xx_IRQ_L1_CRIT: + pr_debug("%s: Critical. l2=%x\n", __func__, l2irq); + + BUG_ON(l2irq != 0); + + type = mpc52xx_irqx_gettype(l2irq); + good_irqchip = &mpc52xx_extirq_irqchip; + break; + + case MPC52xx_IRQ_L1_MAIN: + pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq); + + if ((l2irq >= 1) && (l2irq <= 3)) { + type = mpc52xx_irqx_gettype(l2irq); + good_irqchip = &mpc52xx_extirq_irqchip; + } else { + good_irqchip = &mpc52xx_main_irqchip; + } + break; + + case MPC52xx_IRQ_L1_PERP: + pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq); + good_irqchip = &mpc52xx_periph_irqchip; + break; + + case MPC52xx_IRQ_L1_SDMA: + pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq); + good_irqchip = &mpc52xx_sdma_irqchip; + break; + + default: + pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq); + printk(KERN_ERR "Unknow IRQ!\n"); + return -EINVAL; + } + + switch (type) { + case IRQ_TYPE_EDGE_FALLING: + case IRQ_TYPE_EDGE_RISING: + good_handle = handle_edge_irq; + break; + default: + good_handle = handle_level_irq; + } + + set_irq_chip_and_handler(virq, good_irqchip, good_handle); + + pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq, + (int)irq, type); + + return 0; +} + +static struct irq_host_ops mpc52xx_irqhost_ops = { + .match = mpc52xx_irqhost_match, + .xlate = mpc52xx_irqhost_xlate, + .map = mpc52xx_irqhost_map, +}; + +/* + * init (public) +*/ + +void __init mpc52xx_init_irq(void) +{ + struct device_node *picnode = NULL; + int picnode_regsize; + u32 picnode_regoffset; + + struct device_node *sdmanode = NULL; + int sdmanode_regsize; + u32 sdmanode_regoffset; + + u64 size64; + int flags; + + u32 intr_ctrl; + + picnode = of_find_compatible_node(NULL, "interrupt-controller", + "mpc5200-pic"); + if (picnode == NULL) { + printk(KERN_ERR "MPC52xx PIC: " + "Unable to find the interrupt controller " + "in the OpenFirmware device tree\n"); + goto end; + } + + sdmanode = of_find_compatible_node(NULL, "dma-controller", + "mpc5200-bestcomm"); + if (sdmanode == NULL) { + printk(KERN_ERR "MPC52xx PIC" + "Unable to find the Bestcomm DMA controller device " + "in the OpenFirmware device tree\n"); + goto end; + } + + /* Retrieve PIC ressources */ + picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags); + if (picnode_regoffset == 0) { + printk(KERN_ERR "MPC52xx PIC" + "Unable to get the interrupt controller address\n"); + goto end; + } + + picnode_regoffset = + of_translate_address(picnode, (u32 *) picnode_regoffset); + picnode_regsize = (int)size64; + + /* Retrieve SDMA ressources */ + sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags); + if (sdmanode_regoffset == 0) { + printk(KERN_ERR "MPC52xx PIC: " + "Unable to get the Bestcomm DMA controller address\n"); + goto end; + } + + sdmanode_regoffset = + of_translate_address(sdmanode, (u32 *) sdmanode_regoffset); + sdmanode_regsize = (int)size64; + + /* Remap the necessary zones */ + intr = ioremap(picnode_regoffset, picnode_regsize); + if (intr == NULL) { + printk(KERN_ERR "MPC52xx PIC: " + "Unable to ioremap interrupt controller registers!\n"); + goto end; + } + + sdma = ioremap(sdmanode_regoffset, sdmanode_regsize); + if (sdma == NULL) { + iounmap(intr); + printk(KERN_ERR "MPC52xx PIC: " + "Unable to ioremap Bestcomm DMA registers!\n"); + goto end; + } + + printk(KERN_INFO "MPC52xx PIC: MPC52xx PIC Remapped at 0x%8.8x\n", + picnode_regoffset); + printk(KERN_INFO "MPC52xx PIC: MPC52xx SDMA Remapped at 0x%8.8x\n", + sdmanode_regoffset); + + /* Disable all interrupt sources. */ + out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */ + out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */ + out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */ + out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */ + intr_ctrl = in_be32(&intr->ctrl); + intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */ + intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */ + 0x00001000 | /* MEE master external enable */ + 0x00000000 | /* 0 means disable IRQ 0-3 */ + 0x00000001; /* CEb route critical normally */ + out_be32(&intr->ctrl, intr_ctrl); + + /* Zero a bunch of the priority settings. */ + out_be32(&intr->per_pri1, 0); + out_be32(&intr->per_pri2, 0); + out_be32(&intr->per_pri3, 0); + out_be32(&intr->main_pri1, 0); + out_be32(&intr->main_pri2, 0); + + /* + * As last step, add an irq host to translate the real + * hw irq information provided by the ofw to linux virq + */ + + mpc52xx_irqhost = + irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTHWIRQ, + &mpc52xx_irqhost_ops, -1); + + if (mpc52xx_irqhost) { + mpc52xx_irqhost->host_data = picnode; + printk(KERN_INFO "MPC52xx PIC is up and running!\n"); + } else { + printk(KERN_ERR + "MPC52xx PIC: Unable to allocate the IRQ host\n"); + } + +end: + of_node_put(picnode); + of_node_put(sdmanode); +} + +/* + * get_irq (public) +*/ +unsigned int mpc52xx_get_irq(void) +{ + u32 status; + int irq = NO_IRQ_IGNORE; + + status = in_be32(&intr->enc_status); + if (status & 0x00000400) { /* critical */ + irq = (status >> 8) & 0x3; + if (irq == 2) /* high priority peripheral */ + goto peripheral; + irq |= (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) & + MPC52xx_IRQ_L1_MASK; + } else if (status & 0x00200000) { /* main */ + irq = (status >> 16) & 0x1f; + if (irq == 4) /* low priority peripheral */ + goto peripheral; + irq |= (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) & + MPC52xx_IRQ_L1_MASK; + } else if (status & 0x20000000) { /* peripheral */ + peripheral: + irq = (status >> 24) & 0x1f; + if (irq == 0) { /* bestcomm */ + status = in_be32(&sdma->IntPend); + irq = ffs(status) - 1; + irq |= (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) & + MPC52xx_IRQ_L1_MASK; + } else + irq |= (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) & + MPC52xx_IRQ_L1_MASK; + } + + pr_debug("%s: irq=%x. virq=%d\n", __func__, irq, + irq_linear_revmap(mpc52xx_irqhost, irq)); + + return irq_linear_revmap(mpc52xx_irqhost, irq); +} + diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h new file mode 100644 index 00000000000..e9aa622f19f --- /dev/null +++ b/include/asm-powerpc/mpc52xx.h @@ -0,0 +1,287 @@ +/* + * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips + * May need to be cleaned as the port goes on ... + * + * Copyright (C) 2004-2005 Sylvain Munaut + * Copyright (C) 2003 MontaVista, Software, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef __ASM_POWERPC_MPC52xx_H__ +#define __ASM_POWERPC_MPC52xx_H__ + +#ifndef __ASSEMBLY__ +#include +#include +#endif /* __ASSEMBLY__ */ + + +/* ======================================================================== */ +/* HW IRQ mapping */ +/* ======================================================================== */ + +#define MPC52xx_IRQ_L1_CRIT (0) +#define MPC52xx_IRQ_L1_MAIN (1) +#define MPC52xx_IRQ_L1_PERP (2) +#define MPC52xx_IRQ_L1_SDMA (3) + +#define MPC52xx_IRQ_L1_OFFSET (6) +#define MPC52xx_IRQ_L1_MASK (0xc0) + +#define MPC52xx_IRQ_L2_OFFSET (0) +#define MPC52xx_IRQ_L2_MASK (0x3f) + +#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0) + + +/* ======================================================================== */ +/* Structures mapping of some unit register set */ +/* ======================================================================== */ + +#ifndef __ASSEMBLY__ + +/* Interrupt controller Register set */ +struct mpc52xx_intr { + u32 per_mask; /* INTR + 0x00 */ + u32 per_pri1; /* INTR + 0x04 */ + u32 per_pri2; /* INTR + 0x08 */ + u32 per_pri3; /* INTR + 0x0c */ + u32 ctrl; /* INTR + 0x10 */ + u32 main_mask; /* INTR + 0x14 */ + u32 main_pri1; /* INTR + 0x18 */ + u32 main_pri2; /* INTR + 0x1c */ + u32 reserved1; /* INTR + 0x20 */ + u32 enc_status; /* INTR + 0x24 */ + u32 crit_status; /* INTR + 0x28 */ + u32 main_status; /* INTR + 0x2c */ + u32 per_status; /* INTR + 0x30 */ + u32 reserved2; /* INTR + 0x34 */ + u32 per_error; /* INTR + 0x38 */ +}; + +/* Memory Mapping Control */ +struct mpc52xx_mmap_ctl { + u32 mbar; /* MMAP_CTRL + 0x00 */ + + u32 cs0_start; /* MMAP_CTRL + 0x04 */ + u32 cs0_stop; /* MMAP_CTRL + 0x08 */ + u32 cs1_start; /* MMAP_CTRL + 0x0c */ + u32 cs1_stop; /* MMAP_CTRL + 0x10 */ + u32 cs2_start; /* MMAP_CTRL + 0x14 */ + u32 cs2_stop; /* MMAP_CTRL + 0x18 */ + u32 cs3_start; /* MMAP_CTRL + 0x1c */ + u32 cs3_stop; /* MMAP_CTRL + 0x20 */ + u32 cs4_start; /* MMAP_CTRL + 0x24 */ + u32 cs4_stop; /* MMAP_CTRL + 0x28 */ + u32 cs5_start; /* MMAP_CTRL + 0x2c */ + u32 cs5_stop; /* MMAP_CTRL + 0x30 */ + + u32 sdram0; /* MMAP_CTRL + 0x34 */ + u32 sdram1; /* MMAP_CTRL + 0X38 */ + + u32 reserved[4]; /* MMAP_CTRL + 0x3c .. 0x48 */ + + u32 boot_start; /* MMAP_CTRL + 0x4c */ + u32 boot_stop; /* MMAP_CTRL + 0x50 */ + + u32 ipbi_ws_ctrl; /* MMAP_CTRL + 0x54 */ + + u32 cs6_start; /* MMAP_CTRL + 0x58 */ + u32 cs6_stop; /* MMAP_CTRL + 0x5c */ + u32 cs7_start; /* MMAP_CTRL + 0x60 */ + u32 cs7_stop; /* MMAP_CTRL + 0x64 */ +}; + +/* SDRAM control */ +struct mpc52xx_sdram { + u32 mode; /* SDRAM + 0x00 */ + u32 ctrl; /* SDRAM + 0x04 */ + u32 config1; /* SDRAM + 0x08 */ + u32 config2; /* SDRAM + 0x0c */ +}; + +/* SDMA */ +struct mpc52xx_sdma { + u32 taskBar; /* SDMA + 0x00 */ + u32 currentPointer; /* SDMA + 0x04 */ + u32 endPointer; /* SDMA + 0x08 */ + u32 variablePointer; /* SDMA + 0x0c */ + + u8 IntVect1; /* SDMA + 0x10 */ + u8 IntVect2; /* SDMA + 0x11 */ + u16 PtdCntrl; /* SDMA + 0x12 */ + + u32 IntPend; /* SDMA + 0x14 */ + u32 IntMask; /* SDMA + 0x18 */ + + u16 tcr[16]; /* SDMA + 0x1c .. 0x3a */ + + u8 ipr[32]; /* SDMA + 0x3c .. 0x5b */ + + u32 cReqSelect; /* SDMA + 0x5c */ + u32 task_size0; /* SDMA + 0x60 */ + u32 task_size1; /* SDMA + 0x64 */ + u32 MDEDebug; /* SDMA + 0x68 */ + u32 ADSDebug; /* SDMA + 0x6c */ + u32 Value1; /* SDMA + 0x70 */ + u32 Value2; /* SDMA + 0x74 */ + u32 Control; /* SDMA + 0x78 */ + u32 Status; /* SDMA + 0x7c */ + u32 PTDDebug; /* SDMA + 0x80 */ +}; + +/* GPT */ +struct mpc52xx_gpt { + u32 mode; /* GPTx + 0x00 */ + u32 count; /* GPTx + 0x04 */ + u32 pwm; /* GPTx + 0x08 */ + u32 status; /* GPTx + 0X0c */ +}; + +/* GPIO */ +struct mpc52xx_gpio { + u32 port_config; /* GPIO + 0x00 */ + u32 simple_gpioe; /* GPIO + 0x04 */ + u32 simple_ode; /* GPIO + 0x08 */ + u32 simple_ddr; /* GPIO + 0x0c */ + u32 simple_dvo; /* GPIO + 0x10 */ + u32 simple_ival; /* GPIO + 0x14 */ + u8 outo_gpioe; /* GPIO + 0x18 */ + u8 reserved1[3]; /* GPIO + 0x19 */ + u8 outo_dvo; /* GPIO + 0x1c */ + u8 reserved2[3]; /* GPIO + 0x1d */ + u8 sint_gpioe; /* GPIO + 0x20 */ + u8 reserved3[3]; /* GPIO + 0x21 */ + u8 sint_ode; /* GPIO + 0x24 */ + u8 reserved4[3]; /* GPIO + 0x25 */ + u8 sint_ddr; /* GPIO + 0x28 */ + u8 reserved5[3]; /* GPIO + 0x29 */ + u8 sint_dvo; /* GPIO + 0x2c */ + u8 reserved6[3]; /* GPIO + 0x2d */ + u8 sint_inten; /* GPIO + 0x30 */ + u8 reserved7[3]; /* GPIO + 0x31 */ + u16 sint_itype; /* GPIO + 0x34 */ + u16 reserved8; /* GPIO + 0x36 */ + u8 gpio_control; /* GPIO + 0x38 */ + u8 reserved9[3]; /* GPIO + 0x39 */ + u8 sint_istat; /* GPIO + 0x3c */ + u8 sint_ival; /* GPIO + 0x3d */ + u8 bus_errs; /* GPIO + 0x3e */ + u8 reserved10; /* GPIO + 0x3f */ +}; + +#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD 4 +#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD 5 +#define MPC52xx_GPIO_PCI_DIS (1<<15) + +/* GPIO with WakeUp*/ +struct mpc52xx_gpio_wkup { + u8 wkup_gpioe; /* GPIO_WKUP + 0x00 */ + u8 reserved1[3]; /* GPIO_WKUP + 0x03 */ + u8 wkup_ode; /* GPIO_WKUP + 0x04 */ + u8 reserved2[3]; /* GPIO_WKUP + 0x05 */ + u8 wkup_ddr; /* GPIO_WKUP + 0x08 */ + u8 reserved3[3]; /* GPIO_WKUP + 0x09 */ + u8 wkup_dvo; /* GPIO_WKUP + 0x0C */ + u8 reserved4[3]; /* GPIO_WKUP + 0x0D */ + u8 wkup_inten; /* GPIO_WKUP + 0x10 */ + u8 reserved5[3]; /* GPIO_WKUP + 0x11 */ + u8 wkup_iinten; /* GPIO_WKUP + 0x14 */ + u8 reserved6[3]; /* GPIO_WKUP + 0x15 */ + u16 wkup_itype; /* GPIO_WKUP + 0x18 */ + u8 reserved7[2]; /* GPIO_WKUP + 0x1A */ + u8 wkup_maste; /* GPIO_WKUP + 0x1C */ + u8 reserved8[3]; /* GPIO_WKUP + 0x1D */ + u8 wkup_ival; /* GPIO_WKUP + 0x20 */ + u8 reserved9[3]; /* GPIO_WKUP + 0x21 */ + u8 wkup_istat; /* GPIO_WKUP + 0x24 */ + u8 reserved10[3]; /* GPIO_WKUP + 0x25 */ +}; + +/* XLB Bus control */ +struct mpc52xx_xlb { + u8 reserved[0x40]; + u32 config; /* XLB + 0x40 */ + u32 version; /* XLB + 0x44 */ + u32 status; /* XLB + 0x48 */ + u32 int_enable; /* XLB + 0x4c */ + u32 addr_capture; /* XLB + 0x50 */ + u32 bus_sig_capture; /* XLB + 0x54 */ + u32 addr_timeout; /* XLB + 0x58 */ + u32 data_timeout; /* XLB + 0x5c */ + u32 bus_act_timeout; /* XLB + 0x60 */ + u32 master_pri_enable; /* XLB + 0x64 */ + u32 master_priority; /* XLB + 0x68 */ + u32 base_address; /* XLB + 0x6c */ + u32 snoop_window; /* XLB + 0x70 */ +}; + +#define MPC52xx_XLB_CFG_PLDIS (1 << 31) +#define MPC52xx_XLB_CFG_SNOOP (1 << 15) + +/* Clock Distribution control */ +struct mpc52xx_cdm { + u32 jtag_id; /* CDM + 0x00 reg0 read only */ + u32 rstcfg; /* CDM + 0x04 reg1 read only */ + u32 breadcrumb; /* CDM + 0x08 reg2 */ + + u8 mem_clk_sel; /* CDM + 0x0c reg3 byte0 */ + u8 xlb_clk_sel; /* CDM + 0x0d reg3 byte1 read only */ + u8 ipb_clk_sel; /* CDM + 0x0e reg3 byte2 */ + u8 pci_clk_sel; /* CDM + 0x0f reg3 byte3 */ + + u8 ext_48mhz_en; /* CDM + 0x10 reg4 byte0 */ + u8 fd_enable; /* CDM + 0x11 reg4 byte1 */ + u16 fd_counters; /* CDM + 0x12 reg4 byte2,3 */ + + u32 clk_enables; /* CDM + 0x14 reg5 */ + + u8 osc_disable; /* CDM + 0x18 reg6 byte0 */ + u8 reserved0[3]; /* CDM + 0x19 reg6 byte1,2,3 */ + + u8 ccs_sleep_enable; /* CDM + 0x1c reg7 byte0 */ + u8 osc_sleep_enable; /* CDM + 0x1d reg7 byte1 */ + u8 reserved1; /* CDM + 0x1e reg7 byte2 */ + u8 ccs_qreq_test; /* CDM + 0x1f reg7 byte3 */ + + u8 soft_reset; /* CDM + 0x20 u8 byte0 */ + u8 no_ckstp; /* CDM + 0x21 u8 byte0 */ + u8 reserved2[2]; /* CDM + 0x22 u8 byte1,2,3 */ + + u8 pll_lock; /* CDM + 0x24 reg9 byte0 */ + u8 pll_looselock; /* CDM + 0x25 reg9 byte1 */ + u8 pll_sm_lockwin; /* CDM + 0x26 reg9 byte2 */ + u8 reserved3; /* CDM + 0x27 reg9 byte3 */ + + u16 reserved4; /* CDM + 0x28 reg10 byte0,1 */ + u16 mclken_div_psc1; /* CDM + 0x2a reg10 byte2,3 */ + + u16 reserved5; /* CDM + 0x2c reg11 byte0,1 */ + u16 mclken_div_psc2; /* CDM + 0x2e reg11 byte2,3 */ + + u16 reserved6; /* CDM + 0x30 reg12 byte0,1 */ + u16 mclken_div_psc3; /* CDM + 0x32 reg12 byte2,3 */ + + u16 reserved7; /* CDM + 0x34 reg13 byte0,1 */ + u16 mclken_div_psc6; /* CDM + 0x36 reg13 byte2,3 */ +}; + +#endif /* __ASSEMBLY__ */ + + +/* ========================================================================= */ +/* Prototypes for MPC52xx sysdev */ +/* ========================================================================= */ + +#ifndef __ASSEMBLY__ + +extern void mpc52xx_init_irq(void); +extern unsigned int mpc52xx_get_irq(void); + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_POWERPC_MPC52xx_H__ */ + -- cgit v1.2.3-70-g09d2 From a9b14973a8c42b2aecc968851372203c6567e196 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Thu, 19 Oct 2006 19:52:26 -0500 Subject: [PATCH] Slight refactor of interrupt mapping for FSL parts * Cleaned up interrupt mapping a little by adding a helper function which parses the irq out of the device-tree, and puts it into a resource. * Changed the arch/ppc platform files to specify PHY_POLL, instead of -1 * Changed the fixed phy to use PHY_IGNORE_INTERRUPT * Added ethtool.h and mii.h to phy.h includes Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/fsl_soc.c | 28 +++++++++++----------------- arch/ppc/platforms/83xx/mpc834x_sys.c | 4 ++-- arch/ppc/platforms/85xx/mpc8540_ads.c | 4 ++-- arch/ppc/platforms/85xx/mpc8560_ads.c | 4 ++-- arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 6 +++--- arch/ppc/platforms/85xx/sbc8560.c | 2 +- arch/ppc/platforms/85xx/stx_gp3.c | 2 +- arch/ppc/platforms/85xx/tqm85xx.c | 4 ++-- arch/ppc/platforms/mpc8272ads_setup.c | 6 +++--- arch/ppc/platforms/mpc866ads_setup.c | 4 ++-- drivers/net/phy/fixed.c | 2 +- include/asm-powerpc/prom.h | 7 +++++++ include/linux/phy.h | 3 +++ 13 files changed, 40 insertions(+), 36 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index dbe92ae2033..ad31e56e892 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -146,7 +147,7 @@ static int __init gfar_mdio_of_init(void) } for (k = 0; k < 32; k++) - mdio_data.irq[k] = -1; + mdio_data.irq[k] = PHY_POLL; while ((child = of_get_next_child(np, child)) != NULL) { int irq = irq_of_parse_and_map(child, 0); @@ -177,6 +178,7 @@ static const char *gfar_tx_intr = "tx"; static const char *gfar_rx_intr = "rx"; static const char *gfar_err_intr = "error"; + static int __init gfar_of_init(void) { struct device_node *np; @@ -204,8 +206,7 @@ static int __init gfar_of_init(void) if (ret) goto err; - r[1].start = r[1].end = irq_of_parse_and_map(np, 0); - r[1].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[1]); model = get_property(np, "model", NULL); @@ -214,12 +215,10 @@ static int __init gfar_of_init(void) r[1].name = gfar_tx_intr; r[2].name = gfar_rx_intr; - r[2].start = r[2].end = irq_of_parse_and_map(np, 1); - r[2].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 1, &r[2]); r[3].name = gfar_err_intr; - r[3].start = r[3].end = irq_of_parse_and_map(np, 2); - r[3].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 2, &r[3]); n_res += 2; } @@ -323,8 +322,7 @@ static int __init fsl_i2c_of_init(void) if (ret) goto err; - r[1].start = r[1].end = irq_of_parse_and_map(np, 0); - r[1].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[1]); i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); if (IS_ERR(i2c_dev)) { @@ -459,8 +457,7 @@ static int __init fsl_usb_of_init(void) if (ret) goto err; - r[1].start = r[1].end = irq_of_parse_and_map(np, 0); - r[1].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[1]); usb_dev_mph = platform_device_register_simple("fsl-ehci", i, r, 2); @@ -507,8 +504,7 @@ static int __init fsl_usb_of_init(void) if (ret) goto unreg_mph; - r[1].start = r[1].end = irq_of_parse_and_map(np, 0); - r[1].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[1]); usb_dev_dr = platform_device_register_simple("fsl-ehci", i, r, 2); @@ -591,8 +587,7 @@ static int __init fs_enet_of_init(void) r[2].name = fcc_regs_c; fs_enet_data.fcc_regs_c = r[2].start; - r[3].start = r[3].end = irq_of_parse_and_map(np, 0); - r[3].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[3]); fs_enet_dev = platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4); @@ -754,8 +749,7 @@ static int __init cpm_uart_of_init(void) goto err; r[1].name = scc_pram; - r[2].start = r[2].end = irq_of_parse_and_map(np, 0); - r[2].flags = IORESOURCE_IRQ; + of_irq_to_resource(np, 0, &r[2]); cpm_uart_dev = platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3); diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 3397f0de159..b84f8df325c 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -121,8 +121,8 @@ mpc834x_sys_setup_arch(void) mdata->irq[0] = MPC83xx_IRQ_EXT1; mdata->irq[1] = MPC83xx_IRQ_EXT2; - mdata->irq[2] = -1; - mdata->irq[31] = -1; + mdata->irq[2] = PHY_POLL; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index 4f839da6782..00a3ba57063 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c @@ -92,9 +92,9 @@ mpc8540ads_setup_arch(void) mdata->irq[0] = MPC85xx_IRQ_EXT5; mdata->irq[1] = MPC85xx_IRQ_EXT5; - mdata->irq[2] = -1; + mdata->irq[2] = PHY_POLL; mdata->irq[3] = MPC85xx_IRQ_EXT5; - mdata->irq[31] = -1; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 14ecec7bbed..3a060468dd9 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c @@ -156,9 +156,9 @@ mpc8560ads_setup_arch(void) mdata->irq[0] = MPC85xx_IRQ_EXT5; mdata->irq[1] = MPC85xx_IRQ_EXT5; - mdata->irq[2] = -1; + mdata->irq[2] = PHY_POLL; mdata->irq[3] = MPC85xx_IRQ_EXT5; - mdata->irq[31] = -1; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 5ce0f69c1db..2d59eb776c9 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -451,9 +451,9 @@ mpc85xx_cds_setup_arch(void) mdata->irq[0] = MPC85xx_IRQ_EXT5; mdata->irq[1] = MPC85xx_IRQ_EXT5; - mdata->irq[2] = -1; - mdata->irq[3] = -1; - mdata->irq[31] = -1; + mdata->irq[2] = PHY_POLL; + mdata->irq[3] = PHY_POLL; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 764d580ff53..1d10ab98f66 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c @@ -129,7 +129,7 @@ sbc8560_setup_arch(void) mdata->irq[25] = MPC85xx_IRQ_EXT6; mdata->irq[26] = MPC85xx_IRQ_EXT7; - mdata->irq[31] = -1; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 4bb18ab2767..b1f5b737c70 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c @@ -123,7 +123,7 @@ gp3_setup_arch(void) mdata->irq[2] = MPC85xx_IRQ_EXT5; mdata->irq[4] = MPC85xx_IRQ_EXT5; - mdata->irq[31] = -1; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c index dd45f2e1844..4ee2bd156dc 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.c +++ b/arch/ppc/platforms/85xx/tqm85xx.c @@ -137,9 +137,9 @@ tqm85xx_setup_arch(void) mdata->irq[0] = MPC85xx_IRQ_EXT8; mdata->irq[1] = MPC85xx_IRQ_EXT8; - mdata->irq[2] = -1; + mdata->irq[2] = PHY_POLL; mdata->irq[3] = MPC85xx_IRQ_EXT8; - mdata->irq[31] = -1; + mdata->irq[31] = PHY_POLL; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c index 1f9ea36837b..0bc06768cf2 100644 --- a/arch/ppc/platforms/mpc8272ads_setup.c +++ b/arch/ppc/platforms/mpc8272ads_setup.c @@ -266,10 +266,10 @@ static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev, int idx) { m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT; - m82xx_mii_bb_pdata.irq[1] = -1; - m82xx_mii_bb_pdata.irq[2] = -1; + m82xx_mii_bb_pdata.irq[1] = PHY_POLL; + m82xx_mii_bb_pdata.irq[2] = PHY_POLL; m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT; - m82xx_mii_bb_pdata.irq[31] = -1; + m82xx_mii_bb_pdata.irq[31] = PHY_POLL; m82xx_mii_bb_pdata.mdio_dat.offset = diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c index e95d2c11174..8a0c07eb444 100644 --- a/arch/ppc/platforms/mpc866ads_setup.c +++ b/arch/ppc/platforms/mpc866ads_setup.c @@ -361,7 +361,7 @@ int __init mpc866ads_init(void) fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; /* No PHY interrupt line here */ - fmpi->irq[0xf] = -1; + fmpi->irq[0xf] = PHY_POLL; /* Since either of the uarts could be used as console, they need to ready */ #ifdef CONFIG_SERIAL_CPM_SMC1 @@ -380,7 +380,7 @@ int __init mpc866ads_init(void) fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; /* No PHY interrupt line here */ - fmpi->irq[0xf] = -1; + fmpi->irq[0xf] = PHY_POLL; return 0; } diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c index f14e99276db..096d4a100bf 100644 --- a/drivers/net/phy/fixed.c +++ b/drivers/net/phy/fixed.c @@ -254,7 +254,7 @@ static int fixed_mdio_register_device(int number, int speed, int duplex) goto device_create_fail; } - phydev->irq = -1; + phydev->irq = PHY_IGNORE_INTERRUPT; phydev->dev.bus = &mdio_bus_type; if(number) diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 52462976933..39f04ef96f3 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -17,6 +17,7 @@ */ #include #include +#include #include /* Definitions used by the flattened device tree */ @@ -331,6 +332,12 @@ extern int of_irq_map_one(struct device_node *device, int index, struct pci_dev; extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); +static inline void of_irq_to_resource(struct device_node *dev, int index, struct resource *r) +{ + r->start = r->end = irq_of_parse_and_map(dev, index); + r->flags = IORESOURCE_IRQ; +} + #endif /* __KERNEL__ */ #endif /* _POWERPC_PROM_H */ diff --git a/include/linux/phy.h b/include/linux/phy.h index 9447a57ee8a..892d6abe57e 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -20,6 +20,9 @@ #include #include +#include +#include +#include #define PHY_BASIC_FEATURES (SUPPORTED_10baseT_Half | \ SUPPORTED_10baseT_Full | \ -- cgit v1.2.3-70-g09d2 From 66a91e9c0ab62ea938afaba7352741d8c554a589 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Tue, 7 Nov 2006 16:57:22 -0600 Subject: [PATCH] of_irq_to_resource now returns the virq Mostly this is to allow for error checking (check the return for NO_IRQ) Added a check that the resource is non-NULL, too. Signed-off-by: Andrew Fleming Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- include/asm-powerpc/prom.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 39f04ef96f3..1fd7a2253e3 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -332,10 +332,18 @@ extern int of_irq_map_one(struct device_node *device, int index, struct pci_dev; extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); -static inline void of_irq_to_resource(struct device_node *dev, int index, struct resource *r) +static inline int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) { - r->start = r->end = irq_of_parse_and_map(dev, index); - r->flags = IORESOURCE_IRQ; + int irq = irq_of_parse_and_map(dev, index); + + /* Only dereference the resource if both the + * resource and the irq are valid. */ + if (r && irq != NO_IRQ) { + r->start = r->end = irq; + r->flags = IORESOURCE_IRQ; + } + + return irq; } -- cgit v1.2.3-70-g09d2 From fc9e8b4e275b6882cb537154c8fc7cde3692eea0 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 9 Nov 2006 15:42:44 -0600 Subject: [PATCH] Optimize qe_brg struct to use an array The qe_brg structure manually defined each of the 16 BRG registers, which made any code that used them cumbersome. This patch replaces the fields with a single 16-element array. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/qe_lib/qe.c | 3 +-- include/asm-powerpc/immap_qe.h | 17 +---------------- 2 files changed, 2 insertions(+), 18 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 2bae632d3ad..812c87c73bb 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -175,8 +175,7 @@ void qe_setbrg(u32 brg, u32 rate) u32 divisor, tempval; int div16 = 0; - bp = &qe_immr->brg.brgc1; - bp += brg; + bp = &qe_immr->brg.brgc[brg]; divisor = (get_brg_clk() / rate); if (divisor > QE_BRGC_DIVISOR_MAX + 1) { diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h index ce12f85fff9..9fdd0491f6a 100644 --- a/include/asm-powerpc/immap_qe.h +++ b/include/asm-powerpc/immap_qe.h @@ -136,22 +136,7 @@ struct qe_timers { /* BRG */ struct qe_brg { - __be32 brgc1; /* BRG1 configuration register */ - __be32 brgc2; /* BRG2 configuration register */ - __be32 brgc3; /* BRG3 configuration register */ - __be32 brgc4; /* BRG4 configuration register */ - __be32 brgc5; /* BRG5 configuration register */ - __be32 brgc6; /* BRG6 configuration register */ - __be32 brgc7; /* BRG7 configuration register */ - __be32 brgc8; /* BRG8 configuration register */ - __be32 brgc9; /* BRG9 configuration register */ - __be32 brgc10; /* BRG10 configuration register */ - __be32 brgc11; /* BRG11 configuration register */ - __be32 brgc12; /* BRG12 configuration register */ - __be32 brgc13; /* BRG13 configuration register */ - __be32 brgc14; /* BRG14 configuration register */ - __be32 brgc15; /* BRG15 configuration register */ - __be32 brgc16; /* BRG16 configuration register */ + __be32 brgc[16]; /* BRG configuration registers */ u8 res0[0x40]; } __attribute__ ((packed)); -- cgit v1.2.3-70-g09d2 From 19a79859e168640f8e16d7b216d211c1c52b687a Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sat, 11 Nov 2006 10:53:19 +0100 Subject: [PATCH] ppc: Fix io.h for config with CONFIG_PCI not set When CONFIG_PCI option is not set, the variables pci_dram_offset, isa_io_base and isa_mem_base are not defined. Currently, the test is handled in each platform header. This patch moves the test in io.h once and for all. Signed-off-by: Sylvain Munaut Signed-off-by: Paul Mackerras --- include/asm-powerpc/mpc85xx.h | 8 -------- include/asm-ppc/io.h | 8 +------- include/asm-ppc/mpc52xx.h | 11 ----------- include/asm-ppc/mpc83xx.h | 8 -------- include/asm-ppc/mpc85xx.h | 8 -------- 5 files changed, 1 insertion(+), 42 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/mpc85xx.h b/include/asm-powerpc/mpc85xx.h index ccdb8a21138..54142997a58 100644 --- a/include/asm-powerpc/mpc85xx.h +++ b/include/asm-powerpc/mpc85xx.h @@ -31,14 +31,6 @@ #include #endif -#define _IO_BASE isa_io_base -#define _ISA_MEM_BASE isa_mem_base -#ifdef CONFIG_PCI -#define PCI_DRAM_OFFSET pci_dram_offset -#else -#define PCI_DRAM_OFFSET 0 -#endif - /* Let modules/drivers get at CCSRBAR */ extern phys_addr_t get_ccsrbar(void); diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index a4c411b753e..b744baf9e20 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -26,17 +26,11 @@ #if defined(CONFIG_4xx) #include -#elif defined(CONFIG_PPC_MPC52xx) -#include #elif defined(CONFIG_8xx) #include #elif defined(CONFIG_8260) #include -#elif defined(CONFIG_83xx) -#include -#elif defined(CONFIG_85xx) -#include -#elif defined(CONFIG_APUS) +#elif defined(CONFIG_APUS) || !defined(CONFIG_PCI) #define _IO_BASE 0 #define _ISA_MEM_BASE 0 #define PCI_DRAM_OFFSET 0 diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h index 64c8874618d..d9d21aa68ba 100644 --- a/include/asm-ppc/mpc52xx.h +++ b/include/asm-ppc/mpc52xx.h @@ -29,17 +29,6 @@ struct pt_regs; #endif /* __ASSEMBLY__ */ -#ifdef CONFIG_PCI -#define _IO_BASE isa_io_base -#define _ISA_MEM_BASE isa_mem_base -#define PCI_DRAM_OFFSET pci_dram_offset -#else -#define _IO_BASE 0 -#define _ISA_MEM_BASE 0 -#define PCI_DRAM_OFFSET 0 -#endif - - /* ======================================================================== */ /* PPC Sys devices definition */ /* ======================================================================== */ diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h index 02ed2c32571..c3061972309 100644 --- a/include/asm-ppc/mpc83xx.h +++ b/include/asm-ppc/mpc83xx.h @@ -25,14 +25,6 @@ #include #endif -#define _IO_BASE isa_io_base -#define _ISA_MEM_BASE isa_mem_base -#ifdef CONFIG_PCI -#define PCI_DRAM_OFFSET pci_dram_offset -#else -#define PCI_DRAM_OFFSET 0 -#endif - /* * The "residual" board information structure the boot loader passes * into the kernel. diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h index 9b4851199c7..d7e4a79d77f 100644 --- a/include/asm-ppc/mpc85xx.h +++ b/include/asm-ppc/mpc85xx.h @@ -44,14 +44,6 @@ #include #endif -#define _IO_BASE isa_io_base -#define _ISA_MEM_BASE isa_mem_base -#ifdef CONFIG_PCI -#define PCI_DRAM_OFFSET pci_dram_offset -#else -#define PCI_DRAM_OFFSET 0 -#endif - /* * The "residual" board information structure the boot loader passes * into the kernel. -- cgit v1.2.3-70-g09d2 From edb2d97eb57b7a21c9256260562de6a65dda86cc Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 10 Oct 2006 08:01:21 -0600 Subject: PCI: Replace HAVE_ARCH_PCI_MWI with PCI_DISABLE_MWI pSeries is the only architecture left using HAVE_ARCH_PCI_MWI and it's really inappropriate for its needs. It really wants to disable MWI altogether. So here are a pair of stub implementations for pci_set_mwi and pci_clear_mwi. Also rename pci_generic_prep_mwi to pci_set_cacheline_size since that better reflects what it does. Signed-off-by: Matthew Wilcox Cc: Paul Mackerras Acked-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 31 ++++++++++++++++++------------- include/asm-powerpc/pci.h | 20 +++++++------------- 2 files changed, 25 insertions(+), 26 deletions(-) (limited to 'include/asm-powerpc') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bc88c30a418..427991741cf 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -875,7 +875,17 @@ pci_set_master(struct pci_dev *dev) pcibios_set_master(dev); } -#ifndef HAVE_ARCH_PCI_MWI +#ifdef PCI_DISABLE_MWI +int pci_set_mwi(struct pci_dev *dev) +{ + return 0; +} + +void pci_clear_mwi(struct pci_dev *dev) +{ +} + +#else #ifndef PCI_CACHE_LINE_BYTES #define PCI_CACHE_LINE_BYTES L1_CACHE_BYTES @@ -886,17 +896,17 @@ pci_set_master(struct pci_dev *dev) u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4; /** - * pci_generic_prep_mwi - helper function for pci_set_mwi - * @dev: the PCI device for which MWI is enabled + * pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed + * @dev: the PCI device for which MWI is to be enabled * - * Helper function for generic implementation of pcibios_prep_mwi - * function. Originally copied from drivers/net/acenic.c. + * Helper function for pci_set_mwi. + * Originally copied from drivers/net/acenic.c. * Copyright 1998-2001 by Jes Sorensen, . * * RETURNS: An appropriate -ERRNO error value on error, or zero for success. */ static int -pci_generic_prep_mwi(struct pci_dev *dev) +pci_set_cacheline_size(struct pci_dev *dev) { u8 cacheline_size; @@ -922,7 +932,6 @@ pci_generic_prep_mwi(struct pci_dev *dev) return -EINVAL; } -#endif /* !HAVE_ARCH_PCI_MWI */ /** * pci_set_mwi - enables memory-write-invalidate PCI transaction @@ -940,12 +949,7 @@ pci_set_mwi(struct pci_dev *dev) int rc; u16 cmd; -#ifdef HAVE_ARCH_PCI_MWI - rc = pcibios_prep_mwi(dev); -#else - rc = pci_generic_prep_mwi(dev); -#endif - + rc = pci_set_cacheline_size(dev); if (rc) return rc; @@ -976,6 +980,7 @@ pci_clear_mwi(struct pci_dev *dev) pci_write_config_word(dev, PCI_COMMAND, cmd); } } +#endif /* ! PCI_DISABLE_MWI */ /** * pci_intx - enables/disables PCI INTx for device dev diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index 46afd29b904..721c97f09b2 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h @@ -62,19 +62,13 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) } #ifdef CONFIG_PPC64 -#define HAVE_ARCH_PCI_MWI 1 -static inline int pcibios_prep_mwi(struct pci_dev *dev) -{ - /* - * We would like to avoid touching the cacheline size or MWI bit - * but we cant do that with the current pcibios_prep_mwi - * interface. pSeries firmware sets the cacheline size (which is not - * the cpu cacheline size in all cases) and hardware treats MWI - * the same as memory write. So we dont touch the cacheline size - * here and allow the generic code to set the MWI bit. - */ - return 0; -} + +/* + * We want to avoid touching the cacheline size or MWI bit. + * pSeries firmware sets the cacheline size (which is not the cpu cacheline + * size in all cases) and hardware treats MWI the same as memory write. + */ +#define PCI_DISABLE_MWI extern struct dma_mapping_ops pci_dma_ops; -- cgit v1.2.3-70-g09d2 From c6dbaef22a2f78700e242915a13218dd780c89ff Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:18:39 +1100 Subject: Driver core: add dev_archdata to struct device Add arch specific dev_archdata to struct device Adds an arch specific struct dev_arch to struct device. This enables architecture to add specific fields to every device in the system, like DMA operation pointers, NUMA node ID, firmware specific data, etc... Signed-off-by: Benjamin Herrenschmidt Acked-by: Andi Kleen Acked-By: David Howells Signed-off-by: Greg Kroah-Hartman --- include/asm-alpha/device.h | 7 +++++++ include/asm-arm/device.h | 7 +++++++ include/asm-arm26/device.h | 7 +++++++ include/asm-avr32/device.h | 7 +++++++ include/asm-cris/device.h | 7 +++++++ include/asm-frv/device.h | 7 +++++++ include/asm-generic/device.h | 12 ++++++++++++ include/asm-h8300/device.h | 7 +++++++ include/asm-i386/device.h | 7 +++++++ include/asm-ia64/device.h | 7 +++++++ include/asm-m32r/device.h | 7 +++++++ include/asm-m68k/device.h | 7 +++++++ include/asm-m68knommu/device.h | 7 +++++++ include/asm-mips/device.h | 7 +++++++ include/asm-parisc/device.h | 7 +++++++ include/asm-powerpc/device.h | 7 +++++++ include/asm-ppc/device.h | 7 +++++++ include/asm-s390/device.h | 7 +++++++ include/asm-sh/device.h | 7 +++++++ include/asm-sh64/device.h | 7 +++++++ include/asm-sparc/device.h | 7 +++++++ include/asm-sparc64/device.h | 7 +++++++ include/asm-um/device.h | 7 +++++++ include/asm-v850/device.h | 7 +++++++ include/asm-x86_64/device.h | 7 +++++++ include/asm-xtensa/device.h | 7 +++++++ include/linux/device.h | 3 +++ 27 files changed, 190 insertions(+) create mode 100644 include/asm-alpha/device.h create mode 100644 include/asm-arm/device.h create mode 100644 include/asm-arm26/device.h create mode 100644 include/asm-avr32/device.h create mode 100644 include/asm-cris/device.h create mode 100644 include/asm-frv/device.h create mode 100644 include/asm-generic/device.h create mode 100644 include/asm-h8300/device.h create mode 100644 include/asm-i386/device.h create mode 100644 include/asm-ia64/device.h create mode 100644 include/asm-m32r/device.h create mode 100644 include/asm-m68k/device.h create mode 100644 include/asm-m68knommu/device.h create mode 100644 include/asm-mips/device.h create mode 100644 include/asm-parisc/device.h create mode 100644 include/asm-powerpc/device.h create mode 100644 include/asm-ppc/device.h create mode 100644 include/asm-s390/device.h create mode 100644 include/asm-sh/device.h create mode 100644 include/asm-sh64/device.h create mode 100644 include/asm-sparc/device.h create mode 100644 include/asm-sparc64/device.h create mode 100644 include/asm-um/device.h create mode 100644 include/asm-v850/device.h create mode 100644 include/asm-x86_64/device.h create mode 100644 include/asm-xtensa/device.h (limited to 'include/asm-powerpc') diff --git a/include/asm-alpha/device.h b/include/asm-alpha/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-alpha/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-arm/device.h b/include/asm-arm/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-arm/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-arm26/device.h b/include/asm-arm26/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-arm26/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-avr32/device.h b/include/asm-avr32/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-avr32/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-cris/device.h b/include/asm-cris/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-cris/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-frv/device.h b/include/asm-frv/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-frv/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-generic/device.h b/include/asm-generic/device.h new file mode 100644 index 00000000000..c17c9600f22 --- /dev/null +++ b/include/asm-generic/device.h @@ -0,0 +1,12 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#ifndef _ASM_GENERIC_DEVICE_H +#define _ASM_GENERIC_DEVICE_H + +struct dev_archdata { +}; + +#endif /* _ASM_GENERIC_DEVICE_H */ diff --git a/include/asm-h8300/device.h b/include/asm-h8300/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-h8300/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-i386/device.h b/include/asm-i386/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-i386/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-ia64/device.h b/include/asm-ia64/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-ia64/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-m32r/device.h b/include/asm-m32r/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-m32r/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-m68k/device.h b/include/asm-m68k/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-m68k/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-m68knommu/device.h b/include/asm-m68knommu/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-m68knommu/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-mips/device.h b/include/asm-mips/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-mips/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-parisc/device.h b/include/asm-parisc/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-parisc/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-powerpc/device.h b/include/asm-powerpc/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-powerpc/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-ppc/device.h b/include/asm-ppc/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-ppc/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-s390/device.h b/include/asm-s390/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-s390/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-sh/device.h b/include/asm-sh/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-sh/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-sh64/device.h b/include/asm-sh64/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-sh64/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-sparc/device.h b/include/asm-sparc/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-sparc/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-sparc64/device.h b/include/asm-sparc64/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-sparc64/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-um/device.h b/include/asm-um/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-um/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-v850/device.h b/include/asm-v850/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-v850/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-x86_64/device.h b/include/asm-x86_64/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-x86_64/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/asm-xtensa/device.h b/include/asm-xtensa/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/include/asm-xtensa/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include + diff --git a/include/linux/device.h b/include/linux/device.h index 00b29e0c5ce..5b54d756cd5 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -21,6 +21,7 @@ #include #include #include +#include #define DEVICE_NAME_SIZE 50 #define DEVICE_NAME_HALF __stringify(20) /* Less than half to accommodate slop */ @@ -383,6 +384,8 @@ struct device { struct dma_coherent_mem *dma_mem; /* internal for coherent mem override */ + /* arch specific additions */ + struct dev_archdata archdata; /* class_device migration path */ struct list_head node; -- cgit v1.2.3-70-g09d2 From 879178cfbe56baa42ee73b9668816872c97d8ccd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:21:58 -0800 Subject: [NET]: POWERPC checksum annotations and cleanups. * sanitize prototypes, annotate * kill useless shifts Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/asm-powerpc/checksum.h | 59 +++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 38 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/checksum.h b/include/asm-powerpc/checksum.h index 609ecbbd721..7cdf358337c 100644 --- a/include/asm-powerpc/checksum.h +++ b/include/asm-powerpc/checksum.h @@ -14,17 +14,16 @@ * which always checksum on 4 octet boundaries. ihl is the number * of 32-bit words and is always >= 5. */ -extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); +extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); /* * computes the checksum of the TCP/UDP pseudo-header * returns a 16-bit checksum, already complemented */ -extern unsigned short csum_tcpudp_magic(unsigned long saddr, - unsigned long daddr, +extern __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, - unsigned int sum); + __wsum sum); /* * computes the checksum of a memory block at buff, length len, @@ -38,8 +37,7 @@ extern unsigned short csum_tcpudp_magic(unsigned long saddr, * * it's best to have buff aligned on a 32-bit boundary */ -extern unsigned int csum_partial(const unsigned char * buff, int len, - unsigned int sum); +extern __wsum csum_partial(const void *buff, int len, __wsum sum); /* * Computes the checksum of a memory block at src, length len, @@ -51,20 +49,15 @@ extern unsigned int csum_partial(const unsigned char * buff, int len, * Like csum_partial, this must be called with even lengths, * except for the last fragment. */ -extern unsigned int csum_partial_copy_generic(const char *src, char *dst, - int len, unsigned int sum, +extern __wsum csum_partial_copy_generic(const void *src, void *dst, + int len, __wsum sum, int *src_err, int *dst_err); /* * the same as csum_partial, but copies from src to dst while it * checksums. */ -unsigned int csum_partial_copy_nocheck(const char *src, - char *dst, - int len, - unsigned int sum); - #define csum_partial_copy_from_user(src, dst, len, sum, errp) \ - csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL) + csum_partial_copy_generic((__force const void *)(src), (dst), (len), (sum), (errp), NULL) #define csum_partial_copy_nocheck(src, dst, len, sum) \ csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL) @@ -74,7 +67,7 @@ unsigned int csum_partial_copy_nocheck(const char *src, * turns a 32-bit partial checksum (e.g. from csum_partial) into a * 1's complement 16-bit checksum. */ -static inline unsigned int csum_fold(unsigned int sum) +static inline __sum16 csum_fold(__wsum sum) { unsigned int tmp; @@ -83,41 +76,32 @@ static inline unsigned int csum_fold(unsigned int sum) /* if there is a carry from adding the two 16-bit halves, it will carry from the lower half into the upper half, giving us the correct sum in the upper half. */ - sum = ~(sum + tmp) >> 16; - return sum; + return (__force __sum16)(~((__force u32)sum + tmp) >> 16); } /* * this routine is used for miscellaneous IP-like checksums, mainly * in icmp.c */ -static inline unsigned short ip_compute_csum(unsigned char * buff, int len) +static inline __sum16 ip_compute_csum(const void *buff, int len) { return csum_fold(csum_partial(buff, len, 0)); } -#ifdef __powerpc64__ -static inline u32 csum_tcpudp_nofold(u32 saddr, - u32 daddr, +static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, - unsigned int sum) + __wsum sum) { - unsigned long s = sum; +#ifdef __powerpc64__ + unsigned long s = (__force u32)sum; - s += saddr; - s += daddr; - s += (proto << 16) + len; + s += (__force u32)saddr; + s += (__force u32)daddr; + s += proto + len; s += (s >> 32); - return (u32) s; -} + return (__force __wsum) s; #else -static inline unsigned long csum_tcpudp_nofold(unsigned long saddr, - unsigned long daddr, - unsigned short len, - unsigned short proto, - unsigned int sum) -{ __asm__("\n\ addc %0,%0,%1 \n\ adde %0,%0,%2 \n\ @@ -125,10 +109,9 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr, addze %0,%0 \n\ " : "=r" (sum) - : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum)); - return sum; -} - + : "r" (daddr), "r"(saddr), "r"(proto + len), "0"(sum)); + return sum; #endif +} #endif /* __KERNEL__ */ #endif -- cgit v1.2.3-70-g09d2 From f90bb153b1493719d18b4529a46ebfe43220ea6c Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:24:51 +1100 Subject: [POWERPC] Make pci_read_irq_line the default This patch reworks the way IRQs are fixed up on PCI for arch powerpc. It makes pci_read_irq_line() called by default in the PCI code for devices that are probed, and add an optional per-device fixup in ppc_md for platforms that really need to correct what they obtain from pci_read_irq_line(). It also removes ppc_md.irq_bus_setup which was only used by pSeries and should not be needed anymore. I've also removed the pSeries s7a workaround as it can't work with the current interrupt code anyway. I'm trying to get one of these machines working so I can test a proper fix for that problem. I also haven't updated the old-style fixup code from 85xx_cds.c because it's actually buggy :) It assigns pci_dev->irq hard coded numbers which is no good with the new IRQ mapping code. It should at least use irq_create_mapping(NULL, hard_coded_number); and possibly also set_irq_type() to set them as level low. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_32.c | 10 +++++ arch/powerpc/kernel/pci_64.c | 8 +++- arch/powerpc/platforms/82xx/mpc82xx_ads.c | 13 ------- arch/powerpc/platforms/83xx/mpc834x_itx.c | 3 -- arch/powerpc/platforms/83xx/mpc834x_sys.c | 3 -- arch/powerpc/platforms/83xx/mpc83xx.h | 1 - arch/powerpc/platforms/83xx/pci.c | 9 ----- arch/powerpc/platforms/85xx/mpc85xx_ads.c | 11 ------ arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | 10 ----- arch/powerpc/platforms/cell/setup.c | 9 ----- arch/powerpc/platforms/chrp/chrp.h | 1 - arch/powerpc/platforms/chrp/pci.c | 9 ----- arch/powerpc/platforms/chrp/setup.c | 1 - arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | 16 +++----- arch/powerpc/platforms/maple/maple.h | 2 +- arch/powerpc/platforms/maple/pci.c | 47 +++++++++-------------- arch/powerpc/platforms/maple/setup.c | 2 +- arch/powerpc/platforms/pasemi/pasemi.h | 1 - arch/powerpc/platforms/pasemi/pci.c | 8 ---- arch/powerpc/platforms/pasemi/setup.c | 1 - arch/powerpc/platforms/powermac/pci.c | 35 +++++++---------- arch/powerpc/platforms/powermac/pmac.h | 2 +- arch/powerpc/platforms/powermac/setup.c | 2 +- arch/powerpc/platforms/pseries/pci.c | 35 ----------------- arch/powerpc/platforms/pseries/setup.c | 1 - include/asm-powerpc/machdep.h | 2 +- include/asm-powerpc/ppc-pci.h | 1 - 27 files changed, 59 insertions(+), 184 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 0d9ff72e285..853ecef8178 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -1338,6 +1339,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) struct pci_controller *hose = (struct pci_controller *) bus->sysdata; unsigned long io_offset; struct resource *res; + struct pci_dev *dev; int i; io_offset = (unsigned long)hose->io_base_virt - isa_io_base; @@ -1390,8 +1392,16 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) } } + /* Platform specific bus fixups */ if (ppc_md.pcibios_fixup_bus) ppc_md.pcibios_fixup_bus(bus); + + /* Read default IRQs and fixup if necessary */ + list_for_each_entry(dev, &bus->devices, bus_list) { + pci_read_irq_line(dev); + if (ppc_md.pci_irq_fixup) + ppc_md.pci_irq_fixup(dev); + } } char __init *pcibios_setup(char *str) diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 80ae9ea15cd..9a6bb80a8cd 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -1215,8 +1215,12 @@ static void __devinit do_bus_setup(struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) ppc_md.iommu_dev_setup(dev); - if (ppc_md.irq_bus_setup) - ppc_md.irq_bus_setup(bus); + /* Read default IRQs and fixup if necessary */ + list_for_each_entry(dev, &bus->devices, bus_list) { + pci_read_irq_line(dev); + if (ppc_md.pci_irq_fixup) + ppc_md.pci_irq_fixup(dev); + } } void __devinit pcibios_fixup_bus(struct pci_bus *bus) diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c index bb9acbb9817..ea880f1f0dc 100644 --- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c +++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c @@ -515,16 +515,6 @@ static int m82xx_pci_exclude_device(u_char bus, u_char devfn) return PCIBIOS_SUCCESSFUL; } -static void -__init mpc82xx_pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - - for_each_pci_dev(dev) { - pci_read_irq_line(dev); - } -} - void __init add_bridge(struct device_node *np) { int len; @@ -597,9 +587,6 @@ static void __init mpc82xx_ads_setup_arch(void) add_bridge(np); of_node_put(np); - ppc_md.pci_map_irq = NULL; - ppc_md.pcibios_fixup = mpc82xx_pcibios_fixup; - ppc_md.pcibios_fixup_bus = NULL; #endif #ifdef CONFIG_ROOT_NFS diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c index e2bcaaf6b32..314c42ac604 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c @@ -118,7 +118,4 @@ define_machine(mpc834x_itx) { .time_init = mpc83xx_time_init, .calibrate_decr = generic_calibrate_decr, .progress = udbg_progress, -#ifdef CONFIG_PCI - .pcibios_fixup = mpc83xx_pcibios_fixup, -#endif }; diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c index 677196187a4..80b735a414d 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_sys.c +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c @@ -137,7 +137,4 @@ define_machine(mpc834x_sys) { .time_init = mpc83xx_time_init, .calibrate_decr = generic_calibrate_decr, .progress = udbg_progress, -#ifdef CONFIG_PCI - .pcibios_fixup = mpc83xx_pcibios_fixup, -#endif }; diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 2c82bca9bfb..01cae106912 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h @@ -11,7 +11,6 @@ extern int add_bridge(struct device_node *dev); extern int mpc83xx_exclude_device(u_char bus, u_char devfn); -extern void mpc83xx_pcibios_fixup(void); extern void mpc83xx_restart(char *cmd); extern long mpc83xx_time_init(void); diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index 4557ac5255c..9c365055514 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c @@ -45,15 +45,6 @@ int mpc83xx_exclude_device(u_char bus, u_char devfn) return PCIBIOS_SUCCESSFUL; } -void __init mpc83xx_pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - - /* map all the PCI irqs */ - for_each_pci_dev(dev) - pci_read_irq_line(dev); -} - int __init add_bridge(struct device_node *dev) { int len; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index d3e669d69c7..bda2e55e6c4 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -53,15 +53,6 @@ mpc85xx_exclude_device(u_char bus, u_char devfn) else return PCIBIOS_SUCCESSFUL; } - -void __init -mpc85xx_pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - - for_each_pci_dev(dev) - pci_read_irq_line(dev); -} #endif /* CONFIG_PCI */ #ifdef CONFIG_CPM2 @@ -253,8 +244,6 @@ static void __init mpc85xx_ads_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) add_bridge(np); - - ppc_md.pcibios_fixup = mpc85xx_pcibios_fixup; ppc_md.pci_exclude_device = mpc85xx_exclude_device; #endif diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 1a1c226ad4d..f4dd5f2f8a2 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -398,15 +398,6 @@ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m) } -void __init mpc86xx_hpcn_pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - - for_each_pci_dev(dev) - pci_read_irq_line(dev); -} - - /* * Called very early, device-tree isn't unflattened */ @@ -461,7 +452,6 @@ define_machine(mpc86xx_hpcn) { .setup_arch = mpc86xx_hpcn_setup_arch, .init_IRQ = mpc86xx_hpcn_init_irq, .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, - .pcibios_fixup = mpc86xx_hpcn_pcibios_fixup, .get_irq = mpic_get_irq, .restart = mpc86xx_restart, .time_init = mpc86xx_time_init, diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 22c228a49c3..1944bb413f0 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -80,14 +80,6 @@ static void cell_progress(char *s, unsigned short hex) printk("*** %04x : %s\n", hex, s ? s : ""); } -static void __init cell_pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - - for_each_pci_dev(dev) - pci_read_irq_line(dev); -} - static void __init cell_init_irq(void) { iic_init_IRQ(); @@ -180,7 +172,6 @@ define_machine(cell) { .check_legacy_ioport = cell_check_legacy_ioport, .progress = cell_progress, .init_IRQ = cell_init_irq, - .pcibios_fixup = cell_pcibios_fixup, #ifdef CONFIG_KEXEC .machine_kexec = default_machine_kexec, .machine_kexec_prepare = default_machine_kexec_prepare, diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h index 996c28744e9..63f0aee4c15 100644 --- a/arch/powerpc/platforms/chrp/chrp.h +++ b/arch/powerpc/platforms/chrp/chrp.h @@ -9,4 +9,3 @@ extern long chrp_time_init(void); extern void chrp_find_bridges(void); extern void chrp_event_scan(unsigned long); -extern void chrp_pcibios_fixup(void); diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 0f4340506c7..ddb4a116ea8 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -156,15 +156,6 @@ hydra_init(void) return 1; } -void __init -chrp_pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - - for_each_pci_dev(dev) - pci_read_irq_line(dev); -} - #define PRG_CL_RESET_VALID 0x00010000 static void __init diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 49b8dabcbc9..e6807d6d75b 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -600,7 +600,6 @@ define_machine(chrp) { .init = chrp_init2, .show_cpuinfo = chrp_show_cpuinfo, .init_IRQ = chrp_init_IRQ, - .pcibios_fixup = chrp_pcibios_fixup, .restart = rtas_restart, .power_off = rtas_power_off, .halt = rtas_halt, diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index bdb475c65cb..c6113c39009 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -89,7 +89,7 @@ u8 find_slot_by_devfn(unsigned int *interrupt_map, unsigned int devfn) /* * Scans the interrupt map for pci device */ -void mpc7448_hpc2_fixup_irq(struct pci_dev *dev) +void __devinit mpc7448_hpc2_fixup_irq(struct pci_dev *dev) { struct pci_controller *hose; struct device_node *node; @@ -117,19 +117,13 @@ void mpc7448_hpc2_fixup_irq(struct pci_dev *dev) pin = 1; pin--; dev->irq = interrupt[slot*4*7 + pin*7 + 5]; + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + DBG("TSI_PCI: dev->irq = 0x%x\n", dev->irq); } /* temporary pci irq map fixup*/ -void __init mpc7448_hpc2_pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - for_each_pci_dev(dev) { - mpc7448_hpc2_fixup_irq(dev); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } -} - static void __init mpc7448_hpc2_setup_arch(void) { struct device_node *cpu; @@ -300,7 +294,7 @@ define_machine(mpc7448_hpc2){ .init_IRQ = mpc7448_hpc2_init_IRQ, .show_cpuinfo = mpc7448_hpc2_show_cpuinfo, .get_irq = mpic_get_irq, - .pcibios_fixup = mpc7448_hpc2_pcibios_fixup, + .pci_irq_fixup = mpc7448_hpc2_fixup_irq, .restart = mpc7448_hpc2_restart, .calibrate_decr = generic_calibrate_decr, .machine_check_exception= mpc7448_machine_check_exception, diff --git a/arch/powerpc/platforms/maple/maple.h b/arch/powerpc/platforms/maple/maple.h index 0657c579b84..c6911ddc479 100644 --- a/arch/powerpc/platforms/maple/maple.h +++ b/arch/powerpc/platforms/maple/maple.h @@ -8,5 +8,5 @@ extern void maple_get_rtc_time(struct rtc_time *tm); extern unsigned long maple_get_boot_time(void); extern void maple_calibrate_decr(void); extern void maple_pci_init(void); -extern void maple_pcibios_fixup(void); +extern void maple_pci_irq_fixup(struct pci_dev *dev); extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel); diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 63b4d1bff35..3a32deda765 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -502,38 +502,29 @@ static int __init add_bridge(struct device_node *dev) } -void __init maple_pcibios_fixup(void) +void __devinit maple_pci_irq_fixup(struct pci_dev *dev) { - struct pci_dev *dev = NULL; - - DBG(" -> maple_pcibios_fixup\n"); - - for_each_pci_dev(dev) { - /* Fixup IRQ for PCIe host */ - if (u4_pcie != NULL && dev->bus->number == 0 && - pci_bus_to_host(dev->bus) == u4_pcie) { - printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n"); - dev->irq = irq_create_mapping(NULL, 1); - if (dev->irq != NO_IRQ) - set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW); - continue; - } - - /* Hide AMD8111 IDE interrupt when in legacy mode so - * the driver calls pci_get_legacy_ide_irq() - */ - if (dev->vendor == PCI_VENDOR_ID_AMD && - dev->device == PCI_DEVICE_ID_AMD_8111_IDE && - (dev->class & 5) != 5) { - dev->irq = NO_IRQ; - continue; - } + DBG(" -> maple_pci_irq_fixup\n"); + + /* Fixup IRQ for PCIe host */ + if (u4_pcie != NULL && dev->bus->number == 0 && + pci_bus_to_host(dev->bus) == u4_pcie) { + printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n"); + dev->irq = irq_create_mapping(NULL, 1); + if (dev->irq != NO_IRQ) + set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW); + } - /* For all others, map the interrupt from the device-tree */ - pci_read_irq_line(dev); + /* Hide AMD8111 IDE interrupt when in legacy mode so + * the driver calls pci_get_legacy_ide_irq() + */ + if (dev->vendor == PCI_VENDOR_ID_AMD && + dev->device == PCI_DEVICE_ID_AMD_8111_IDE && + (dev->class & 5) != 5) { + dev->irq = NO_IRQ; } - DBG(" <- maple_pcibios_fixup\n"); + DBG(" <- maple_pci_irq_fixup\n"); } static void __init maple_fixup_phb_resources(void) diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index fe6b9bff61b..094989d50ba 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -312,7 +312,7 @@ define_machine(maple_md) { .setup_arch = maple_setup_arch, .init_early = maple_init_early, .init_IRQ = maple_init_IRQ, - .pcibios_fixup = maple_pcibios_fixup, + .pci_irq_fixup = maple_pci_irq_fixup, .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, .restart = maple_restart, .power_off = maple_power_off, diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h index fd71d72736b..51c2a2397ec 100644 --- a/arch/powerpc/platforms/pasemi/pasemi.h +++ b/arch/powerpc/platforms/pasemi/pasemi.h @@ -3,6 +3,5 @@ extern unsigned long pas_get_boot_time(void); extern void pas_pci_init(void); -extern void pas_pcibios_fixup(void); #endif /* _PASEMI_PASEMI_H */ diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index 39020c1fa13..faa618e0404 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c @@ -148,14 +148,6 @@ static int __init add_bridge(struct device_node *dev) } -void __init pas_pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - - for_each_pci_dev(dev) - pci_read_irq_line(dev); -} - static void __init pas_fixup_phb_resources(void) { struct pci_controller *hose, *tmp; diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 106896c3b60..eb2457567f8 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -176,7 +176,6 @@ define_machine(pas) { .init_early = pas_init_early, .init_IRQ = pas_init_IRQ, .get_irq = mpic_get_irq, - .pcibios_fixup = pas_pcibios_fixup, .restart = pas_restart, .power_off = pas_power_off, .halt = pas_halt, diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 257dc906846..f42475b27c1 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -984,30 +984,23 @@ static int __init add_bridge(struct device_node *dev) return 0; } -void __init pmac_pcibios_fixup(void) +void __devinit pmac_pci_irq_fixup(struct pci_dev *dev) { - struct pci_dev* dev = NULL; - - for_each_pci_dev(dev) { - /* Read interrupt from the device-tree */ - pci_read_irq_line(dev); - #ifdef CONFIG_PPC32 - /* Fixup interrupt for the modem/ethernet combo controller. - * on machines with a second ohare chip. - * The number in the device tree (27) is bogus (correct for - * the ethernet-only board but not the combo ethernet/modem - * board). The real interrupt is 28 on the second controller - * -> 28+32 = 60. - */ - if (has_second_ohare && - dev->vendor == PCI_VENDOR_ID_DEC && - dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) { - dev->irq = irq_create_mapping(NULL, 60); - set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW); - } -#endif /* CONFIG_PPC32 */ + /* Fixup interrupt for the modem/ethernet combo controller. + * on machines with a second ohare chip. + * The number in the device tree (27) is bogus (correct for + * the ethernet-only board but not the combo ethernet/modem + * board). The real interrupt is 28 on the second controller + * -> 28+32 = 60. + */ + if (has_second_ohare && + dev->vendor == PCI_VENDOR_ID_DEC && + dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) { + dev->irq = irq_create_mapping(NULL, 60); + set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW); } +#endif /* CONFIG_PPC32 */ } #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h index 94e7b24b840..6e090a7dea8 100644 --- a/arch/powerpc/platforms/powermac/pmac.h +++ b/arch/powerpc/platforms/powermac/pmac.h @@ -20,7 +20,7 @@ extern void pmac_get_rtc_time(struct rtc_time *); extern int pmac_set_rtc_time(struct rtc_time *); extern void pmac_read_rtc_time(void); extern void pmac_calibrate_decr(void); -extern void pmac_pcibios_fixup(void); +extern void pmac_pci_irq_fixup(struct pci_dev *); extern void pmac_pci_init(void); extern unsigned long pmac_ide_get_base(int index); extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index cb1c342061e..805791d76fd 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -727,7 +727,7 @@ define_machine(powermac) { .show_cpuinfo = pmac_show_cpuinfo, .init_IRQ = pmac_pic_init, .get_irq = NULL, /* changed later */ - .pcibios_fixup = pmac_pcibios_fixup, + .pci_irq_fixup = pmac_pci_irq_fixup, .restart = pmac_restart, .power_off = pmac_power_off, .halt = pmac_halt, diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 410a6bcc4ca..715db5c8990 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -29,8 +29,6 @@ #include #include -static int __devinitdata s7a_workaround = -1; - #if 0 void pcibios_name_device(struct pci_dev *dev) { @@ -57,39 +55,6 @@ void pcibios_name_device(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); #endif -static void __devinit check_s7a(void) -{ - struct device_node *root; - const char *model; - - s7a_workaround = 0; - root = of_find_node_by_path("/"); - if (root) { - model = get_property(root, "model", NULL); - if (model && !strcmp(model, "IBM,7013-S7A")) - s7a_workaround = 1; - of_node_put(root); - } -} - -void __devinit pSeries_irq_bus_setup(struct pci_bus *bus) -{ - struct pci_dev *dev; - - if (s7a_workaround < 0) - check_s7a(); - list_for_each_entry(dev, &bus->devices, bus_list) { - pci_read_irq_line(dev); - if (s7a_workaround) { - if (dev->irq > 16) { - dev->irq -= 3; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - dev->irq); - } - } - } -} - static void __init pSeries_request_regions(void) { if (!isa_io_base) diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 89a8119f988..a8f3812aa38 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -553,7 +553,6 @@ define_machine(pseries) { .log_error = pSeries_log_error, .pcibios_fixup = pSeries_final_fixup, .pci_probe_mode = pSeries_pci_probe_mode, - .irq_bus_setup = pSeries_irq_bus_setup, .restart = rtas_restart, .power_off = rtas_power_off, .halt = rtas_halt, diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index dac90dc341c..3810f131901 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -86,7 +86,6 @@ struct machdep_calls { void (*tce_flush)(struct iommu_table *tbl); void (*iommu_dev_setup)(struct pci_dev *dev); void (*iommu_bus_setup)(struct pci_bus *bus); - void (*irq_bus_setup)(struct pci_bus *bus); #endif /* CONFIG_PPC64 */ int (*probe)(void); @@ -106,6 +105,7 @@ struct machdep_calls { /* Called after scanning the bus, before allocating resources */ void (*pcibios_fixup)(void); int (*pci_probe_mode)(struct pci_bus *); + void (*pci_irq_fixup)(struct pci_dev *dev); void (*restart)(char *cmd); void (*power_off)(void); diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index 1115756c79f..8894d1d4226 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h @@ -47,7 +47,6 @@ unsigned long get_phb_buid (struct device_node *); /* From pSeries_pci.h */ extern void pSeries_final_fixup(void); -extern void pSeries_irq_bus_setup(struct pci_bus *bus); extern unsigned long pci_probe_only; -- cgit v1.2.3-70-g09d2 From 69108cf00679716bcab58acb3135390654c5bb99 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:24:52 +1100 Subject: [POWERPC] Remove ppc_md.pci_map_irq & ppc_swizzle for ARCH=powerpc These were inherited from ARCH=ppc, but are not needed since parsing of interrupts should be done via the of_* functions (who can do swizzling). If we ever need to do non-standard swizzling on bridges without a device-node, then we might add back a slightly different version of ppc_md.pci_swizzle but for now, that is not the case. I removed the couple of calls for these in 83xx. If that breaks something, then there is a problem with the device-tree on these. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_32.c | 23 ----------------------- arch/powerpc/platforms/83xx/mpc832x_mds.c | 2 -- arch/powerpc/platforms/83xx/mpc8360e_pb.c | 2 -- include/asm-powerpc/machdep.h | 4 ---- 4 files changed, 31 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 853ecef8178..d32cd500d8b 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -1283,10 +1283,6 @@ pcibios_init(void) if (pci_assign_all_buses && have_of) pcibios_make_OF_bus_map(); - /* Do machine dependent PCI interrupt routing */ - if (ppc_md.pci_swizzle && ppc_md.pci_map_irq) - pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq); - /* Call machine dependent fixup */ if (ppc_md.pcibios_fixup) ppc_md.pcibios_fixup(); @@ -1309,25 +1305,6 @@ pcibios_init(void) subsys_initcall(pcibios_init); -unsigned char __init -common_swizzle(struct pci_dev *dev, unsigned char *pinp) -{ - struct pci_controller *hose = dev->sysdata; - - if (dev->bus->number != hose->first_busno) { - u8 pin = *pinp; - do { - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - /* Move up the chain of bridges. */ - dev = dev->bus->self; - } while (dev->bus->self); - *pinp = pin; - - /* The slot is the idsel of the last bridge. */ - } - return PCI_SLOT(dev->devfn); -} - unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, unsigned long start, unsigned long size) { diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index a43ac71ab74..f58c9780b66 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -97,8 +97,6 @@ static void __init mpc832x_sys_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) add_bridge(np); - - ppc_md.pci_swizzle = common_swizzle; ppc_md.pci_exclude_device = mpc83xx_exclude_device; #endif diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc8360e_pb.c index 1a523c81c06..7bfd47ad723 100644 --- a/arch/powerpc/platforms/83xx/mpc8360e_pb.c +++ b/arch/powerpc/platforms/83xx/mpc8360e_pb.c @@ -102,8 +102,6 @@ static void __init mpc8360_sys_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) add_bridge(np); - - ppc_md.pci_swizzle = common_swizzle; ppc_md.pci_exclude_device = mpc83xx_exclude_device; #endif diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 3810f131901..162205f6264 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -199,10 +199,6 @@ struct machdep_calls { * Returns 0 to allow assignment/enabling of the device. */ int (*pcibios_enable_device_hook)(struct pci_dev *, int initial); - /* For interrupt routing */ - unsigned char (*pci_swizzle)(struct pci_dev *, unsigned char *); - int (*pci_map_irq)(struct pci_dev *, unsigned char, unsigned char); - /* Called in indirect_* to avoid touching devices */ int (*pci_exclude_device)(unsigned char, unsigned char); -- cgit v1.2.3-70-g09d2 From 4c75a6f441cdd1c69a6c173bc7944e12c2ba6f84 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:24:53 +1100 Subject: [POWERPC] Generic DCR infrastructure This patch adds new dcr_map/dcr_read/dcr_write accessors for DCRs that can be used by drivers to transparently address either native DCRs or memory mapped DCRs. The implementation for memory mapped DCRs is done after the binding being currently worked on for SLOF and the Axon chipset. This patch enables it for the cell native platform Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 16 +++++ arch/powerpc/kernel/Makefile | 1 + arch/powerpc/sysdev/Makefile | 3 +- arch/powerpc/sysdev/dcr-low.S | 39 +++++++++++ arch/powerpc/sysdev/dcr.c | 137 +++++++++++++++++++++++++++++++++++++++ arch/ppc/Kconfig | 11 ++++ include/asm-powerpc/dcr-mmio.h | 51 +++++++++++++++ include/asm-powerpc/dcr-native.h | 39 +++++++++++ include/asm-powerpc/dcr.h | 42 ++++++++++++ 9 files changed, 337 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/sysdev/dcr-low.S create mode 100644 arch/powerpc/sysdev/dcr.c create mode 100644 include/asm-powerpc/dcr-mmio.h create mode 100644 include/asm-powerpc/dcr-native.h create mode 100644 include/asm-powerpc/dcr.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 96316c86610..0e564d30fc4 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -160,9 +160,11 @@ config PPC_86xx config 40x bool "AMCC 40x" + select PPC_DCR_NATIVE config 44x bool "AMCC 44x" + select PPC_DCR_NATIVE config 8xx bool "Freescale 8xx" @@ -208,6 +210,19 @@ config PPC_FPU bool default y if PPC64 +config PPC_DCR_NATIVE + bool + default n + +config PPC_DCR_MMIO + bool + default n + +config PPC_DCR + bool + depends on PPC_DCR_NATIVE || PPC_DCR_MMIO + default y + config BOOKE bool depends on E200 || E500 @@ -453,6 +468,7 @@ config PPC_CELL config PPC_CELL_NATIVE bool select PPC_CELL + select PPC_DCR_MMIO default n config PPC_IBM_CELL_BLADE diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index d8240ce2212..f34d158b962 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o + module-$(CONFIG_PPC64) += module_64.o obj-$(CONFIG_MODULES) += $(module-y) diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 5b87f7b42a1..8ba11ab5e61 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -5,8 +5,7 @@ endif obj-$(CONFIG_MPIC) += mpic.o obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o obj-$(CONFIG_PPC_MPC106) += grackle.o -obj-$(CONFIG_BOOKE) += dcr.o -obj-$(CONFIG_40x) += dcr.o +obj-$(CONFIG_PPC_DCR) += dcr.o dcr-low.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o diff --git a/arch/powerpc/sysdev/dcr-low.S b/arch/powerpc/sysdev/dcr-low.S new file mode 100644 index 00000000000..2078f39e2f1 --- /dev/null +++ b/arch/powerpc/sysdev/dcr-low.S @@ -0,0 +1,39 @@ +/* + * "Indirect" DCR access + * + * Copyright (c) 2004 Eugene Surovegin + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +#define DCR_ACCESS_PROLOG(table) \ + rlwinm r3,r3,4,18,27; \ + lis r5,table@h; \ + ori r5,r5,table@l; \ + add r3,r3,r5; \ + mtctr r3; \ + bctr + +_GLOBAL(__mfdcr) + DCR_ACCESS_PROLOG(__mfdcr_table) + +_GLOBAL(__mtdcr) + DCR_ACCESS_PROLOG(__mtdcr_table) + +__mfdcr_table: + mfdcr r3,0; blr +__mtdcr_table: + mtdcr 0,r4; blr + +dcr = 1 + .rept 1023 + mfdcr r3,dcr; blr + mtdcr dcr,r4; blr + dcr = dcr + 1 + .endr diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c new file mode 100644 index 00000000000..dffeeaeca1d --- /dev/null +++ b/arch/powerpc/sysdev/dcr.c @@ -0,0 +1,137 @@ +/* + * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#undef DEBUG + +#include +#include +#include + +unsigned int dcr_resource_start(struct device_node *np, unsigned int index) +{ + unsigned int ds; + const u32 *dr = get_property(np, "dcr-reg", &ds); + + if (dr == NULL || ds & 1 || index >= (ds / 8)) + return 0; + + return dr[index * 2]; +} + +unsigned int dcr_resource_len(struct device_node *np, unsigned int index) +{ + unsigned int ds; + const u32 *dr = get_property(np, "dcr-reg", &ds); + + if (dr == NULL || ds & 1 || index >= (ds / 8)) + return 0; + + return dr[index * 2 + 1]; +} + +#ifndef CONFIG_PPC_DCR_NATIVE + +static struct device_node * find_dcr_parent(struct device_node * node) +{ + struct device_node *par, *tmp; + const u32 *p; + + for (par = of_node_get(node); par;) { + if (get_property(par, "dcr-controller", NULL)) + break; + p = get_property(par, "dcr-parent", NULL); + tmp = par; + if (p == NULL) + par = of_get_parent(par); + else + par = of_find_node_by_phandle(*p); + of_node_put(tmp); + } + return par; +} + +u64 of_translate_dcr_address(struct device_node *dev, + unsigned int dcr_n, + unsigned int *out_stride) +{ + struct device_node *dp; + const u32 *p; + unsigned int stride; + u64 ret; + + dp = find_dcr_parent(dev); + if (dp == NULL) + return OF_BAD_ADDR; + + /* Stride is not properly defined yet, default to 0x10 for Axon */ + p = get_property(dp, "dcr-mmio-stride", NULL); + stride = (p == NULL) ? 0x10 : *p; + + /* XXX FIXME: Which property name is to use of the 2 following ? */ + p = get_property(dp, "dcr-mmio-range", NULL); + if (p == NULL) + p = get_property(dp, "dcr-mmio-space", NULL); + if (p == NULL) + return OF_BAD_ADDR; + + /* Maybe could do some better range checking here */ + ret = of_translate_address(dp, p); + if (ret != OF_BAD_ADDR) + ret += (u64)(stride) * (u64)dcr_n; + if (out_stride) + *out_stride = stride; + return ret; +} + +dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, + unsigned int dcr_c) +{ + dcr_host_t ret = { .token = NULL, .stride = 0 }; + u64 addr; + + pr_debug("dcr_map(%s, 0x%x, 0x%x)\n", + dev->full_name, dcr_n, dcr_c); + + addr = of_translate_dcr_address(dev, dcr_n, &ret.stride); + pr_debug("translates to addr: 0x%lx, stride: 0x%x\n", + addr, ret.stride); + if (addr == OF_BAD_ADDR) + return ret; + pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride); + ret.token = ioremap(addr, dcr_c * ret.stride); + if (ret.token == NULL) + return ret; + pr_debug("mapped at 0x%p -> base is 0x%p\n", + ret.token, ret.token - dcr_n * ret.stride); + ret.token -= dcr_n * ret.stride; + return ret; +} + +void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c) +{ + dcr_host_t h = host; + + if (h.token == NULL) + return; + h.token -= dcr_n * h.stride; + iounmap(h.token); + h.token = NULL; +} + +#endif /* !defined(CONFIG_PPC_DCR_NATIVE) */ diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index ef018e25fb0..edf71a4ecc9 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -77,9 +77,11 @@ config 6xx config 40x bool "40x" + select PPC_DCR_NATIVE config 44x bool "44x" + select PPC_DCR_NATIVE config 8xx bool "8xx" @@ -95,6 +97,15 @@ endchoice config PPC_FPU bool +config PPC_DCR_NATIVE + bool + default n + +config PPC_DCR + bool + depends on PPC_DCR_NATIVE + default y + config BOOKE bool depends on E200 || E500 diff --git a/include/asm-powerpc/dcr-mmio.h b/include/asm-powerpc/dcr-mmio.h new file mode 100644 index 00000000000..5dbfca8dde3 --- /dev/null +++ b/include/asm-powerpc/dcr-mmio.h @@ -0,0 +1,51 @@ +/* + * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ASM_POWERPC_DCR_MMIO_H +#define _ASM_POWERPC_DCR_MMIO_H +#ifdef __KERNEL__ + +#include + +typedef struct { void __iomem *token; unsigned int stride; } dcr_host_t; + +#define DCR_MAP_OK(host) ((host).token != NULL) + +extern dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, + unsigned int dcr_c); +extern void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c); + +static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n) +{ + return in_be32(host.token + dcr_n * host.stride); +} + +static inline void dcr_write(dcr_host_t host, unsigned int dcr_n, u32 value) +{ + out_be32(host.token + dcr_n * host.stride, value); +} + +extern u64 of_translate_dcr_address(struct device_node *dev, + unsigned int dcr_n, + unsigned int *stride); + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_DCR_MMIO_H */ + + diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h new file mode 100644 index 00000000000..fd4a5f5e33d --- /dev/null +++ b/include/asm-powerpc/dcr-native.h @@ -0,0 +1,39 @@ +/* + * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ASM_POWERPC_DCR_NATIVE_H +#define _ASM_POWERPC_DCR_NATIVE_H +#ifdef __KERNEL__ + +#include + +typedef struct {} dcr_host_t; + +#define DCR_MAP_OK(host) (1) + +#define dcr_map(dev, dcr_n, dcr_c) {} +#define dcr_unmap(host, dcr_n, dcr_c) {} +#define dcr_read(host, dcr_n) mfdcr(dcr_n) +#define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value) + + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_DCR_NATIVE_H */ + + diff --git a/include/asm-powerpc/dcr.h b/include/asm-powerpc/dcr.h new file mode 100644 index 00000000000..473f2c7fd89 --- /dev/null +++ b/include/asm-powerpc/dcr.h @@ -0,0 +1,42 @@ +/* + * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ASM_POWERPC_DCR_H +#define _ASM_POWERPC_DCR_H +#ifdef __KERNEL__ + +#ifdef CONFIG_PPC_DCR_NATIVE +#include +#else +#include +#endif + +/* + * On CONFIG_PPC_MERGE, we have additional helpers to read the DCR + * base from the device-tree + */ +#ifdef CONFIG_PPC_MERGE +extern unsigned int dcr_resource_start(struct device_node *np, + unsigned int index); +extern unsigned int dcr_resource_len(struct device_node *np, + unsigned int index); +#endif /* CONFIG_PPC_MERGE */ + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_DCR_H */ -- cgit v1.2.3-70-g09d2 From fbf0274e43b7e17ee740fee2d693932be093d56d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:24:55 +1100 Subject: [POWERPC] Support for DCR based MPIC This patch implements support for DCR based MPIC implementations. Such implementations have the MPIC_USES_DCR flag set and don't use the phys_addr argument of mpic_alloc (they require a valid dcr mapping in the device node) This version of the patch can use a little bif of cleanup still (I can probably consolidate rb->dbase/doff, at least once I'm sure on how the hardware is actually supposed to work vs. possible simulator issues) and it should be possible to build a DCR-only version of the driver. I need to cleanup a bit the CONFIG_* handling for that and probably introduce CONFIG_MPIC_MMIO and CONFIG_MPIC_DCR. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/mpic.c | 136 +++++++++++++++++++++++++++++++++------------ include/asm-powerpc/mpic.h | 35 ++++++++++-- 2 files changed, 131 insertions(+), 40 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index ba4833f57d4..909306ca04f 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -147,33 +147,51 @@ static u32 mpic_infos[][MPIC_IDX_END] = { */ -static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base, - unsigned int reg) +static inline u32 _mpic_read(enum mpic_reg_type type, + struct mpic_reg_bank *rb, + unsigned int reg) { - if (be) - return in_be32(base + (reg >> 2)); - else - return in_le32(base + (reg >> 2)); + switch(type) { +#ifdef CONFIG_PPC_DCR + case mpic_access_dcr: + return dcr_read(rb->dhost, + rb->dbase + reg + rb->doff); +#endif + case mpic_access_mmio_be: + return in_be32(rb->base + (reg >> 2)); + case mpic_access_mmio_le: + default: + return in_le32(rb->base + (reg >> 2)); + } } -static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base, - unsigned int reg, u32 value) +static inline void _mpic_write(enum mpic_reg_type type, + struct mpic_reg_bank *rb, + unsigned int reg, u32 value) { - if (be) - out_be32(base + (reg >> 2), value); - else - out_le32(base + (reg >> 2), value); + switch(type) { +#ifdef CONFIG_PPC_DCR + case mpic_access_dcr: + return dcr_write(rb->dhost, + rb->dbase + reg + rb->doff, value); +#endif + case mpic_access_mmio_be: + return out_be32(rb->base + (reg >> 2), value); + case mpic_access_mmio_le: + default: + return out_le32(rb->base + (reg >> 2), value); + } } static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) { - unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0; + enum mpic_reg_type type = mpic->reg_type; unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + (ipi * MPIC_INFO(GREG_IPI_STRIDE)); - if (mpic->flags & MPIC_BROKEN_IPI) - be = !be; - return _mpic_read(be, mpic->gregs, offset); + if ((mpic->flags & MPIC_BROKEN_IPI) && type == mpic_access_mmio_le) + type = mpic_access_mmio_be; + return _mpic_read(type, &mpic->gregs, offset); } static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) @@ -181,7 +199,7 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + (ipi * MPIC_INFO(GREG_IPI_STRIDE)); - _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value); + _mpic_write(mpic->reg_type, &mpic->gregs, offset, value); } static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) @@ -190,8 +208,7 @@ static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) if (mpic->flags & MPIC_PRIMARY) cpu = hard_smp_processor_id(); - return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, - mpic->cpuregs[cpu], reg); + return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg); } static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) @@ -201,7 +218,7 @@ static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 valu if (mpic->flags & MPIC_PRIMARY) cpu = hard_smp_processor_id(); - _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, value); + _mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value); } static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg) @@ -209,7 +226,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne unsigned int isu = src_no >> mpic->isu_shift; unsigned int idx = src_no & mpic->isu_mask; - return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], + return _mpic_read(mpic->reg_type, &mpic->isus[isu], reg + (idx * MPIC_INFO(IRQ_STRIDE))); } @@ -219,12 +236,12 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, unsigned int isu = src_no >> mpic->isu_shift; unsigned int idx = src_no & mpic->isu_mask; - _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], + _mpic_write(mpic->reg_type, &mpic->isus[isu], reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); } -#define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r)) -#define mpic_write(b,r,v) _mpic_write(mpic->flags & MPIC_BIG_ENDIAN,(b),(r),(v)) +#define mpic_read(b,r) _mpic_read(mpic->reg_type,&(b),(r)) +#define mpic_write(b,r,v) _mpic_write(mpic->reg_type,&(b),(r),(v)) #define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i)) #define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v)) #define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i)) @@ -238,6 +255,38 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, */ +static void _mpic_map_mmio(struct mpic *mpic, unsigned long phys_addr, + struct mpic_reg_bank *rb, unsigned int offset, + unsigned int size) +{ + rb->base = ioremap(phys_addr + offset, size); + BUG_ON(rb->base == NULL); +} + +#ifdef CONFIG_PPC_DCR +static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb, + unsigned int offset, unsigned int size) +{ + rb->dbase = mpic->dcr_base; + rb->doff = offset; + rb->dhost = dcr_map(mpic->of_node, rb->dbase + rb->doff, size); + BUG_ON(!DCR_MAP_OK(rb->dhost)); +} + +static inline void mpic_map(struct mpic *mpic, unsigned long phys_addr, + struct mpic_reg_bank *rb, unsigned int offset, + unsigned int size) +{ + if (mpic->flags & MPIC_USES_DCR) + _mpic_map_dcr(mpic, rb, offset, size); + else + _mpic_map_mmio(mpic, phys_addr, rb, offset, size); +} +#else /* CONFIG_PPC_DCR */ +#define mpic_map(m,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) +#endif /* !CONFIG_PPC_DCR */ + + /* Check if we have one of those nice broken MPICs with a flipped endian on * reads from IPI registers @@ -883,6 +932,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, if (flags & MPIC_PRIMARY) mpic->hc_ht_irq.set_affinity = mpic_set_affinity; #endif /* CONFIG_MPIC_BROKEN_U3 */ + #ifdef CONFIG_SMP mpic->hc_ipi = mpic_ipi_chip; mpic->hc_ipi.typename = name; @@ -897,11 +947,26 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; #endif + /* default register type */ + mpic->reg_type = (flags & MPIC_BIG_ENDIAN) ? + mpic_access_mmio_be : mpic_access_mmio_le; + +#ifdef CONFIG_PPC_DCR + if (mpic->flags & MPIC_USES_DCR) { + const u32 *dbasep; + BUG_ON(mpic->of_node == NULL); + dbasep = get_property(mpic->of_node, "dcr-reg", NULL); + BUG_ON(dbasep == NULL); + mpic->dcr_base = *dbasep; + mpic->reg_type = mpic_access_dcr; + } +#else + BUG_ON (mpic->flags & MPIC_USES_DCR); +#endif /* CONFIG_PPC_DCR */ + /* Map the global registers */ - mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000); - mpic->tmregs = mpic->gregs + - ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2); - BUG_ON(mpic->gregs == NULL); + mpic_map(mpic, phys_addr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); + mpic_map(mpic, phys_addr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); /* Reset */ if (flags & MPIC_WANTS_RESET) { @@ -926,17 +991,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* Map the per-CPU registers */ for (i = 0; i < mpic->num_cpus; i++) { - mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) + - i * MPIC_INFO(CPU_STRIDE), 0x1000); - BUG_ON(mpic->cpuregs[i] == NULL); + mpic_map(mpic, phys_addr, &mpic->cpuregs[i], + MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), + 0x1000); } /* Initialize main ISU if none provided */ if (mpic->isu_size == 0) { mpic->isu_size = mpic->num_sources; - mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE), - MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); - BUG_ON(mpic->isus[0] == NULL); + mpic_map(mpic, phys_addr, &mpic->isus[0], + MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); } mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); mpic->isu_mask = (1 << mpic->isu_shift) - 1; @@ -979,8 +1043,8 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, BUG_ON(isu_num >= MPIC_MAX_ISU); - mpic->isus[isu_num] = ioremap(phys_addr, - MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); + mpic_map(mpic, phys_addr, &mpic->isus[isu_num], 0, + MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); if ((isu_first + mpic->isu_size) > mpic->num_sources) mpic->num_sources = isu_first + mpic->isu_size; } diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h index ef0a5458d2b..ad989d182fb 100644 --- a/include/asm-powerpc/mpic.h +++ b/include/asm-powerpc/mpic.h @@ -3,6 +3,7 @@ #ifdef __KERNEL__ #include +#include /* * Global registers @@ -225,6 +226,23 @@ struct mpic_irq_fixup #endif /* CONFIG_MPIC_BROKEN_U3 */ +enum mpic_reg_type { + mpic_access_mmio_le, + mpic_access_mmio_be, +#ifdef CONFIG_PPC_DCR + mpic_access_dcr +#endif +}; + +struct mpic_reg_bank { + u32 __iomem *base; +#ifdef CONFIG_PPC_DCR + dcr_host_t dhost; + unsigned int dbase; + unsigned int doff; +#endif /* CONFIG_PPC_DCR */ +}; + /* The instance data of a given MPIC */ struct mpic { @@ -264,11 +282,18 @@ struct mpic spinlock_t fixup_lock; #endif + /* Register access method */ + enum mpic_reg_type reg_type; + /* The various ioremap'ed bases */ - volatile u32 __iomem *gregs; - volatile u32 __iomem *tmregs; - volatile u32 __iomem *cpuregs[MPIC_MAX_CPUS]; - volatile u32 __iomem *isus[MPIC_MAX_ISU]; + struct mpic_reg_bank gregs; + struct mpic_reg_bank tmregs; + struct mpic_reg_bank cpuregs[MPIC_MAX_CPUS]; + struct mpic_reg_bank isus[MPIC_MAX_ISU]; + +#ifdef CONFIG_PPC_DCR + unsigned int dcr_base; +#endif #ifdef CONFIG_MPIC_WEIRD /* Pointer to HW info array */ @@ -305,6 +330,8 @@ struct mpic #define MPIC_SPV_EOI 0x00000020 /* No passthrough disable */ #define MPIC_NO_PTHROU_DIS 0x00000040 +/* DCR based MPIC */ +#define MPIC_USES_DCR 0x00000080 /* MPIC HW modification ID */ #define MPIC_REGSET_MASK 0xf0000000 -- cgit v1.2.3-70-g09d2 From a959ff56bbf07954ea4fa1cf72f99a38795eadb3 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:24:56 +1100 Subject: [POWERPC] Improve MPIC driver auto-configuration from DT This patch applies on top of the MPIC DCR support. It makes the MPIC driver capable of a lot more auto-configuration based on the device-tree, for example, it can retreive it's own physical address if not passed as an argument, find out if it's DCR or MMIO mapped, and set the BIG_ENDIAN flag automatically in the presence of a "big-endian" property in the device-tree node. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/mpic.c | 50 ++++++++++++++++++++++++++++++++++------------ include/asm-powerpc/mpic.h | 4 ++-- 2 files changed, 39 insertions(+), 15 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 909306ca04f..411480d5c62 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -894,7 +894,7 @@ static struct irq_host_ops mpic_host_ops = { */ struct mpic * __init mpic_alloc(struct device_node *node, - unsigned long phys_addr, + phys_addr_t phys_addr, unsigned int flags, unsigned int isu_size, unsigned int irq_count, @@ -904,6 +904,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, u32 reg; const char *vers; int i; + u64 paddr = phys_addr; mpic = alloc_bootmem(sizeof(struct mpic)); if (mpic == NULL) @@ -943,6 +944,11 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->irq_count = irq_count; mpic->num_sources = 0; /* so far */ + /* Check for "big-endian" in device-tree */ + if (node && get_property(node, "big-endian", NULL) != NULL) + mpic->flags |= MPIC_BIG_ENDIAN; + + #ifdef CONFIG_MPIC_WEIRD mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; #endif @@ -951,11 +957,17 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->reg_type = (flags & MPIC_BIG_ENDIAN) ? mpic_access_mmio_be : mpic_access_mmio_le; + /* If no physical address is passed in, a device-node is mandatory */ + BUG_ON(paddr == 0 && node == NULL); + + /* If no physical address passed in, check if it's dcr based */ + if (paddr == 0 && get_property(node, "dcr-reg", NULL) != NULL) + mpic->flags |= MPIC_USES_DCR; + #ifdef CONFIG_PPC_DCR if (mpic->flags & MPIC_USES_DCR) { const u32 *dbasep; - BUG_ON(mpic->of_node == NULL); - dbasep = get_property(mpic->of_node, "dcr-reg", NULL); + dbasep = get_property(node, "dcr-reg", NULL); BUG_ON(dbasep == NULL); mpic->dcr_base = *dbasep; mpic->reg_type = mpic_access_dcr; @@ -964,9 +976,20 @@ struct mpic * __init mpic_alloc(struct device_node *node, BUG_ON (mpic->flags & MPIC_USES_DCR); #endif /* CONFIG_PPC_DCR */ + /* If the MPIC is not DCR based, and no physical address was passed + * in, try to obtain one + */ + if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) { + const u32 *reg; + reg = get_property(node, "reg", NULL); + BUG_ON(reg == NULL); + paddr = of_translate_address(node, reg); + BUG_ON(paddr == OF_BAD_ADDR); + } + /* Map the global registers */ - mpic_map(mpic, phys_addr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); - mpic_map(mpic, phys_addr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); + mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); + mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); /* Reset */ if (flags & MPIC_WANTS_RESET) { @@ -991,7 +1014,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* Map the per-CPU registers */ for (i = 0; i < mpic->num_cpus; i++) { - mpic_map(mpic, phys_addr, &mpic->cpuregs[i], + mpic_map(mpic, paddr, &mpic->cpuregs[i], MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), 0x1000); } @@ -999,7 +1022,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* Initialize main ISU if none provided */ if (mpic->isu_size == 0) { mpic->isu_size = mpic->num_sources; - mpic_map(mpic, phys_addr, &mpic->isus[0], + mpic_map(mpic, paddr, &mpic->isus[0], MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); } mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); @@ -1020,10 +1043,11 @@ struct mpic * __init mpic_alloc(struct device_node *node, vers = ""; break; } - printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n", - name, vers, phys_addr, mpic->num_cpus); - printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size, - mpic->isu_shift, mpic->isu_mask); + printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx," + " max %d CPUs\n", + name, vers, (unsigned long long)paddr, mpic->num_cpus); + printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", + mpic->isu_size, mpic->isu_shift, mpic->isu_mask); mpic->next = mpics; mpics = mpic; @@ -1037,13 +1061,13 @@ struct mpic * __init mpic_alloc(struct device_node *node, } void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, - unsigned long phys_addr) + phys_addr_t paddr) { unsigned int isu_first = isu_num * mpic->isu_size; BUG_ON(isu_num >= MPIC_MAX_ISU); - mpic_map(mpic, phys_addr, &mpic->isus[isu_num], 0, + mpic_map(mpic, paddr, &mpic->isus[isu_num], 0, MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); if ((isu_first + mpic->isu_size) > mpic->num_sources) mpic->num_sources = isu_first + mpic->isu_size; diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h index ad989d182fb..b71e7b32a55 100644 --- a/include/asm-powerpc/mpic.h +++ b/include/asm-powerpc/mpic.h @@ -364,7 +364,7 @@ struct mpic * that is senses[0] correspond to linux irq "irq_offset". */ extern struct mpic *mpic_alloc(struct device_node *node, - unsigned long phys_addr, + phys_addr_t phys_addr, unsigned int flags, unsigned int isu_size, unsigned int irq_count, @@ -377,7 +377,7 @@ extern struct mpic *mpic_alloc(struct device_node *node, * @phys_addr: physical address of the ISU */ extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, - unsigned long phys_addr); + phys_addr_t phys_addr); /* Set default sense codes * -- cgit v1.2.3-70-g09d2 From 7eebde700fe6fd6573e80bd8e5ed82b4ae705575 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:24:59 +1100 Subject: [POWERPC] Souped-up of_platform_device support This patch first splits of_device.c and of_platform.c, the later containing the bits relative to of_platform_device's. On the "breaks" side of things, drivers uisng of_platform_device(s) need to include asm/of_platform.h now and of_(un)register_driver is now of_(un)register_platform_driver. In addition to a few utility functions to locate of_platform_device(s), the main new addition is of_platform_bus_probe() which allows the platform code to trigger an automatic creation of of_platform_devices for a whole tree of devices. The function acts based on the type of the various "parent" devices encountered from a provided root, using either a default known list of bus types that can be "probed" or a passed-in list. It will only register devices on busses matching that list, which mean that typically, it will not register PCI devices, as expected (since they will be picked up by the PCI layer). This will be used by Cell platforms using 4xx-type IOs in the Axon bridge and can be used by any embedded-type device as well. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 2 +- arch/powerpc/kernel/of_device.c | 172 +++------------ arch/powerpc/kernel/of_platform.c | 372 ++++++++++++++++++++++++++++++++ arch/powerpc/platforms/powermac/setup.c | 1 + drivers/macintosh/smu.c | 3 +- drivers/macintosh/therm_adt746x.c | 2 +- drivers/macintosh/therm_pm72.c | 5 +- drivers/macintosh/therm_windtunnel.c | 7 +- drivers/video/platinumfb.c | 5 +- include/asm-powerpc/of_device.h | 34 +-- include/asm-powerpc/of_platform.h | 60 ++++++ 11 files changed, 476 insertions(+), 187 deletions(-) create mode 100644 arch/powerpc/kernel/of_platform.c create mode 100644 include/asm-powerpc/of_platform.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index f34d158b962..04fdbe568d7 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ obj-$(CONFIG_PPC64) += vdso64/ obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o obj-$(CONFIG_PPC_970_NAP) += idle_power4.o -obj-$(CONFIG_PPC_OF) += of_device.o prom_parse.o +obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o procfs-$(CONFIG_PPC64) := proc_ppc64.o obj-$(CONFIG_PROC_FS) += $(procfs-y) rtaspci-$(CONFIG_PPC64) := rtas_pci.o diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 397c83eda20..5c653986afa 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -9,30 +9,26 @@ #include /** - * of_match_device - Tell if an of_device structure has a matching - * of_match structure + * of_match_node - Tell if an device_node has a matching of_match structure * @ids: array of of device match structures to search in - * @dev: the of device structure to match against + * @node: the of device structure to match against * - * Used by a driver to check whether an of_device present in the - * system is in its list of supported devices. + * Low level utility function used by device matching. */ -const struct of_device_id *of_match_device(const struct of_device_id *matches, - const struct of_device *dev) +const struct of_device_id *of_match_node(const struct of_device_id *matches, + const struct device_node *node) { - if (!dev->node) - return NULL; while (matches->name[0] || matches->type[0] || matches->compatible[0]) { int match = 1; if (matches->name[0]) - match &= dev->node->name - && !strcmp(matches->name, dev->node->name); + match &= node->name + && !strcmp(matches->name, node->name); if (matches->type[0]) - match &= dev->node->type - && !strcmp(matches->type, dev->node->type); + match &= node->type + && !strcmp(matches->type, node->type); if (matches->compatible[0]) - match &= device_is_compatible(dev->node, - matches->compatible); + match &= device_is_compatible(node, + matches->compatible); if (match) return matches; matches++; @@ -40,16 +36,21 @@ const struct of_device_id *of_match_device(const struct of_device_id *matches, return NULL; } -static int of_platform_bus_match(struct device *dev, struct device_driver *drv) +/** + * of_match_device - Tell if an of_device structure has a matching + * of_match structure + * @ids: array of of device match structures to search in + * @dev: the of device structure to match against + * + * Used by a driver to check whether an of_device present in the + * system is in its list of supported devices. + */ +const struct of_device_id *of_match_device(const struct of_device_id *matches, + const struct of_device *dev) { - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * of_drv = to_of_platform_driver(drv); - const struct of_device_id * matches = of_drv->match_table; - - if (!matches) - return 0; - - return of_match_device(matches, of_dev) != NULL; + if (!dev->node) + return NULL; + return of_match_node(matches, dev->node); } struct of_device *of_dev_get(struct of_device *dev) @@ -71,96 +72,8 @@ void of_dev_put(struct of_device *dev) put_device(&dev->dev); } - -static int of_device_probe(struct device *dev) -{ - int error = -ENODEV; - struct of_platform_driver *drv; - struct of_device *of_dev; - const struct of_device_id *match; - - drv = to_of_platform_driver(dev->driver); - of_dev = to_of_device(dev); - - if (!drv->probe) - return error; - - of_dev_get(of_dev); - - match = of_match_device(drv->match_table, of_dev); - if (match) - error = drv->probe(of_dev, match); - if (error) - of_dev_put(of_dev); - - return error; -} - -static int of_device_remove(struct device *dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - - if (dev->driver && drv->remove) - drv->remove(of_dev); - return 0; -} - -static int of_device_suspend(struct device *dev, pm_message_t state) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->suspend) - error = drv->suspend(of_dev, state); - return error; -} - -static int of_device_resume(struct device * dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->resume) - error = drv->resume(of_dev); - return error; -} - -struct bus_type of_platform_bus_type = { - .name = "of_platform", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; - -static int __init of_bus_driver_init(void) -{ - return bus_register(&of_platform_bus_type); -} - -postcore_initcall(of_bus_driver_init); - -int of_register_driver(struct of_platform_driver *drv) -{ - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = &of_platform_bus_type; - - /* register with core */ - return driver_register(&drv->driver); -} - -void of_unregister_driver(struct of_platform_driver *drv) -{ - driver_unregister(&drv->driver); -} - - -static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t dev_show_devspec(struct device *dev, + struct device_attribute *attr, char *buf) { struct of_device *ofdev; @@ -208,41 +121,10 @@ void of_device_unregister(struct of_device *ofdev) device_unregister(&ofdev->dev); } -struct of_device* of_platform_device_create(struct device_node *np, - const char *bus_id, - struct device *parent) -{ - struct of_device *dev; - - dev = kmalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return NULL; - memset(dev, 0, sizeof(*dev)); - - dev->node = of_node_get(np); - dev->dma_mask = 0xffffffffUL; - dev->dev.dma_mask = &dev->dma_mask; - dev->dev.parent = parent; - dev->dev.bus = &of_platform_bus_type; - dev->dev.release = of_release_dev; - - strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); - - if (of_device_register(dev) != 0) { - kfree(dev); - return NULL; - } - - return dev; -} EXPORT_SYMBOL(of_match_device); -EXPORT_SYMBOL(of_platform_bus_type); -EXPORT_SYMBOL(of_register_driver); -EXPORT_SYMBOL(of_unregister_driver); EXPORT_SYMBOL(of_device_register); EXPORT_SYMBOL(of_device_unregister); EXPORT_SYMBOL(of_dev_get); EXPORT_SYMBOL(of_dev_put); -EXPORT_SYMBOL(of_platform_device_create); EXPORT_SYMBOL(of_release_dev); diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c new file mode 100644 index 00000000000..25850ade8e6 --- /dev/null +++ b/arch/powerpc/kernel/of_platform.c @@ -0,0 +1,372 @@ +/* + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* + * The list of OF IDs below is used for matching bus types in the + * system whose devices are to be exposed as of_platform_devices. + * + * This is the default list valid for most platforms. This file provides + * functions who can take an explicit list if necessary though + * + * The search is always performed recursively looking for children of + * the provided device_node and recursively if such a children matches + * a bus type in the list + */ + +static struct of_device_id of_default_bus_ids[] = { + { .type = "soc", }, + { .compatible = "soc", }, + { .type = "spider", }, + { .type = "axon", }, + { .type = "plb5", }, + { .type = "plb4", }, + { .type = "opb", }, + {}, +}; + +/* + * + * OF platform device type definition & base infrastructure + * + */ + +static int of_platform_bus_match(struct device *dev, struct device_driver *drv) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * of_drv = to_of_platform_driver(drv); + const struct of_device_id * matches = of_drv->match_table; + + if (!matches) + return 0; + + return of_match_device(matches, of_dev) != NULL; +} + +static int of_platform_device_probe(struct device *dev) +{ + int error = -ENODEV; + struct of_platform_driver *drv; + struct of_device *of_dev; + const struct of_device_id *match; + + drv = to_of_platform_driver(dev->driver); + of_dev = to_of_device(dev); + + if (!drv->probe) + return error; + + of_dev_get(of_dev); + + match = of_match_device(drv->match_table, of_dev); + if (match) + error = drv->probe(of_dev, match); + if (error) + of_dev_put(of_dev); + + return error; +} + +static int of_platform_device_remove(struct device *dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(of_dev); + return 0; +} + +static int of_platform_device_suspend(struct device *dev, pm_message_t state) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->suspend) + error = drv->suspend(of_dev, state); + return error; +} + +static int of_platform_device_resume(struct device * dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->resume) + error = drv->resume(of_dev); + return error; +} + +struct bus_type of_platform_bus_type = { + .name = "of_platform", + .match = of_platform_bus_match, + .probe = of_platform_device_probe, + .remove = of_platform_device_remove, + .suspend = of_platform_device_suspend, + .resume = of_platform_device_resume, +}; +EXPORT_SYMBOL(of_platform_bus_type); + +static int __init of_bus_driver_init(void) +{ + return bus_register(&of_platform_bus_type); +} + +postcore_initcall(of_bus_driver_init); + +int of_register_platform_driver(struct of_platform_driver *drv) +{ + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = &of_platform_bus_type; + + /* register with core */ + return driver_register(&drv->driver); +} +EXPORT_SYMBOL(of_register_platform_driver); + +void of_unregister_platform_driver(struct of_platform_driver *drv) +{ + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL(of_unregister_platform_driver); + +static void of_platform_make_bus_id(struct of_device *dev) +{ + struct device_node *node = dev->node; + char *name = dev->dev.bus_id; + const u32 *reg; + u64 addr; + + /* + * If it's a DCR based device, use 'd' for native DCRs + * and 'D' for MMIO DCRs. + */ +#ifdef CONFIG_PPC_DCR + reg = get_property(node, "dcr-reg", NULL); + if (reg) { +#ifdef CONFIG_PPC_DCR_NATIVE + snprintf(name, BUS_ID_SIZE, "d%x.%s", + *reg, node->name); +#else /* CONFIG_PPC_DCR_NATIVE */ + addr = of_translate_dcr_address(node, *reg, NULL); + if (addr != OF_BAD_ADDR) { + snprintf(name, BUS_ID_SIZE, + "D%llx.%s", (unsigned long long)addr, + node->name); + return; + } +#endif /* !CONFIG_PPC_DCR_NATIVE */ + } +#endif /* CONFIG_PPC_DCR */ + + /* + * For MMIO, get the physical address + */ + reg = get_property(node, "reg", NULL); + if (reg) { + addr = of_translate_address(node, reg); + if (addr != OF_BAD_ADDR) { + snprintf(name, BUS_ID_SIZE, + "%llx.%s", (unsigned long long)addr, + node->name); + return; + } + } + + /* + * No BusID, use the node name and pray + */ + snprintf(name, BUS_ID_SIZE, "%s", node->name); +} + +struct of_device* of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent) +{ + struct of_device *dev; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); + + dev->node = of_node_get(np); + dev->dma_mask = 0xffffffffUL; + dev->dev.dma_mask = &dev->dma_mask; + dev->dev.parent = parent; + dev->dev.bus = &of_platform_bus_type; + dev->dev.release = of_release_dev; + + if (bus_id) + strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + else + of_platform_make_bus_id(dev); + + if (of_device_register(dev) != 0) { + kfree(dev); + return NULL; + } + + return dev; +} +EXPORT_SYMBOL(of_platform_device_create); + + + +/** + * of_platform_bus_create - Create an OF device for a bus node and all its + * children. Optionally recursively instanciate matching busses. + * @bus: device node of the bus to instanciate + * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to + * disallow recursive creation of child busses + */ +static int of_platform_bus_create(struct device_node *bus, + struct of_device_id *matches, + struct device *parent) +{ + struct device_node *child; + struct of_device *dev; + int rc = 0; + + for (child = NULL; (child = of_get_next_child(bus, child)); ) { + pr_debug(" create child: %s\n", child->full_name); + dev = of_platform_device_create(child, NULL, parent); + if (dev == NULL) + rc = -ENOMEM; + else if (!of_match_node(matches, child)) + continue; + if (rc == 0) { + pr_debug(" and sub busses\n"); + rc = of_platform_bus_create(child, matches, &dev->dev); + } if (rc) { + of_node_put(child); + break; + } + } + return rc; +} + +/** + * of_platform_bus_probe - Probe the device-tree for platform busses + * @root: parent of the first level to probe or NULL for the root of the tree + * @matches: match table, NULL to use the default + * @parent: parent to hook devices from, NULL for toplevel + * + * Note that children of the provided root are not instanciated as devices + * unless the specified root itself matches the bus list and is not NULL. + */ + +int of_platform_bus_probe(struct device_node *root, + struct of_device_id *matches, + struct device *parent) +{ + struct device_node *child; + struct of_device *dev; + int rc = 0; + + if (matches == NULL) + matches = of_default_bus_ids; + if (matches == OF_NO_DEEP_PROBE) + return -EINVAL; + if (root == NULL) + root = of_find_node_by_path("/"); + else + of_node_get(root); + + pr_debug("of_platform_bus_probe()\n"); + pr_debug(" starting at: %s\n", root->full_name); + + /* Do a self check of bus type, if there's a match, create + * children + */ + if (of_match_node(matches, root)) { + pr_debug(" root match, create all sub devices\n"); + dev = of_platform_device_create(root, NULL, parent); + if (dev == NULL) { + rc = -ENOMEM; + goto bail; + } + pr_debug(" create all sub busses\n"); + rc = of_platform_bus_create(root, matches, &dev->dev); + goto bail; + } + for (child = NULL; (child = of_get_next_child(root, child)); ) { + if (!of_match_node(matches, child)) + continue; + + pr_debug(" match: %s\n", child->full_name); + dev = of_platform_device_create(child, NULL, parent); + if (dev == NULL) + rc = -ENOMEM; + else + rc = of_platform_bus_create(child, matches, &dev->dev); + if (rc) { + of_node_put(child); + break; + } + } + bail: + of_node_put(root); + return rc; +} +EXPORT_SYMBOL(of_platform_bus_probe); + +static int of_dev_node_match(struct device *dev, void *data) +{ + return to_of_device(dev)->node == data; +} + +struct of_device *of_find_device_by_node(struct device_node *np) +{ + struct device *dev; + + dev = bus_find_device(&of_platform_bus_type, + NULL, np, of_dev_node_match); + if (dev) + return to_of_device(dev); + return NULL; +} +EXPORT_SYMBOL(of_find_device_by_node); + +static int of_dev_phandle_match(struct device *dev, void *data) +{ + phandle *ph = data; + return to_of_device(dev)->node->linux_phandle == *ph; +} + +struct of_device *of_find_device_by_phandle(phandle ph) +{ + struct device *dev; + + dev = bus_find_device(&of_platform_bus_type, + NULL, &ph, of_dev_phandle_match); + if (dev) + return to_of_device(dev); + return NULL; +} +EXPORT_SYMBOL(of_find_device_by_phandle); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 805791d76fd..4ec6a5a65f3 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index ade25b3fbb3..4f724cdd2ef 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -46,6 +46,7 @@ #include #include #include +#include #define VERSION "0.7" #define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp." @@ -653,7 +654,7 @@ static int __init smu_init_sysfs(void) * I'm a bit too far from figuring out how that works with those * new chipsets, but that will come back and bite us */ - of_register_driver(&smu_of_platform_driver); + of_register_platform_driver(&smu_of_platform_driver); return 0; } diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index a0f30d0853e..13b953ae8eb 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #undef DEBUG diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index d00c0c37a12..2e4ad44a863 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -129,6 +129,7 @@ #include #include #include +#include #include "therm_pm72.h" @@ -2236,14 +2237,14 @@ static int __init therm_pm72_init(void) return -ENODEV; } - of_register_driver(&fcu_of_platform_driver); + of_register_platform_driver(&fcu_of_platform_driver); return 0; } static void __exit therm_pm72_exit(void) { - of_unregister_driver(&fcu_of_platform_driver); + of_unregister_platform_driver(&fcu_of_platform_driver); if (of_dev) of_device_unregister(of_dev); diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 738faab1b22..a1d3a987cb3 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -36,12 +36,13 @@ #include #include #include + #include #include #include #include #include -#include +#include #include #define LOG_TEMP 0 /* continously log temperature */ @@ -511,14 +512,14 @@ g4fan_init( void ) return -ENODEV; } - of_register_driver( &therm_of_driver ); + of_register_platform_driver( &therm_of_driver ); return 0; } static void __exit g4fan_exit( void ) { - of_unregister_driver( &therm_of_driver ); + of_unregister_platform_driver( &therm_of_driver ); if( x.of_dev ) of_device_unregister( x.of_dev ); diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index fdb33cd21a2..cb26c6df058 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "macmodes.h" #include "platinumfb.h" @@ -682,14 +683,14 @@ static int __init platinumfb_init(void) return -ENODEV; platinumfb_setup(option); #endif - of_register_driver(&platinum_driver); + of_register_platform_driver(&platinum_driver); return 0; } static void __exit platinumfb_exit(void) { - of_unregister_driver(&platinum_driver); + of_unregister_platform_driver(&platinum_driver); } MODULE_LICENSE("GPL"); diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h index c5c0b0b3cd5..1ef7e9edd1a 100644 --- a/include/asm-powerpc/of_device.h +++ b/include/asm-powerpc/of_device.h @@ -6,12 +6,6 @@ #include #include -/* - * The of_platform_bus_type is a bus type used by drivers that do not - * attach to a macio or similar bus but still use OF probing - * mechanism - */ -extern struct bus_type of_platform_bus_type; /* * The of_device is a kind of "base class" that is a superset of @@ -26,40 +20,16 @@ struct of_device }; #define to_of_device(d) container_of(d, struct of_device, dev) +extern const struct of_device_id *of_match_node( + const struct of_device_id *matches, const struct device_node *node); extern const struct of_device_id *of_match_device( const struct of_device_id *matches, const struct of_device *dev); extern struct of_device *of_dev_get(struct of_device *dev); extern void of_dev_put(struct of_device *dev); -/* - * An of_platform_driver driver is attached to a basic of_device on - * the "platform bus" (of_platform_bus_type) - */ -struct of_platform_driver -{ - char *name; - struct of_device_id *match_table; - struct module *owner; - - int (*probe)(struct of_device* dev, const struct of_device_id *match); - int (*remove)(struct of_device* dev); - - int (*suspend)(struct of_device* dev, pm_message_t state); - int (*resume)(struct of_device* dev); - int (*shutdown)(struct of_device* dev); - - struct device_driver driver; -}; -#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver) - -extern int of_register_driver(struct of_platform_driver *drv); -extern void of_unregister_driver(struct of_platform_driver *drv); extern int of_device_register(struct of_device *ofdev); extern void of_device_unregister(struct of_device *ofdev); -extern struct of_device *of_platform_device_create(struct device_node *np, - const char *bus_id, - struct device *parent); extern void of_release_dev(struct device *dev); #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/of_platform.h b/include/asm-powerpc/of_platform.h new file mode 100644 index 00000000000..217eafb167e --- /dev/null +++ b/include/asm-powerpc/of_platform.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include + +/* + * The of_platform_bus_type is a bus type used by drivers that do not + * attach to a macio or similar bus but still use OF probing + * mechanism + */ +extern struct bus_type of_platform_bus_type; + +/* + * An of_platform_driver driver is attached to a basic of_device on + * the "platform bus" (of_platform_bus_type) + */ +struct of_platform_driver +{ + char *name; + struct of_device_id *match_table; + struct module *owner; + + int (*probe)(struct of_device* dev, + const struct of_device_id *match); + int (*remove)(struct of_device* dev); + + int (*suspend)(struct of_device* dev, pm_message_t state); + int (*resume)(struct of_device* dev); + int (*shutdown)(struct of_device* dev); + + struct device_driver driver; +}; +#define to_of_platform_driver(drv) \ + container_of(drv,struct of_platform_driver, driver) + +/* Platform drivers register/unregister */ +extern int of_register_platform_driver(struct of_platform_driver *drv); +extern void of_unregister_platform_driver(struct of_platform_driver *drv); + +/* Platform devices and busses creation */ +extern struct of_device *of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent); +/* pseudo "matches" value to not do deep probe */ +#define OF_NO_DEEP_PROBE ((struct of_device_id *)-1) + +extern int of_platform_bus_probe(struct device_node *root, + struct of_device_id *matches, + struct device *parent); + +extern struct of_device *of_find_device_by_node(struct device_node *np); +extern struct of_device *of_find_device_by_phandle(phandle ph); -- cgit v1.2.3-70-g09d2 From 12d04eef927bf61328af2c7cbe756c96f98ac3bf Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:25:02 +1100 Subject: [POWERPC] Refactor 64 bits DMA operations This patch completely refactors DMA operations for 64 bits powerpc. 32 bits is untouched for now. We use the new dev_archdata structure to add the dma operations pointer and associated data to struct device. While at it, we also add the OF node pointer and numa node. In the future, we might want to look into merging that with pci_dn as well. The old vio, pci-iommu and pci-direct DMA ops are gone. They are now replaced by a set of generic iommu and direct DMA ops (non PCI specific) that can be used by bus types. The toplevel implementation is now inline. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 3 +- arch/powerpc/kernel/dma_64.c | 240 ++++++++++++++++------------- arch/powerpc/kernel/ibmebus.c | 6 +- arch/powerpc/kernel/iommu.c | 6 +- arch/powerpc/kernel/of_platform.c | 9 +- arch/powerpc/kernel/pci_64.c | 26 +++- arch/powerpc/kernel/pci_direct_iommu.c | 98 ------------ arch/powerpc/kernel/pci_iommu.c | 164 -------------------- arch/powerpc/kernel/setup_64.c | 1 + arch/powerpc/kernel/vio.c | 94 +++-------- arch/powerpc/platforms/cell/iommu.c | 21 +-- arch/powerpc/platforms/iseries/iommu.c | 12 +- arch/powerpc/platforms/iseries/pci.c | 2 +- arch/powerpc/platforms/pasemi/setup.c | 16 +- arch/powerpc/platforms/pseries/iommu.c | 90 +++++------ arch/powerpc/platforms/pseries/pci_dlpar.c | 4 +- arch/powerpc/sysdev/dart_iommu.c | 31 ++-- include/asm-powerpc/device.h | 19 ++- include/asm-powerpc/dma-mapping.h | 180 +++++++++++++++++----- include/asm-powerpc/ibmebus.h | 1 - include/asm-powerpc/iommu.h | 20 +-- include/asm-powerpc/iseries/iommu.h | 4 +- include/asm-powerpc/machdep.h | 4 +- include/asm-powerpc/of_device.h | 2 +- include/asm-powerpc/pci.h | 8 +- include/asm-powerpc/vio.h | 1 - 26 files changed, 451 insertions(+), 611 deletions(-) delete mode 100644 arch/powerpc/kernel/pci_direct_iommu.c delete mode 100644 arch/powerpc/kernel/pci_iommu.c (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 04fdbe568d7..eba8d118e21 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -62,8 +62,7 @@ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o module-$(CONFIG_PPC64) += module_64.o obj-$(CONFIG_MODULES) += $(module-y) -pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ - pci_direct_iommu.o iomap.o +pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o iomap.o pci32-$(CONFIG_PPC32) := pci_32.o obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) kexec-$(CONFIG_PPC64) := machine_kexec_64.o diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c index 6c168f6ea14..4e655119978 100644 --- a/arch/powerpc/kernel/dma_64.c +++ b/arch/powerpc/kernel/dma_64.c @@ -1,151 +1,185 @@ /* - * Copyright (C) 2004 IBM Corporation + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation * - * Implements the generic device dma API for ppc64. Handles - * the pci and vio busses + * Provide default implementations of the DMA mapping callbacks for + * directly mapped busses and busses using the iommu infrastructure */ #include #include -/* Include the busses we support */ -#include -#include -#include -#include #include +#include +#include -static struct dma_mapping_ops *get_dma_ops(struct device *dev) -{ -#ifdef CONFIG_PCI - if (dev->bus == &pci_bus_type) - return &pci_dma_ops; -#endif -#ifdef CONFIG_IBMVIO - if (dev->bus == &vio_bus_type) - return &vio_dma_ops; -#endif -#ifdef CONFIG_IBMEBUS - if (dev->bus == &ibmebus_bus_type) - return &ibmebus_dma_ops; -#endif - return NULL; -} +/* + * Generic iommu implementation + */ -int dma_supported(struct device *dev, u64 mask) +static inline unsigned long device_to_mask(struct device *dev) { - struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + if (dev->dma_mask && *dev->dma_mask) + return *dev->dma_mask; + /* Assume devices without mask can take 32 bit addresses */ + return 0xfffffffful; +} - BUG_ON(!dma_ops); - return dma_ops->dma_supported(dev, mask); +/* Allocates a contiguous real buffer and creates mappings over it. + * Returns the virtual address of the buffer and sets dma_handle + * to the dma address (mapping) of the first page. + */ +static void *dma_iommu_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ + return iommu_alloc_coherent(dev->archdata.dma_data, size, dma_handle, + device_to_mask(dev), flag, + dev->archdata.numa_node); } -EXPORT_SYMBOL(dma_supported); -int dma_set_mask(struct device *dev, u64 dma_mask) +static void dma_iommu_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) { -#ifdef CONFIG_PCI - if (dev->bus == &pci_bus_type) - return pci_set_dma_mask(to_pci_dev(dev), dma_mask); -#endif -#ifdef CONFIG_IBMVIO - if (dev->bus == &vio_bus_type) - return -EIO; -#endif /* CONFIG_IBMVIO */ -#ifdef CONFIG_IBMEBUS - if (dev->bus == &ibmebus_bus_type) - return -EIO; -#endif - BUG(); - return 0; + iommu_free_coherent(dev->archdata.dma_data, size, vaddr, dma_handle); } -EXPORT_SYMBOL(dma_set_mask); -void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) +/* Creates TCEs for a user provided buffer. The user buffer must be + * contiguous real kernel storage (not vmalloc). The address of the buffer + * passed here is the kernel (virtual) address of the buffer. The buffer + * need not be page aligned, the dma_addr_t returned will point to the same + * byte within the page as vaddr. + */ +static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr, + size_t size, + enum dma_data_direction direction) { - struct dma_mapping_ops *dma_ops = get_dma_ops(dev); - - BUG_ON(!dma_ops); - - return dma_ops->alloc_coherent(dev, size, dma_handle, flag); + return iommu_map_single(dev->archdata.dma_data, vaddr, size, + device_to_mask(dev), direction); } -EXPORT_SYMBOL(dma_alloc_coherent); -void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, - dma_addr_t dma_handle) + +static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle, + size_t size, + enum dma_data_direction direction) { - struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + iommu_unmap_single(dev->archdata.dma_data, dma_handle, size, direction); +} - BUG_ON(!dma_ops); - dma_ops->free_coherent(dev, size, cpu_addr, dma_handle); +static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist, + int nelems, enum dma_data_direction direction) +{ + return iommu_map_sg(dev->archdata.dma_data, sglist, nelems, + device_to_mask(dev), direction); } -EXPORT_SYMBOL(dma_free_coherent); -dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, - enum dma_data_direction direction) +static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist, + int nelems, enum dma_data_direction direction) { - struct dma_mapping_ops *dma_ops = get_dma_ops(dev); - - BUG_ON(!dma_ops); - - return dma_ops->map_single(dev, cpu_addr, size, direction); + iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction); } -EXPORT_SYMBOL(dma_map_single); -void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, - enum dma_data_direction direction) +/* We support DMA to/from any memory page via the iommu */ +static int dma_iommu_dma_supported(struct device *dev, u64 mask) { - struct dma_mapping_ops *dma_ops = get_dma_ops(dev); - - BUG_ON(!dma_ops); - - dma_ops->unmap_single(dev, dma_addr, size, direction); + struct iommu_table *tbl = dev->archdata.dma_data; + + if (!tbl || tbl->it_offset > mask) { + printk(KERN_INFO + "Warning: IOMMU offset too big for device mask\n"); + if (tbl) + printk(KERN_INFO + "mask: 0x%08lx, table offset: 0x%08lx\n", + mask, tbl->it_offset); + else + printk(KERN_INFO "mask: 0x%08lx, table unavailable\n", + mask); + return 0; + } else + return 1; } -EXPORT_SYMBOL(dma_unmap_single); -dma_addr_t dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - struct dma_mapping_ops *dma_ops = get_dma_ops(dev); +struct dma_mapping_ops dma_iommu_ops = { + .alloc_coherent = dma_iommu_alloc_coherent, + .free_coherent = dma_iommu_free_coherent, + .map_single = dma_iommu_map_single, + .unmap_single = dma_iommu_unmap_single, + .map_sg = dma_iommu_map_sg, + .unmap_sg = dma_iommu_unmap_sg, + .dma_supported = dma_iommu_dma_supported, +}; +EXPORT_SYMBOL(dma_iommu_ops); - BUG_ON(!dma_ops); +/* + * Generic direct DMA implementation + */ - return dma_ops->map_single(dev, page_address(page) + offset, size, - direction); +static void *dma_direct_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ + void *ret; + + /* TODO: Maybe use the numa node here too ? */ + ret = (void *)__get_free_pages(flag, get_order(size)); + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_abs(ret); + } + return ret; } -EXPORT_SYMBOL(dma_map_page); -void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, - enum dma_data_direction direction) +static void dma_direct_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) { - struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + free_pages((unsigned long)vaddr, get_order(size)); +} - BUG_ON(!dma_ops); +static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr, + size_t size, + enum dma_data_direction direction) +{ + return virt_to_abs(ptr); +} - dma_ops->unmap_single(dev, dma_address, size, direction); +static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, + enum dma_data_direction direction) +{ } -EXPORT_SYMBOL(dma_unmap_page); -int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction direction) +static int dma_direct_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) { - struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + int i; - BUG_ON(!dma_ops); + for (i = 0; i < nents; i++, sg++) { + sg->dma_address = page_to_phys(sg->page) + sg->offset; + sg->dma_length = sg->length; + } - return dma_ops->map_sg(dev, sg, nents, direction); + return nents; } -EXPORT_SYMBOL(dma_map_sg); -void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, - enum dma_data_direction direction) +static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) { - struct dma_mapping_ops *dma_ops = get_dma_ops(dev); - - BUG_ON(!dma_ops); +} - dma_ops->unmap_sg(dev, sg, nhwentries, direction); +static int dma_direct_dma_supported(struct device *dev, u64 mask) +{ + /* Could be improved to check for memory though it better be + * done via some global so platforms can set the limit in case + * they have limited DMA windows + */ + return mask >= DMA_32BIT_MASK; } -EXPORT_SYMBOL(dma_unmap_sg); + +struct dma_mapping_ops dma_direct_ops = { + .alloc_coherent = dma_direct_alloc_coherent, + .free_coherent = dma_direct_free_coherent, + .map_single = dma_direct_map_single, + .unmap_single = dma_direct_unmap_single, + .map_sg = dma_direct_map_sg, + .unmap_sg = dma_direct_unmap_sg, + .dma_supported = dma_direct_dma_supported, +}; +EXPORT_SYMBOL(dma_direct_ops); diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 39db7a3affe..8e515797de6 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -112,7 +112,7 @@ static int ibmebus_dma_supported(struct device *dev, u64 mask) return 1; } -struct dma_mapping_ops ibmebus_dma_ops = { +static struct dma_mapping_ops ibmebus_dma_ops = { .alloc_coherent = ibmebus_alloc_coherent, .free_coherent = ibmebus_free_coherent, .map_single = ibmebus_map_single, @@ -176,6 +176,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common( dev->ofdev.dev.bus = &ibmebus_bus_type; dev->ofdev.dev.release = ibmebus_dev_release; + dev->ofdev.dev.archdata.of_node = dev->ofdev.node; + dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops; + dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node); + /* An ibmebusdev is based on a of_device. We have to change the * bus type to use our own DMA mapping operations. */ diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index ba6b7256084..95edad4faf2 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -258,9 +258,9 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, spin_unlock_irqrestore(&(tbl->it_lock), flags); } -int iommu_map_sg(struct device *dev, struct iommu_table *tbl, - struct scatterlist *sglist, int nelems, - unsigned long mask, enum dma_data_direction direction) +int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, + int nelems, unsigned long mask, + enum dma_data_direction direction) { dma_addr_t dma_next = 0, dma_addr; unsigned long flags; diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 25850ade8e6..7a0e77af7c9 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -22,7 +22,7 @@ #include #include #include - +#include /* * The list of OF IDs below is used for matching bus types in the @@ -221,6 +221,13 @@ struct of_device* of_platform_device_create(struct device_node *np, dev->dev.parent = parent; dev->dev.bus = &of_platform_bus_type; dev->dev.release = of_release_dev; + dev->dev.archdata.of_node = np; + dev->dev.archdata.numa_node = of_node_to_nid(np); + + /* We do not fill the DMA ops for platform devices by default. + * This is currently the responsibility of the platform code + * to do such, possibly using a device notifier + */ if (bus_id) strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 9a6bb80a8cd..88b78484b94 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -61,7 +61,7 @@ void iSeries_pcibios_init(void); LIST_HEAD(hose_list); -struct dma_mapping_ops pci_dma_ops; +struct dma_mapping_ops *pci_dma_ops; EXPORT_SYMBOL(pci_dma_ops); int global_phb_number; /* Global phb counter */ @@ -1205,15 +1205,35 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, } EXPORT_SYMBOL(pcibios_fixup_device_resources); +void __devinit pcibios_setup_new_device(struct pci_dev *dev) +{ + struct dev_archdata *sd = &dev->dev.archdata; + + sd->of_node = pci_device_to_OF_node(dev); + + DBG("PCI device %s OF node: %s\n", pci_name(dev), + sd->of_node ? sd->of_node->full_name : ""); + + sd->dma_ops = pci_dma_ops; +#ifdef CONFIG_NUMA + sd->numa_node = pcibus_to_node(dev->bus); +#else + sd->numa_node = -1; +#endif + if (ppc_md.pci_dma_dev_setup) + ppc_md.pci_dma_dev_setup(dev); +} +EXPORT_SYMBOL(pcibios_setup_new_device); static void __devinit do_bus_setup(struct pci_bus *bus) { struct pci_dev *dev; - ppc_md.iommu_bus_setup(bus); + if (ppc_md.pci_dma_bus_setup) + ppc_md.pci_dma_bus_setup(bus); list_for_each_entry(dev, &bus->devices, bus_list) - ppc_md.iommu_dev_setup(dev); + pcibios_setup_new_device(dev); /* Read default IRQs and fixup if necessary */ list_for_each_entry(dev, &bus->devices, bus_list) { diff --git a/arch/powerpc/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c deleted file mode 100644 index 72ce082ce73..00000000000 --- a/arch/powerpc/kernel/pci_direct_iommu.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Support for DMA from PCI devices to main memory on - * machines without an iommu or with directly addressable - * RAM (typically a pmac with 2Gb of RAM or less) - * - * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) -{ - void *ret; - - ret = (void *)__get_free_pages(flag, get_order(size)); - if (ret != NULL) { - memset(ret, 0, size); - *dma_handle = virt_to_abs(ret); - } - return ret; -} - -static void pci_direct_free_coherent(struct device *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - free_pages((unsigned long)vaddr, get_order(size)); -} - -static dma_addr_t pci_direct_map_single(struct device *hwdev, void *ptr, - size_t size, enum dma_data_direction direction) -{ - return virt_to_abs(ptr); -} - -static void pci_direct_unmap_single(struct device *hwdev, dma_addr_t dma_addr, - size_t size, enum dma_data_direction direction) -{ -} - -static int pci_direct_map_sg(struct device *hwdev, struct scatterlist *sg, - int nents, enum dma_data_direction direction) -{ - int i; - - for (i = 0; i < nents; i++, sg++) { - sg->dma_address = page_to_phys(sg->page) + sg->offset; - sg->dma_length = sg->length; - } - - return nents; -} - -static void pci_direct_unmap_sg(struct device *hwdev, struct scatterlist *sg, - int nents, enum dma_data_direction direction) -{ -} - -static int pci_direct_dma_supported(struct device *dev, u64 mask) -{ - return mask < 0x100000000ull; -} - -static struct dma_mapping_ops pci_direct_ops = { - .alloc_coherent = pci_direct_alloc_coherent, - .free_coherent = pci_direct_free_coherent, - .map_single = pci_direct_map_single, - .unmap_single = pci_direct_unmap_single, - .map_sg = pci_direct_map_sg, - .unmap_sg = pci_direct_unmap_sg, - .dma_supported = pci_direct_dma_supported, -}; - -void __init pci_direct_iommu_init(void) -{ - pci_dma_ops = pci_direct_ops; -} diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c deleted file mode 100644 index 0688b2534ac..00000000000 --- a/arch/powerpc/kernel/pci_iommu.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation - * - * Rewrite, cleanup, new allocation schemes: - * Copyright (C) 2004 Olof Johansson, IBM Corporation - * - * Dynamic DMA mapping support, platform-independent parts. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * We can use ->sysdata directly and avoid the extra work in - * pci_device_to_OF_node since ->sysdata will have been initialised - * in the iommu init code for all devices. - */ -#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata)) - -static inline struct iommu_table *device_to_table(struct device *hwdev) -{ - struct pci_dev *pdev; - - if (!hwdev) { - pdev = ppc64_isabridge_dev; - if (!pdev) - return NULL; - } else - pdev = to_pci_dev(hwdev); - - return PCI_DN(PCI_GET_DN(pdev))->iommu_table; -} - - -static inline unsigned long device_to_mask(struct device *hwdev) -{ - struct pci_dev *pdev; - - if (!hwdev) { - pdev = ppc64_isabridge_dev; - if (!pdev) /* This is the best guess we can do */ - return 0xfffffffful; - } else - pdev = to_pci_dev(hwdev); - - if (pdev->dma_mask) - return pdev->dma_mask; - - /* Assume devices without mask can take 32 bit addresses */ - return 0xfffffffful; -} - - -/* Allocates a contiguous real buffer and creates mappings over it. - * Returns the virtual address of the buffer and sets dma_handle - * to the dma address (mapping) of the first page. - */ -static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) -{ - return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle, - device_to_mask(hwdev), flag, - pcibus_to_node(to_pci_dev(hwdev)->bus)); -} - -static void pci_iommu_free_coherent(struct device *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle); -} - -/* Creates TCEs for a user provided buffer. The user buffer must be - * contiguous real kernel storage (not vmalloc). The address of the buffer - * passed here is the kernel (virtual) address of the buffer. The buffer - * need not be page aligned, the dma_addr_t returned will point to the same - * byte within the page as vaddr. - */ -static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, - size_t size, enum dma_data_direction direction) -{ - return iommu_map_single(device_to_table(hwdev), vaddr, size, - device_to_mask(hwdev), direction); -} - - -static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction direction) -{ - iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction); -} - - -static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist, - int nelems, enum dma_data_direction direction) -{ - return iommu_map_sg(pdev, device_to_table(pdev), sglist, - nelems, device_to_mask(pdev), direction); -} - -static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist, - int nelems, enum dma_data_direction direction) -{ - iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction); -} - -/* We support DMA to/from any memory page via the iommu */ -static int pci_iommu_dma_supported(struct device *dev, u64 mask) -{ - struct iommu_table *tbl = device_to_table(dev); - - if (!tbl || tbl->it_offset > mask) { - printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n"); - if (tbl) - printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n", - mask, tbl->it_offset); - else - printk(KERN_INFO "mask: 0x%08lx, table unavailable\n", - mask); - return 0; - } else - return 1; -} - -struct dma_mapping_ops pci_iommu_ops = { - .alloc_coherent = pci_iommu_alloc_coherent, - .free_coherent = pci_iommu_free_coherent, - .map_single = pci_iommu_map_single, - .unmap_single = pci_iommu_unmap_single, - .map_sg = pci_iommu_map_sg, - .unmap_sg = pci_iommu_unmap_sg, - .dma_supported = pci_iommu_dma_supported, -}; - -void pci_iommu_init(void) -{ - pci_dma_ops = pci_iommu_ops; -} diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index b0f1c82df99..f7ad64acf47 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index ed007878d1b..a80f8f1d2e5 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -81,15 +81,15 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) struct iommu_table *tbl; unsigned long offset, size; - dma_window = get_property(dev->dev.platform_data, - "ibm,my-dma-window", NULL); + dma_window = get_property(dev->dev.archdata.of_node, + "ibm,my-dma-window", NULL); if (!dma_window) return NULL; tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); - of_parse_dma_window(dev->dev.platform_data, dma_window, - &tbl->it_index, &offset, &size); + of_parse_dma_window(dev->dev.archdata.of_node, dma_window, + &tbl->it_index, &offset, &size); /* TCE table size - measured in tce entries */ tbl->it_size = size >> IOMMU_PAGE_SHIFT; @@ -117,7 +117,8 @@ static const struct vio_device_id *vio_match_device( { while (ids->type[0] != '\0') { if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && - device_is_compatible(dev->dev.platform_data, ids->compat)) + device_is_compatible(dev->dev.archdata.of_node, + ids->compat)) return ids; ids++; } @@ -198,9 +199,9 @@ EXPORT_SYMBOL(vio_unregister_driver); /* vio_dev refcount hit 0 */ static void __devinit vio_dev_release(struct device *dev) { - if (dev->platform_data) { - /* XXX free TCE table */ - of_node_put(dev->platform_data); + if (dev->archdata.of_node) { + /* XXX should free TCE table */ + of_node_put(dev->archdata.of_node); } kfree(to_vio_dev(dev)); } @@ -210,7 +211,7 @@ static void __devinit vio_dev_release(struct device *dev) * @of_node: The OF node for this device. * * Creates and initializes a vio_dev structure from the data in - * of_node (dev.platform_data) and adds it to the list of virtual devices. + * of_node and adds it to the list of virtual devices. * Returns a pointer to the created vio_dev or NULL if node has * NULL device_type or compatible fields. */ @@ -240,8 +241,6 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) if (viodev == NULL) return NULL; - viodev->dev.platform_data = of_node_get(of_node); - viodev->irq = irq_of_parse_and_map(of_node, 0); snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); @@ -254,7 +253,10 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) if (unit_address != NULL) viodev->unit_address = *unit_address; } - viodev->iommu_table = vio_build_iommu_table(viodev); + viodev->dev.archdata.of_node = of_node_get(of_node); + viodev->dev.archdata.dma_ops = &dma_iommu_ops; + viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev); + viodev->dev.archdata.numa_node = of_node_to_nid(of_node); /* init generic 'struct device' fields: */ viodev->dev.parent = &vio_bus_device.dev; @@ -285,10 +287,11 @@ static int __init vio_bus_init(void) #ifdef CONFIG_PPC_ISERIES if (firmware_has_feature(FW_FEATURE_ISERIES)) { iommu_vio_init(); - vio_bus_device.iommu_table = &vio_iommu_table; + vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops; + vio_bus_device.dev.archdata.dma_data = &vio_iommu_table; iSeries_vio_dev = &vio_bus_device.dev; } -#endif +#endif /* CONFIG_PPC_ISERIES */ err = bus_register(&vio_bus_type); if (err) { @@ -336,7 +339,7 @@ static ssize_t name_show(struct device *dev, static ssize_t devspec_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct device_node *of_node = dev->platform_data; + struct device_node *of_node = dev->archdata.of_node; return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); } @@ -353,62 +356,6 @@ void __devinit vio_unregister_device(struct vio_dev *viodev) } EXPORT_SYMBOL(vio_unregister_device); -static dma_addr_t vio_map_single(struct device *dev, void *vaddr, - size_t size, enum dma_data_direction direction) -{ - return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size, - ~0ul, direction); -} - -static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction direction) -{ - iommu_unmap_single(to_vio_dev(dev)->iommu_table, dma_handle, size, - direction); -} - -static int vio_map_sg(struct device *dev, struct scatterlist *sglist, - int nelems, enum dma_data_direction direction) -{ - return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist, - nelems, ~0ul, direction); -} - -static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist, - int nelems, enum dma_data_direction direction) -{ - iommu_unmap_sg(to_vio_dev(dev)->iommu_table, sglist, nelems, direction); -} - -static void *vio_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) -{ - return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, - dma_handle, ~0ul, flag, -1); -} - -static void vio_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - iommu_free_coherent(to_vio_dev(dev)->iommu_table, size, vaddr, - dma_handle); -} - -static int vio_dma_supported(struct device *dev, u64 mask) -{ - return 1; -} - -struct dma_mapping_ops vio_dma_ops = { - .alloc_coherent = vio_alloc_coherent, - .free_coherent = vio_free_coherent, - .map_single = vio_map_single, - .unmap_single = vio_unmap_single, - .map_sg = vio_map_sg, - .unmap_sg = vio_unmap_sg, - .dma_supported = vio_dma_supported, -}; - static int vio_bus_match(struct device *dev, struct device_driver *drv) { const struct vio_dev *vio_dev = to_vio_dev(dev); @@ -422,13 +369,14 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { const struct vio_dev *vio_dev = to_vio_dev(dev); - struct device_node *dn = dev->platform_data; + struct device_node *dn; const char *cp; int length; if (!num_envp) return -ENOMEM; + dn = dev->archdata.of_node; if (!dn) return -ENODEV; cp = get_property(dn, "compatible", &length); @@ -465,7 +413,7 @@ struct bus_type vio_bus_type = { */ const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) { - return get_property(vdev->dev.platform_data, which, length); + return get_property(vdev->dev.archdata.of_node, which, length); } EXPORT_SYMBOL(vio_get_attribute); diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index aca4c3db0dd..0e6ab8a55ef 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -255,9 +255,6 @@ static void enable_mapping(void __iomem *base, void __iomem *mmio_base) set_iost_origin(mmio_base); } -static void iommu_dev_setup_null(struct pci_dev *d) { } -static void iommu_bus_setup_null(struct pci_bus *b) { } - struct cell_iommu { unsigned long base; unsigned long mmio_base; @@ -306,12 +303,15 @@ static void cell_do_map_iommu(struct cell_iommu *iommu, } } -static void iommu_devnode_setup(struct device_node *d) +static void pci_dma_cell_bus_setup(struct pci_bus *b) { const unsigned int *ioid; unsigned long map_start, map_size, token; const unsigned long *dma_window; struct cell_iommu *iommu; + struct device_node *d; + + d = pci_bus_to_OF_node(b); ioid = get_property(d, "ioid", NULL); if (!ioid) @@ -330,12 +330,6 @@ static void iommu_devnode_setup(struct device_node *d) cell_do_map_iommu(iommu, *ioid, map_start, map_size); } -static void iommu_bus_setup(struct pci_bus *b) -{ - struct device_node *d = (struct device_node *)b->sysdata; - iommu_devnode_setup(d); -} - static int cell_map_iommu_hardcoded(int num_nodes) { @@ -499,16 +493,13 @@ void cell_init_iommu(void) if (setup_bus) { pr_debug("%s: IOMMU mapping activated\n", __FUNCTION__); - ppc_md.iommu_dev_setup = iommu_dev_setup_null; - ppc_md.iommu_bus_setup = iommu_bus_setup; + ppc_md.pci_dma_bus_setup = pci_dma_cell_bus_setup; } else { pr_debug("%s: IOMMU mapping activated, " "no device action necessary\n", __FUNCTION__); /* Direct I/O, IOMMU off */ - ppc_md.iommu_dev_setup = iommu_dev_setup_null; - ppc_md.iommu_bus_setup = iommu_bus_setup_null; } } - pci_dma_ops = cell_iommu_ops; + pci_dma_ops = &cell_iommu_ops; } diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 218817d13c5..ee0a4e42e4f 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -168,7 +169,7 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl) } -void iommu_devnode_init_iSeries(struct device_node *dn) +void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn) { struct iommu_table *tbl; struct pci_dn *pdn = PCI_DN(dn); @@ -186,19 +187,14 @@ void iommu_devnode_init_iSeries(struct device_node *dn) pdn->iommu_table = iommu_init_table(tbl, -1); else kfree(tbl); + pdev->dev.archdata.dma_data = pdn->iommu_table; } #endif -static void iommu_dev_setup_iSeries(struct pci_dev *dev) { } -static void iommu_bus_setup_iSeries(struct pci_bus *bus) { } - void iommu_init_early_iSeries(void) { ppc_md.tce_build = tce_build_iSeries; ppc_md.tce_free = tce_free_iSeries; - ppc_md.iommu_dev_setup = iommu_dev_setup_iSeries; - ppc_md.iommu_bus_setup = iommu_bus_setup_iSeries; - - pci_iommu_init(); + pci_dma_ops = &dma_iommu_ops; } diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 4aa165e010d..a90ae42a7bc 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -253,7 +253,7 @@ void __init iSeries_pci_final_fixup(void) PCI_DN(node)->pcidev = pdev; allocate_device_bars(pdev); iSeries_Device_Information(pdev, DeviceCount); - iommu_devnode_init_iSeries(node); + iommu_devnode_init_iSeries(pdev, node); } else printk("PCI: Device Tree not found for 0x%016lX\n", (unsigned long)pdev); diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index eb2457567f8..89d6e295dbf 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -71,6 +72,9 @@ void __init pas_setup_arch(void) /* Setup SMP callback */ smp_ops = &pas_smp_ops; #endif + /* no iommu yet */ + pci_dma_ops = &dma_direct_ops; + /* Lookup PCI hosts */ pas_pci_init(); @@ -81,17 +85,6 @@ void __init pas_setup_arch(void) printk(KERN_DEBUG "Using default idle loop\n"); } -static void iommu_dev_setup_null(struct pci_dev *dev) { } -static void iommu_bus_setup_null(struct pci_bus *bus) { } - -static void __init pas_init_early(void) -{ - /* No iommu code yet */ - ppc_md.iommu_dev_setup = iommu_dev_setup_null; - ppc_md.iommu_bus_setup = iommu_bus_setup_null; - pci_direct_iommu_init(); -} - /* No legacy IO on our parts */ static int pas_check_legacy_ioport(unsigned int baseport) { @@ -173,7 +166,6 @@ define_machine(pas) { .name = "PA Semi PA6T-1682M", .probe = pas_probe, .setup_arch = pas_setup_arch, - .init_early = pas_init_early, .init_IRQ = pas_init_IRQ, .get_irq = mpic_get_irq, .restart = pas_restart, diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 556c279a789..3c95392f4f4 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -309,7 +309,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, tbl->it_size = size >> IOMMU_PAGE_SHIFT; } -static void iommu_bus_setup_pSeries(struct pci_bus *bus) +static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) { struct device_node *dn; struct iommu_table *tbl; @@ -318,10 +318,9 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) struct pci_dn *pci; int children; - DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); - dn = pci_bus_to_OF_node(bus); - pci = PCI_DN(dn); + + DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name); if (bus->self) { /* This is not a root bus, any setup will be done for the @@ -329,6 +328,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) */ return; } + pci = PCI_DN(dn); /* Check if the ISA bus on the system is under * this PHB. @@ -390,17 +390,17 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) } -static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) +static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) { struct iommu_table *tbl; struct device_node *dn, *pdn; struct pci_dn *ppci; const void *dma_window = NULL; - DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); - dn = pci_bus_to_OF_node(bus); + DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name); + /* Find nearest ibm,dma-window, walking up the device tree */ for (pdn = dn; pdn != NULL; pdn = pdn->parent) { dma_window = get_property(pdn, "ibm,dma-window", NULL); @@ -409,11 +409,15 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) } if (dma_window == NULL) { - DBG("iommu_bus_setup_pSeriesLP: bus %s seems to have no ibm,dma-window property\n", dn->full_name); + DBG(" no ibm,dma-window property !\n"); return; } ppci = PCI_DN(pdn); + + DBG(" parent is %s, iommu_table: 0x%p\n", + pdn->full_name, ppci->iommu_table); + if (!ppci->iommu_table) { /* Bussubno hasn't been copied yet. * Do it now because iommu_table_setparms_lpar needs it. @@ -427,6 +431,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); + DBG(" created table: %p\n", ppci->iommu_table); } if (pdn != dn) @@ -434,27 +439,27 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) } -static void iommu_dev_setup_pSeries(struct pci_dev *dev) +static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) { - struct device_node *dn, *mydn; + struct device_node *dn; struct iommu_table *tbl; - DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev)); + DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev)); - mydn = dn = pci_device_to_OF_node(dev); + dn = dev->dev.archdata.of_node; /* If we're the direct child of a root bus, then we need to allocate * an iommu table ourselves. The bus setup code should have setup * the window sizes already. */ if (!dev->bus->self) { + struct pci_controller *phb = PCI_DN(dn)->phb; + DBG(" --> first child, no bridge. Allocating iommu table.\n"); tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, - PCI_DN(dn)->phb->node); - iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); - PCI_DN(dn)->iommu_table = iommu_init_table(tbl, - PCI_DN(dn)->phb->node); - + phb->node); + iommu_table_setparms(phb, dn, tbl); + dev->dev.archdata.dma_data = iommu_init_table(tbl, phb->node); return; } @@ -465,11 +470,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev) while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL) dn = dn->parent; - if (dn && PCI_DN(dn)) { - PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table; - } else { - DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev)); - } + if (dn && PCI_DN(dn)) + dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table; + else + printk(KERN_WARNING "iommu: Device %s has no iommu table\n", + pci_name(dev)); } static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) @@ -495,13 +500,15 @@ static struct notifier_block iommu_reconfig_nb = { .notifier_call = iommu_reconfig_notifier, }; -static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) +static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) { struct device_node *pdn, *dn; struct iommu_table *tbl; const void *dma_window = NULL; struct pci_dn *pci; + DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev)); + /* dev setup for LPAR is a little tricky, since the device tree might * contain the dma-window properties per-device and not neccesarily * for the bus. So we need to search upwards in the tree until we @@ -509,9 +516,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) * already allocated. */ dn = pci_device_to_OF_node(dev); - - DBG("iommu_dev_setup_pSeriesLP, dev %p (%s) %s\n", - dev, pci_name(dev), dn->full_name); + DBG(" node is %s\n", dn->full_name); for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; pdn = pdn->parent) { @@ -520,16 +525,17 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) break; } + DBG(" parent is %s\n", pdn->full_name); + /* Check for parent == NULL so we don't try to setup the empty EADS * slots on POWER4 machines. */ if (dma_window == NULL || pdn->parent == NULL) { - DBG("No dma window for device, linking to parent\n"); - PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table; + DBG(" no dma window for device, linking to parent\n"); + dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table; return; - } else { - DBG("Found DMA window, allocating table\n"); } + DBG(" found DMA window, table: %p\n", pci->iommu_table); pci = PCI_DN(pdn); if (!pci->iommu_table) { @@ -542,24 +548,20 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); pci->iommu_table = iommu_init_table(tbl, pci->phb->node); + DBG(" created table: %p\n", pci->iommu_table); } - if (pdn != dn) - PCI_DN(dn)->iommu_table = pci->iommu_table; + dev->dev.archdata.dma_data = pci->iommu_table; } -static void iommu_bus_setup_null(struct pci_bus *b) { } -static void iommu_dev_setup_null(struct pci_dev *d) { } - /* These are called very early. */ void iommu_init_early_pSeries(void) { if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { /* Direct I/O, IOMMU off */ - ppc_md.iommu_dev_setup = iommu_dev_setup_null; - ppc_md.iommu_bus_setup = iommu_bus_setup_null; - pci_direct_iommu_init(); - + ppc_md.pci_dma_dev_setup = NULL; + ppc_md.pci_dma_bus_setup = NULL; + pci_dma_ops = &dma_direct_ops; return; } @@ -572,19 +574,19 @@ void iommu_init_early_pSeries(void) ppc_md.tce_free = tce_free_pSeriesLP; } ppc_md.tce_get = tce_get_pSeriesLP; - ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP; - ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP; + ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP; + ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP; } else { ppc_md.tce_build = tce_build_pSeries; ppc_md.tce_free = tce_free_pSeries; ppc_md.tce_get = tce_get_pseries; - ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries; - ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries; + ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeries; + ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeries; } pSeries_reconfig_notifier_register(&iommu_reconfig_nb); - pci_iommu_init(); + pci_dma_ops = &dma_iommu_ops; } diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 6bfacc21708..bb0cb5c5b56 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -93,8 +93,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) if (list_empty(&dev->global_list)) { int i; - /* Need to setup IOMMU tables */ - ppc_md.iommu_dev_setup(dev); + /* Fill device archdata and setup iommu table */ + pcibios_setup_new_device(dev); if(fix_bus) pcibios_fixup_device_resources(dev, bus); diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 572b7846cc7..ac784bb5728 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -289,24 +289,15 @@ static void iommu_table_dart_setup(void) set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map); } -static void iommu_dev_setup_dart(struct pci_dev *dev) +static void pci_dma_dev_setup_dart(struct pci_dev *dev) { - struct device_node *dn; - /* We only have one iommu table on the mac for now, which makes * things simple. Setup all PCI devices to point to this table - * - * We must use pci_device_to_OF_node() to make sure that - * we get the real "final" pointer to the device in the - * pci_dev sysdata and not the temporary PHB one */ - dn = pci_device_to_OF_node(dev); - - if (dn) - PCI_DN(dn)->iommu_table = &iommu_table_dart; + dev->dev.archdata.dma_data = &iommu_table_dart; } -static void iommu_bus_setup_dart(struct pci_bus *bus) +static void pci_dma_bus_setup_dart(struct pci_bus *bus) { struct device_node *dn; @@ -321,9 +312,6 @@ static void iommu_bus_setup_dart(struct pci_bus *bus) PCI_DN(dn)->iommu_table = &iommu_table_dart; } -static void iommu_dev_setup_null(struct pci_dev *dev) { } -static void iommu_bus_setup_null(struct pci_bus *bus) { } - void iommu_init_early_dart(void) { struct device_node *dn; @@ -344,22 +332,21 @@ void iommu_init_early_dart(void) /* Initialize the DART HW */ if (dart_init(dn) == 0) { - ppc_md.iommu_dev_setup = iommu_dev_setup_dart; - ppc_md.iommu_bus_setup = iommu_bus_setup_dart; + ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart; + ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; /* Setup pci_dma ops */ - pci_iommu_init(); - + pci_dma_ops = &dma_iommu_ops; return; } bail: /* If init failed, use direct iommu and null setup functions */ - ppc_md.iommu_dev_setup = iommu_dev_setup_null; - ppc_md.iommu_bus_setup = iommu_bus_setup_null; + ppc_md.pci_dma_dev_setup = NULL; + ppc_md.pci_dma_bus_setup = NULL; /* Setup pci_dma ops */ - pci_direct_iommu_init(); + pci_dma_ops = &dma_direct_ops; } diff --git a/include/asm-powerpc/device.h b/include/asm-powerpc/device.h index d8f9872b0e2..228ab2a315b 100644 --- a/include/asm-powerpc/device.h +++ b/include/asm-powerpc/device.h @@ -3,5 +3,22 @@ * * This file is released under the GPLv2 */ -#include +#ifndef _ASM_POWERPC_DEVICE_H +#define _ASM_POWERPC_DEVICE_H +struct dma_mapping_ops; +struct device_node; + +struct dev_archdata { + /* Optional pointer to an OF device node */ + struct device_node *of_node; + + /* DMA operations on that device */ + struct dma_mapping_ops *dma_ops; + void *dma_data; + + /* NUMA node if applicable */ + int numa_node; +}; + +#endif /* _ASM_POWERPC_DEVICE_H */ diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h index 2ab9baf78bb..8367810c994 100644 --- a/include/asm-powerpc/dma-mapping.h +++ b/include/asm-powerpc/dma-mapping.h @@ -44,26 +44,148 @@ extern void __dma_sync_page(struct page *page, unsigned long offset, #endif /* ! CONFIG_NOT_COHERENT_CACHE */ #ifdef CONFIG_PPC64 +/* + * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO + */ +struct dma_mapping_ops { + void * (*alloc_coherent)(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag); + void (*free_coherent)(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle); + dma_addr_t (*map_single)(struct device *dev, void *ptr, + size_t size, enum dma_data_direction direction); + void (*unmap_single)(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction direction); + int (*map_sg)(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction); + void (*unmap_sg)(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction); + int (*dma_supported)(struct device *dev, u64 mask); + int (*dac_dma_supported)(struct device *dev, u64 mask); + int (*set_dma_mask)(struct device *dev, u64 dma_mask); +}; + +static inline struct dma_mapping_ops *get_dma_ops(struct device *dev) +{ + /* We don't handle the NULL dev case for ISA for now. We could + * do it via an out of line call but it is not needed for now. The + * only ISA DMA device we support is the floppy and we have a hack + * in the floppy driver directly to get a device for us. + */ + if (unlikely(dev == NULL || dev->archdata.dma_ops == NULL)) + return NULL; + return dev->archdata.dma_ops; +} + +static inline int dma_supported(struct device *dev, u64 mask) +{ + struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + + if (unlikely(dma_ops == NULL)) + return 0; + if (dma_ops->dma_supported == NULL) + return 1; + return dma_ops->dma_supported(dev, mask); +} + +static inline int dma_set_mask(struct device *dev, u64 dma_mask) +{ + struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + + if (unlikely(dma_ops == NULL)) + return -EIO; + if (dma_ops->set_dma_mask != NULL) + return dma_ops->set_dma_mask(dev, dma_mask); + if (!dev->dma_mask || !dma_supported(dev, *dev->dma_mask)) + return -EIO; + *dev->dma_mask = dma_mask; + return 0; +} + +static inline void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ + struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + + BUG_ON(!dma_ops); + return dma_ops->alloc_coherent(dev, size, dma_handle, flag); +} + +static inline void dma_free_coherent(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle) +{ + struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + + BUG_ON(!dma_ops); + dma_ops->free_coherent(dev, size, cpu_addr, dma_handle); +} + +static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, + size_t size, + enum dma_data_direction direction) +{ + struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + + BUG_ON(!dma_ops); + return dma_ops->map_single(dev, cpu_addr, size, direction); +} + +static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, + enum dma_data_direction direction) +{ + struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + + BUG_ON(!dma_ops); + dma_ops->unmap_single(dev, dma_addr, size, direction); +} + +static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + + BUG_ON(!dma_ops); + return dma_ops->map_single(dev, page_address(page) + offset, size, + direction); +} + +static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address, + size_t size, + enum dma_data_direction direction) +{ + struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + + BUG_ON(!dma_ops); + dma_ops->unmap_single(dev, dma_address, size, direction); +} + +static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) +{ + struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + + BUG_ON(!dma_ops); + return dma_ops->map_sg(dev, sg, nents, direction); +} + +static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nhwentries, + enum dma_data_direction direction) +{ + struct dma_mapping_ops *dma_ops = get_dma_ops(dev); + + BUG_ON(!dma_ops); + dma_ops->unmap_sg(dev, sg, nhwentries, direction); +} -extern int dma_supported(struct device *dev, u64 mask); -extern int dma_set_mask(struct device *dev, u64 dma_mask); -extern void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag); -extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, - dma_addr_t dma_handle); -extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, - size_t size, enum dma_data_direction direction); -extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, - size_t size, enum dma_data_direction direction); -extern dma_addr_t dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction direction); -extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, - size_t size, enum dma_data_direction direction); -extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction direction); -extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, - int nhwentries, enum dma_data_direction direction); + +/* + * Available generic sets of operations + */ +extern struct dma_mapping_ops dma_iommu_ops; +extern struct dma_mapping_ops dma_direct_ops; #else /* CONFIG_PPC64 */ @@ -261,25 +383,5 @@ static inline void dma_cache_sync(void *vaddr, size_t size, __dma_sync(vaddr, size, (int)direction); } -/* - * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO - */ -struct dma_mapping_ops { - void * (*alloc_coherent)(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag); - void (*free_coherent)(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle); - dma_addr_t (*map_single)(struct device *dev, void *ptr, - size_t size, enum dma_data_direction direction); - void (*unmap_single)(struct device *dev, dma_addr_t dma_addr, - size_t size, enum dma_data_direction direction); - int (*map_sg)(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction direction); - void (*unmap_sg)(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction direction); - int (*dma_supported)(struct device *dev, u64 mask); - int (*dac_dma_supported)(struct device *dev, u64 mask); -}; - #endif /* __KERNEL__ */ #endif /* _ASM_DMA_MAPPING_H */ diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h index 3493429b70f..66112114b8c 100644 --- a/include/asm-powerpc/ibmebus.h +++ b/include/asm-powerpc/ibmebus.h @@ -44,7 +44,6 @@ #include #include -extern struct dma_mapping_ops ibmebus_dma_ops; extern struct bus_type ibmebus_bus_type; struct ibmebus_dev { diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index 19e6f7e0a60..19403183dbb 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -79,22 +79,22 @@ extern void iommu_free_table(struct device_node *dn); extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, int nid); -extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl, - struct scatterlist *sglist, int nelems, unsigned long mask, - enum dma_data_direction direction); +extern int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, + int nelems, unsigned long mask, + enum dma_data_direction direction); extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, - int nelems, enum dma_data_direction direction); + int nelems, enum dma_data_direction direction); extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, - dma_addr_t *dma_handle, unsigned long mask, - gfp_t flag, int node); + dma_addr_t *dma_handle, unsigned long mask, + gfp_t flag, int node); extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, - void *vaddr, dma_addr_t dma_handle); + void *vaddr, dma_addr_t dma_handle); extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, - size_t size, unsigned long mask, - enum dma_data_direction direction); + size_t size, unsigned long mask, + enum dma_data_direction direction); extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, - size_t size, enum dma_data_direction direction); + size_t size, enum dma_data_direction direction); extern void iommu_init_early_pSeries(void); extern void iommu_init_early_iSeries(void); diff --git a/include/asm-powerpc/iseries/iommu.h b/include/asm-powerpc/iseries/iommu.h index 0edbfe10cb3..6e323a13ac3 100644 --- a/include/asm-powerpc/iseries/iommu.h +++ b/include/asm-powerpc/iseries/iommu.h @@ -21,11 +21,13 @@ * Boston, MA 02111-1307 USA */ +struct pci_dev; struct device_node; struct iommu_table; /* Creates table for an individual device node */ -extern void iommu_devnode_init_iSeries(struct device_node *dn); +extern void iommu_devnode_init_iSeries(struct pci_dev *pdev, + struct device_node *dn); /* Get table parameters from HV */ extern void iommu_table_getparms_iSeries(unsigned long busno, diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 162205f6264..ccc29744656 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -84,8 +84,8 @@ struct machdep_calls { unsigned long (*tce_get)(struct iommu_table *tbl, long index); void (*tce_flush)(struct iommu_table *tbl); - void (*iommu_dev_setup)(struct pci_dev *dev); - void (*iommu_bus_setup)(struct pci_bus *bus); + void (*pci_dma_dev_setup)(struct pci_dev *dev); + void (*pci_dma_bus_setup)(struct pci_bus *bus); #endif /* CONFIG_PPC64 */ int (*probe)(void); diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h index 1ef7e9edd1a..a889b2005bf 100644 --- a/include/asm-powerpc/of_device.h +++ b/include/asm-powerpc/of_device.h @@ -14,7 +14,7 @@ */ struct of_device { - struct device_node *node; /* OF device node */ + struct device_node *node; /* to be obsoleted */ u64 dma_mask; /* DMA mask */ struct device dev; /* Generic device interface */ }; diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index c7728605149..16f13319c76 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h @@ -70,15 +70,15 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) */ #define PCI_DISABLE_MWI -extern struct dma_mapping_ops pci_dma_ops; +extern struct dma_mapping_ops *pci_dma_ops; /* For DAC DMA, we currently don't support it by default, but * we let 64-bit platforms override this. */ static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask) { - if (pci_dma_ops.dac_dma_supported) - return pci_dma_ops.dac_dma_supported(&hwdev->dev, mask); + if (pci_dma_ops && pci_dma_ops->dac_dma_supported) + return pci_dma_ops->dac_dma_supported(&hwdev->dev, mask); return 0; } @@ -210,6 +210,8 @@ extern int remap_bus_range(struct pci_bus *bus); extern void pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus); +extern void pcibios_setup_new_device(struct pci_dev *dev); + extern void pcibios_claim_one_bus(struct pci_bus *b); extern struct pci_controller *init_phb_dynamic(struct device_node *dn); diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h index 4b51d42e141..0117b544ecb 100644 --- a/include/asm-powerpc/vio.h +++ b/include/asm-powerpc/vio.h @@ -45,7 +45,6 @@ struct iommu_table; * The vio_dev structure is used to describe virtual I/O devices. */ struct vio_dev { - struct iommu_table *iommu_table; /* vio_map_* uses this */ const char *name; const char *type; uint32_t unit_address; -- cgit v1.2.3-70-g09d2 From 803d4573e60bc890d7fbc040ad1c18c2dc7f8279 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:25:07 +1100 Subject: [POWERPC] Add "parent" struct device for PCI host bridges Add a "parent" struct device to our PCI host bridge data structure so that PCI can be rooted off another device in sysfs. Note that arch/ppc doesn't use it, only arch/powerpc, though it's available for both 32 and 64 bits. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_32.c | 5 ++++- arch/powerpc/kernel/pci_64.c | 2 +- include/asm-powerpc/pci-bridge.h | 1 + include/asm-ppc/pci-bridge.h | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index d32cd500d8b..0ad101a5fc5 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -1269,7 +1269,10 @@ pcibios_init(void) if (pci_assign_all_buses) hose->first_busno = next_busno; hose->last_busno = 0xff; - bus = pci_scan_bus(hose->first_busno, hose->ops, hose); + bus = pci_scan_bus_parented(hose->parent, hose->first_busno, + hose->ops, hose); + if (bus) + pci_bus_add_devices(bus); hose->last_busno = bus->subordinate; if (pci_assign_all_buses || next_busno <= hose->last_busno) next_busno = hose->last_busno + pcibios_assign_bus_offset; diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 5ffab8787b9..74e580d25c1 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -513,7 +513,7 @@ void __devinit scan_phb(struct pci_controller *hose) DBG("Scanning PHB %s\n", node ? node->full_name : ""); - bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node); + bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node); if (bus == NULL) { printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", hose->global_number); diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index 86ee46b09b8..7bb7f900980 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h @@ -25,6 +25,7 @@ struct pci_controller { int node; void *arch_data; struct list_head list_node; + struct device *parent; int first_busno; int last_busno; diff --git a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h index 9d5230689b3..6c955d0c1ef 100644 --- a/include/asm-ppc/pci-bridge.h +++ b/include/asm-ppc/pci-bridge.h @@ -43,6 +43,7 @@ struct pci_controller { struct pci_controller *next; struct pci_bus *bus; void *arch_data; + struct device *parent; int first_busno; int last_busno; -- cgit v1.2.3-70-g09d2 From 4c9d2800be5dfabf26acdeb401cbabe9edc1dcf2 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:25:08 +1100 Subject: [POWERPC] Generic OF platform driver for PCI host bridges. When enabled in Kconfig, it will pick up any of_platform_device matching it's match list (currently type "pci", "pcix", "pcie", or "ht" and setup a PHB for it. Platform must provide a ppc_md.pci_setup_phb() for it to work (for doing the necessary initialisations specific to a given PHB like setting up the config space ops). It's currently only available on 64 bits as the 32 bits PCI code can't quite cope with it in it's current form. I will fix that later. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 6 ++ arch/powerpc/kernel/of_platform.c | 103 +++++++++++++++++++++++++++++ arch/powerpc/kernel/pci_64.c | 9 +++ arch/powerpc/kernel/rtas_pci.c | 7 +- arch/powerpc/platforms/cell/setup.c | 1 + arch/powerpc/platforms/pseries/pci_dlpar.c | 2 +- include/asm-powerpc/machdep.h | 4 ++ include/asm-powerpc/ppc-pci.h | 12 ++-- 8 files changed, 134 insertions(+), 10 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 65588a6bd2f..3d26ba7ad76 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -223,6 +223,11 @@ config PPC_DCR depends on PPC_DCR_NATIVE || PPC_DCR_MMIO default y +config PPC_OF_PLATFORM_PCI + bool + depends on PPC64 # not supported on 32 bits yet + default n + config BOOKE bool depends on E200 || E500 @@ -469,6 +474,7 @@ config PPC_CELL_NATIVE bool select PPC_CELL select PPC_DCR_MMIO + select PPC_OF_PLATFORM_PCI select MPIC default n diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 7a0e77af7c9..6029543c1b5 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. * + * and Arnd Bergmann, IBM Corp. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -17,12 +18,15 @@ #include #include #include +#include #include #include #include #include #include +#include +#include /* * The list of OF IDs below is used for matching bus types in the @@ -377,3 +381,102 @@ struct of_device *of_find_device_by_phandle(phandle ph) return NULL; } EXPORT_SYMBOL(of_find_device_by_phandle); + + +#ifdef CONFIG_PPC_OF_PLATFORM_PCI + +/* The probing of PCI controllers from of_platform is currently + * 64 bits only, mostly due to gratuitous differences between + * the 32 and 64 bits PCI code on PowerPC and the 32 bits one + * lacking some bits needed here. + */ + +static int __devinit of_pci_phb_probe(struct of_device *dev, + const struct of_device_id *match) +{ + struct pci_controller *phb; + + /* Check if we can do that ... */ + if (ppc_md.pci_setup_phb == NULL) + return -ENODEV; + + printk(KERN_INFO "Setting up PCI bus %s\n", dev->node->full_name); + + /* Alloc and setup PHB data structure */ + phb = pcibios_alloc_controller(dev->node); + if (!phb) + return -ENODEV; + + /* Setup parent in sysfs */ + phb->parent = &dev->dev; + + /* Setup the PHB using arch provided callback */ + if (ppc_md.pci_setup_phb(phb)) { + pcibios_free_controller(phb); + return -ENODEV; + } + + /* Process "ranges" property */ + pci_process_bridge_OF_ranges(phb, dev->node, 0); + + /* Setup IO space. + * This will not work properly for ISA IOs, something needs to be done + * about it if we ever generalize that way of probing PCI brigdes + */ + pci_setup_phb_io_dynamic(phb, 0); + + /* Init pci_dn data structures */ + pci_devs_phb_init_dynamic(phb); + + /* Register devices with EEH */ +#ifdef CONFIG_EEH + if (dev->node->child) + eeh_add_device_tree_early(dev->node); +#endif /* CONFIG_EEH */ + + /* Scan the bus */ + scan_phb(phb); + + /* Claim resources. This might need some rework as well depending + * wether we are doing probe-only or not, like assigning unassigned + * resources etc... + */ + pcibios_claim_one_bus(phb->bus); + + /* Finish EEH setup */ +#ifdef CONFIG_EEH + eeh_add_device_tree_late(phb->bus); +#endif + + /* Add probed PCI devices to the device model */ + pci_bus_add_devices(phb->bus); + + return 0; +} + +static struct of_device_id of_pci_phb_ids[] = { + { .type = "pci", }, + { .type = "pcix", }, + { .type = "pcie", }, + { .type = "pciex", }, + { .type = "ht", }, + {} +}; + +static struct of_platform_driver of_pci_phb_driver = { + .name = "of-pci", + .match_table = of_pci_phb_ids, + .probe = of_pci_phb_probe, + .driver = { + .multithread_probe = 1, + }, +}; + +static __init int of_pci_phb_init(void) +{ + return of_register_platform_driver(&of_pci_phb_driver); +} + +device_initcall(of_pci_phb_init); + +#endif /* CONFIG_PPC_OF_PLATFORM_PCI */ diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 74e580d25c1..d800e19ea56 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -210,6 +210,10 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev) void pcibios_free_controller(struct pci_controller *phb) { + spin_lock(&hose_spinlock); + list_del(&phb->list_node); + spin_unlock(&hose_spinlock); + if (phb->is_dynamic) kfree(phb); } @@ -1242,6 +1246,11 @@ static void __devinit do_bus_setup(struct pci_bus *bus) void __devinit pcibios_fixup_bus(struct pci_bus *bus) { struct pci_dev *dev = bus->self; + struct device_node *np; + + np = pci_bus_to_OF_node(bus); + + DBG("pcibios_fixup_bus(%s)\n", np ? np->full_name : ""); if (dev && pci_probe_only && (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 2576e12d725..03cacc25a0a 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -257,8 +257,10 @@ static int phb_set_bus_ranges(struct device_node *dev, return 0; } -int __devinit setup_phb(struct device_node *dev, struct pci_controller *phb) +int __devinit rtas_setup_phb(struct pci_controller *phb) { + struct device_node *dev = phb->arch_data; + if (is_python(dev)) python_countermeasures(dev); @@ -290,7 +292,7 @@ unsigned long __init find_and_init_phbs(void) phb = pcibios_alloc_controller(node); if (!phb) continue; - setup_phb(node, phb); + rtas_setup_phb(phb); pci_process_bridge_OF_ranges(phb, node, 0); pci_setup_phb_io(phb, index == 0); index++; @@ -362,7 +364,6 @@ int pcibios_remove_root_bus(struct pci_controller *phb) } } - list_del(&phb->list_node); pcibios_free_controller(phb); return 0; diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index b39753f16d4..7e18420166c 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -256,6 +256,7 @@ define_machine(cell) { .check_legacy_ioport = cell_check_legacy_ioport, .progress = cell_progress, .init_IRQ = cell_init_irq, + .pci_setup_phb = rtas_setup_phb, #ifdef CONFIG_KEXEC .machine_kexec = default_machine_kexec, .machine_kexec_prepare = default_machine_kexec_prepare, diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index bb0cb5c5b56..ac56b868913 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -195,7 +195,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) phb = pcibios_alloc_controller(dn); if (!phb) return NULL; - setup_phb(dn, phb); + rtas_setup_phb(phb); pci_process_bridge_OF_ranges(phb, dn, 0); pci_setup_phb_io_dynamic(phb, primary); diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index ccc29744656..23580cf5504 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -26,6 +26,7 @@ struct device_node; struct iommu_table; struct rtc_time; struct file; +struct pci_controller; #ifdef CONFIG_KEXEC struct kimage; #endif @@ -107,6 +108,9 @@ struct machdep_calls { int (*pci_probe_mode)(struct pci_bus *); void (*pci_irq_fixup)(struct pci_dev *dev); + /* To setup PHBs when using automatic OF platform driver for PCI */ + int (*pci_setup_phb)(struct pci_controller *host); + void (*restart)(char *cmd); void (*power_off)(void); void (*halt)(void); diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index 8894d1d4226..ab6eddb518c 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h @@ -36,14 +36,14 @@ typedef void *(*traverse_func)(struct device_node *me, void *data); void *traverse_pci_devices(struct device_node *start, traverse_func pre, void *data); -void pci_devs_phb_init(void); -void pci_devs_phb_init_dynamic(struct pci_controller *phb); -int setup_phb(struct device_node *dev, struct pci_controller *phb); -void __devinit scan_phb(struct pci_controller *hose); +extern void pci_devs_phb_init(void); +extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); +extern void scan_phb(struct pci_controller *hose); /* From rtas_pci.h */ -void init_pci_config_tokens (void); -unsigned long get_phb_buid (struct device_node *); +extern void init_pci_config_tokens (void); +extern unsigned long get_phb_buid (struct device_node *); +extern int rtas_setup_phb(struct pci_controller *phb); /* From pSeries_pci.h */ extern void pSeries_final_fixup(void); -- cgit v1.2.3-70-g09d2 From 4cb3cee03d558fd457cb58f56c80a2a09a66110c Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:25:10 +1100 Subject: [POWERPC] Allow hooking of PCI MMIO & PIO accessors on 64 bits This patch reworks the way iSeries hooks on PCI IO operations (both MMIO and PIO) and provides a generic way for other platforms to do so (we have need to do that for various other platforms). While reworking the IO ops, I ended up doing some spring cleaning in io.h and eeh.h which I might want to split into 2 or 3 patches (among others, eeh.h had a lot of useless stuff in it). A side effect is that EEH for PIO should work now (it used to pass IO ports down to the eeh address check functions which is bogus). Also, new are MMIO "repeat" ops, which other archs like ARM already had, and that we have too now: readsb, readsw, readsl, writesb, writesw, writesl. In the long run, I might also make EEH use the hooks instead of wrapping at the toplevel, which would make things even cleaner and relegate EEH completely in platforms/iseries, but we have to measure the performance impact there (though it's really only on MMIO reads) Since I also need to hook on ioremap, I shuffled the functions a bit there. I introduced ioremap_flags() to use by drivers who want to pass explicit flags to ioremap (and it can be hooked). The old __ioremap() is still there as a low level and cannot be hooked, thus drivers who use it should migrate unless they know they want the low level version. The patch "arch provides generic iomap missing accessors" (should be number 4 in this series) is a pre-requisite to provide full iomap API support with this patch. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 10 + arch/powerpc/kernel/Makefile | 6 +- arch/powerpc/kernel/io.c | 18 +- arch/powerpc/kernel/pci_64.c | 2 +- arch/powerpc/kernel/setup_64.c | 7 + arch/powerpc/mm/pgtable_64.c | 46 ++- arch/powerpc/platforms/iseries/pci.c | 370 ++++++++----------- arch/powerpc/platforms/iseries/setup.c | 12 + include/asm-powerpc/eeh.h | 118 ++---- include/asm-powerpc/ide.h | 7 + include/asm-powerpc/io-defs.h | 56 +++ include/asm-powerpc/io.h | 641 +++++++++++++++++++-------------- include/asm-powerpc/machdep.h | 4 + include/asm-ppc/io.h | 12 +- 14 files changed, 701 insertions(+), 608 deletions(-) create mode 100644 include/asm-powerpc/io-defs.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 3d26ba7ad76..3e89d9d3493 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -394,6 +394,7 @@ config PPC_PSERIES config PPC_ISERIES bool "IBM Legacy iSeries" depends on PPC_MULTIPLATFORM && PPC64 + select PPC_INDIRECT_IO config PPC_CHRP bool "Common Hardware Reference Platform (CHRP) based machines" @@ -548,6 +549,15 @@ config PPC_970_NAP bool default n +config PPC_INDIRECT_IO + bool + select GENERIC_IOMAP + default n + +config GENERIC_IOMAP + bool + default n + source "drivers/cpufreq/Kconfig" config CPU_FREQ_PMAC diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index eba8d118e21..600954df07a 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -62,7 +62,7 @@ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o module-$(CONFIG_PPC64) += module_64.o obj-$(CONFIG_MODULES) += $(module-y) -pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o iomap.o +pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci32-$(CONFIG_PPC32) := pci_32.o obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) kexec-$(CONFIG_PPC64) := machine_kexec_64.o @@ -71,6 +71,10 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y) obj-$(CONFIG_AUDIT) += audit.o obj64-$(CONFIG_AUDIT) += compat_audit.o +ifneq ($(CONFIG_PPC_INDIRECT_IO),y) +pci64-$(CONFIG_PPC64) += iomap.o +endif + ifeq ($(CONFIG_PPC_ISERIES),y) $(obj)/head_64.o: $(obj)/lparmap.s AFLAGS_head_64.o += -I$(obj) diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c index e98180686b3..c1aa07524c2 100644 --- a/arch/powerpc/kernel/io.c +++ b/arch/powerpc/kernel/io.c @@ -25,13 +25,11 @@ #include #include -void _insb(volatile u8 __iomem *port, void *buf, long count) +void _insb(const volatile u8 __iomem *port, void *buf, long count) { u8 *tbuf = buf; u8 tmp; - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - if (unlikely(count <= 0)) return; asm volatile("sync"); @@ -48,8 +46,6 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count) { const u8 *tbuf = buf; - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - if (unlikely(count <= 0)) return; asm volatile("sync"); @@ -60,13 +56,11 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count) } EXPORT_SYMBOL(_outsb); -void _insw_ns(volatile u16 __iomem *port, void *buf, long count) +void _insw_ns(const volatile u16 __iomem *port, void *buf, long count) { u16 *tbuf = buf; u16 tmp; - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - if (unlikely(count <= 0)) return; asm volatile("sync"); @@ -83,8 +77,6 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count) { const u16 *tbuf = buf; - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - if (unlikely(count <= 0)) return; asm volatile("sync"); @@ -95,13 +87,11 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count) } EXPORT_SYMBOL(_outsw_ns); -void _insl_ns(volatile u32 __iomem *port, void *buf, long count) +void _insl_ns(const volatile u32 __iomem *port, void *buf, long count) { u32 *tbuf = buf; u32 tmp; - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - if (unlikely(count <= 0)) return; asm volatile("sync"); @@ -118,8 +108,6 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count) { const u32 *tbuf = buf; - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - if (unlikely(count <= 0)) return; asm volatile("sync"); diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index d800e19ea56..afee470de92 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -1137,7 +1137,7 @@ int unmap_bus_range(struct pci_bus *bus) if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) return 1; - if (iounmap_explicit((void __iomem *) start_virt, size)) + if (__iounmap_explicit((void __iomem *) start_virt, size)) return 1; return 0; diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index f7ad64acf47..f602a53b1b7 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -599,3 +599,10 @@ void __init setup_per_cpu_areas(void) } } #endif + + +#ifdef CONFIG_PPC_INDIRECT_IO +struct ppc_pci_io ppc_pci_io; +EXPORT_SYMBOL(ppc_pci_io); +#endif /* CONFIG_PPC_INDIRECT_IO */ + diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index ac64f4aaa50..e9b21846ccb 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -129,22 +129,12 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa, return (void __iomem *) (ea + (addr & ~PAGE_MASK)); } - -void __iomem * -ioremap(unsigned long addr, unsigned long size) -{ - return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED); -} - void __iomem * __ioremap(unsigned long addr, unsigned long size, unsigned long flags) { unsigned long pa, ea; void __iomem *ret; - if (firmware_has_feature(FW_FEATURE_ISERIES)) - return (void __iomem *)addr; - /* * Choose an address to map it to. * Once the imalloc system is running, we use it. @@ -178,6 +168,25 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size, return ret; } + +void __iomem * ioremap(unsigned long addr, unsigned long size) +{ + unsigned long flags = _PAGE_NO_CACHE | _PAGE_GUARDED; + + if (ppc_md.ioremap) + return ppc_md.ioremap(addr, size, flags); + return __ioremap(addr, size, flags); +} + +void __iomem * ioremap_flags(unsigned long addr, unsigned long size, + unsigned long flags) +{ + if (ppc_md.ioremap) + return ppc_md.ioremap(addr, size, flags); + return __ioremap(addr, size, flags); +} + + #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) int __ioremap_explicit(unsigned long pa, unsigned long ea, @@ -235,13 +244,10 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea, * * XXX what about calls before mem_init_done (ie python_countermeasures()) */ -void iounmap(volatile void __iomem *token) +void __iounmap(void __iomem *token) { void *addr; - if (firmware_has_feature(FW_FEATURE_ISERIES)) - return; - if (!mem_init_done) return; @@ -250,6 +256,14 @@ void iounmap(volatile void __iomem *token) im_free(addr); } +void iounmap(void __iomem *token) +{ + if (ppc_md.iounmap) + ppc_md.iounmap(token); + else + __iounmap(token); +} + static int iounmap_subset_regions(unsigned long addr, unsigned long size) { struct vm_struct *area; @@ -268,7 +282,7 @@ static int iounmap_subset_regions(unsigned long addr, unsigned long size) return 0; } -int iounmap_explicit(volatile void __iomem *start, unsigned long size) +int __iounmap_explicit(void __iomem *start, unsigned long size) { struct vm_struct *area; unsigned long addr; @@ -303,8 +317,10 @@ int iounmap_explicit(volatile void __iomem *start, unsigned long size) } EXPORT_SYMBOL(ioremap); +EXPORT_SYMBOL(ioremap_flags); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); +EXPORT_SYMBOL(__iounmap); void __iomem * reserve_phb_iospace(unsigned long size) { diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index a90ae42a7bc..4a06d9c3498 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -155,53 +155,6 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, Error_Text, Bus, SubBus, AgentId, HvRc); } -/* - * iSeries_pcibios_init - * - * Description: - * This function checks for all possible system PCI host bridges that connect - * PCI buses. The system hypervisor is queried as to the guest partition - * ownership status. A pci_controller is built for any bus which is partially - * owned or fully owned by this guest partition. - */ -void iSeries_pcibios_init(void) -{ - struct pci_controller *phb; - struct device_node *root = of_find_node_by_path("/"); - struct device_node *node = NULL; - - if (root == NULL) { - printk(KERN_CRIT "iSeries_pcibios_init: can't find root " - "of device tree\n"); - return; - } - while ((node = of_get_next_child(root, node)) != NULL) { - HvBusNumber bus; - const u32 *busp; - - if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) - continue; - - busp = get_property(node, "bus-range", NULL); - if (busp == NULL) - continue; - bus = *busp; - printk("bus %d appears to exist\n", bus); - phb = pcibios_alloc_controller(node); - if (phb == NULL) - continue; - - phb->pci_mem_offset = phb->local_number = bus; - phb->first_busno = bus; - phb->last_busno = bus; - phb->ops = &iSeries_pci_ops; - } - - of_node_put(root); - - pci_devs_phb_init(); -} - /* * iSeries_pci_final_fixup(void) */ @@ -438,11 +391,7 @@ static inline struct device_node *xlate_iomm_address( /* * Read MM I/O Instructions for the iSeries * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal - * else, data is returned in big Endian format. - * - * iSeries_Read_Byte = Read Byte ( 8 bit) - * iSeries_Read_Word = Read Word (16 bit) - * iSeries_Read_Long = Read Long (32 bit) + * else, data is returned in Big Endian format. */ static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) { @@ -462,14 +411,15 @@ static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) num_printed = 0; } if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress); + printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", + IoAddress); return 0xff; } do { HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); - return (u8)ret.value; + return ret.value; } static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) @@ -490,7 +440,8 @@ static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) num_printed = 0; } if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress); + printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", + IoAddress); return 0xffff; } do { @@ -498,7 +449,7 @@ static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) BarOffset, 0); } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); - return swab16((u16)ret.value); + return ret.value; } static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) @@ -519,7 +470,8 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) num_printed = 0; } if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress); + printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", + IoAddress); return 0xffffffff; } do { @@ -527,15 +479,12 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) BarOffset, 0); } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); - return swab32((u32)ret.value); + return ret.value; } /* * Write MM I/O Instructions for the iSeries * - * iSeries_Write_Byte = Write Byte (8 bit) - * iSeries_Write_Word = Write Word(16 bit) - * iSeries_Write_Long = Write Long(32 bit) */ static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) { @@ -581,11 +530,12 @@ static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress) num_printed = 0; } if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress); + printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", + IoAddress); return; } do { - rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); + rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, data, 0); } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); } @@ -607,231 +557,221 @@ static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress) num_printed = 0; } if (num_printed++ < 10) - printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress); + printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", + IoAddress); return; } do { - rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); + rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, data, 0); } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); } -extern unsigned char __raw_readb(const volatile void __iomem *addr) +static u8 iseries_readb(const volatile void __iomem *addr) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - return *(volatile unsigned char __force *)addr; + return iSeries_Read_Byte(addr); } -EXPORT_SYMBOL(__raw_readb); -extern unsigned short __raw_readw(const volatile void __iomem *addr) +static u16 iseries_readw(const volatile void __iomem *addr) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - return *(volatile unsigned short __force *)addr; + return le16_to_cpu(iSeries_Read_Word(addr)); } -EXPORT_SYMBOL(__raw_readw); -extern unsigned int __raw_readl(const volatile void __iomem *addr) +static u32 iseries_readl(const volatile void __iomem *addr) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - return *(volatile unsigned int __force *)addr; + return le32_to_cpu(iSeries_Read_Long(addr)); } -EXPORT_SYMBOL(__raw_readl); -extern unsigned long __raw_readq(const volatile void __iomem *addr) +static u16 iseries_readw_be(const volatile void __iomem *addr) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - return *(volatile unsigned long __force *)addr; + return iSeries_Read_Word(addr); } -EXPORT_SYMBOL(__raw_readq); -extern void __raw_writeb(unsigned char v, volatile void __iomem *addr) +static u32 iseries_readl_be(const volatile void __iomem *addr) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - *(volatile unsigned char __force *)addr = v; + return iSeries_Read_Long(addr); } -EXPORT_SYMBOL(__raw_writeb); -extern void __raw_writew(unsigned short v, volatile void __iomem *addr) +static void iseries_writeb(u8 data, volatile void __iomem *addr) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - *(volatile unsigned short __force *)addr = v; + iSeries_Write_Byte(data, addr); } -EXPORT_SYMBOL(__raw_writew); -extern void __raw_writel(unsigned int v, volatile void __iomem *addr) +static void iseries_writew(u16 data, volatile void __iomem *addr) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - *(volatile unsigned int __force *)addr = v; + iSeries_Write_Word(cpu_to_le16(data), addr); } -EXPORT_SYMBOL(__raw_writel); -extern void __raw_writeq(unsigned long v, volatile void __iomem *addr) +static void iseries_writel(u32 data, volatile void __iomem *addr) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - *(volatile unsigned long __force *)addr = v; + iSeries_Write_Long(cpu_to_le32(data), addr); } -EXPORT_SYMBOL(__raw_writeq); -int in_8(const volatile unsigned char __iomem *addr) +static void iseries_writew_be(u16 data, volatile void __iomem *addr) { - if (firmware_has_feature(FW_FEATURE_ISERIES)) - return iSeries_Read_Byte(addr); - return __in_8(addr); + iSeries_Write_Word(data, addr); } -EXPORT_SYMBOL(in_8); -void out_8(volatile unsigned char __iomem *addr, int val) +static void iseries_writel_be(u32 data, volatile void __iomem *addr) { - if (firmware_has_feature(FW_FEATURE_ISERIES)) - iSeries_Write_Byte(val, addr); - else - __out_8(addr, val); + iSeries_Write_Long(data, addr); } -EXPORT_SYMBOL(out_8); -int in_le16(const volatile unsigned short __iomem *addr) +static void iseries_readsb(const volatile void __iomem *addr, void *buf, + unsigned long count) { - if (firmware_has_feature(FW_FEATURE_ISERIES)) - return iSeries_Read_Word(addr); - return __in_le16(addr); + u8 *dst = buf; + while(count-- > 0) + *(dst++) = iSeries_Read_Byte(addr); } -EXPORT_SYMBOL(in_le16); -int in_be16(const volatile unsigned short __iomem *addr) +static void iseries_readsw(const volatile void __iomem *addr, void *buf, + unsigned long count) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - return __in_be16(addr); + u16 *dst = buf; + while(count-- > 0) + *(dst++) = iSeries_Read_Word(addr); } -EXPORT_SYMBOL(in_be16); -void out_le16(volatile unsigned short __iomem *addr, int val) +static void iseries_readsl(const volatile void __iomem *addr, void *buf, + unsigned long count) { - if (firmware_has_feature(FW_FEATURE_ISERIES)) - iSeries_Write_Word(val, addr); - else - __out_le16(addr, val); + u32 *dst = buf; + while(count-- > 0) + *(dst++) = iSeries_Read_Long(addr); } -EXPORT_SYMBOL(out_le16); -void out_be16(volatile unsigned short __iomem *addr, int val) +static void iseries_writesb(volatile void __iomem *addr, const void *buf, + unsigned long count) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - __out_be16(addr, val); + const u8 *src = buf; + while(count-- > 0) + iSeries_Write_Byte(*(src++), addr); } -EXPORT_SYMBOL(out_be16); -unsigned in_le32(const volatile unsigned __iomem *addr) +static void iseries_writesw(volatile void __iomem *addr, const void *buf, + unsigned long count) { - if (firmware_has_feature(FW_FEATURE_ISERIES)) - return iSeries_Read_Long(addr); - return __in_le32(addr); + const u16 *src = buf; + while(count-- > 0) + iSeries_Write_Word(*(src++), addr); } -EXPORT_SYMBOL(in_le32); -unsigned in_be32(const volatile unsigned __iomem *addr) +static void iseries_writesl(volatile void __iomem *addr, const void *buf, + unsigned long count) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - return __in_be32(addr); + const u32 *src = buf; + while(count-- > 0) + iSeries_Write_Long(*(src++), addr); } -EXPORT_SYMBOL(in_be32); -void out_le32(volatile unsigned __iomem *addr, int val) +static void iseries_memset_io(volatile void __iomem *addr, int c, + unsigned long n) { - if (firmware_has_feature(FW_FEATURE_ISERIES)) - iSeries_Write_Long(val, addr); - else - __out_le32(addr, val); -} -EXPORT_SYMBOL(out_le32); + volatile char __iomem *d = addr; -void out_be32(volatile unsigned __iomem *addr, int val) -{ - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - - __out_be32(addr, val); + while (n-- > 0) + iSeries_Write_Byte(c, d++); } -EXPORT_SYMBOL(out_be32); -unsigned long in_le64(const volatile unsigned long __iomem *addr) +static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src, + unsigned long n) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); + char *d = dest; + const volatile char __iomem *s = src; - return __in_le64(addr); + while (n-- > 0) + *d++ = iSeries_Read_Byte(s++); } -EXPORT_SYMBOL(in_le64); -unsigned long in_be64(const volatile unsigned long __iomem *addr) +static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src, + unsigned long n) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); + const char *s = src; + volatile char __iomem *d = dest; - return __in_be64(addr); + while (n-- > 0) + iSeries_Write_Byte(*s++, d++); } -EXPORT_SYMBOL(in_be64); - -void out_le64(volatile unsigned long __iomem *addr, unsigned long val) -{ - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); - __out_le64(addr, val); -} -EXPORT_SYMBOL(out_le64); +/* We only set MMIO ops. The default PIO ops will be default + * to the MMIO ops + pci_io_base which is 0 on iSeries as + * expected so both should work. + * + * Note that we don't implement the readq/writeq versions as + * I don't know of an HV call for doing so. Thus, the default + * operation will be used instead, which will fault a the value + * return by iSeries for MMIO addresses always hits a non mapped + * area. This is as good as the BUG() we used to have there. + */ +static struct ppc_pci_io __initdata iseries_pci_io = { + .readb = iseries_readb, + .readw = iseries_readw, + .readl = iseries_readl, + .readw_be = iseries_readw_be, + .readl_be = iseries_readl_be, + .writeb = iseries_writeb, + .writew = iseries_writew, + .writel = iseries_writel, + .writew_be = iseries_writew_be, + .writel_be = iseries_writel_be, + .readsb = iseries_readsb, + .readsw = iseries_readsw, + .readsl = iseries_readsl, + .writesb = iseries_writesb, + .writesw = iseries_writesw, + .writesl = iseries_writesl, + .memset_io = iseries_memset_io, + .memcpy_fromio = iseries_memcpy_fromio, + .memcpy_toio = iseries_memcpy_toio, +}; -void out_be64(volatile unsigned long __iomem *addr, unsigned long val) +/* + * iSeries_pcibios_init + * + * Description: + * This function checks for all possible system PCI host bridges that connect + * PCI buses. The system hypervisor is queried as to the guest partition + * ownership status. A pci_controller is built for any bus which is partially + * owned or fully owned by this guest partition. + */ +void __init iSeries_pcibios_init(void) { - BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); + struct pci_controller *phb; + struct device_node *root = of_find_node_by_path("/"); + struct device_node *node = NULL; - __out_be64(addr, val); -} -EXPORT_SYMBOL(out_be64); + /* Install IO hooks */ + ppc_pci_io = iseries_pci_io; -void memset_io(volatile void __iomem *addr, int c, unsigned long n) -{ - if (firmware_has_feature(FW_FEATURE_ISERIES)) { - volatile char __iomem *d = addr; + if (root == NULL) { + printk(KERN_CRIT "iSeries_pcibios_init: can't find root " + "of device tree\n"); + return; + } + while ((node = of_get_next_child(root, node)) != NULL) { + HvBusNumber bus; + const u32 *busp; - while (n-- > 0) { - iSeries_Write_Byte(c, d++); - } - } else - eeh_memset_io(addr, c, n); -} -EXPORT_SYMBOL(memset_io); + if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) + continue; -void memcpy_fromio(void *dest, const volatile void __iomem *src, - unsigned long n) -{ - if (firmware_has_feature(FW_FEATURE_ISERIES)) { - char *d = dest; - const volatile char __iomem *s = src; + busp = get_property(node, "bus-range", NULL); + if (busp == NULL) + continue; + bus = *busp; + printk("bus %d appears to exist\n", bus); + phb = pcibios_alloc_controller(node); + if (phb == NULL) + continue; - while (n-- > 0) { - *d++ = iSeries_Read_Byte(s++); - } - } else - eeh_memcpy_fromio(dest, src, n); -} -EXPORT_SYMBOL(memcpy_fromio); + phb->pci_mem_offset = phb->local_number = bus; + phb->first_busno = bus; + phb->last_busno = bus; + phb->ops = &iSeries_pci_ops; + } -void memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) -{ - if (firmware_has_feature(FW_FEATURE_ISERIES)) { - const char *s = src; - volatile char __iomem *d = dest; + of_node_put(root); - while (n-- > 0) { - iSeries_Write_Byte(*s++, d++); - } - } else - eeh_memcpy_toio(dest, src, n); + pci_devs_phb_init(); } -EXPORT_SYMBOL(memcpy_toio); + diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index cd8965ec9dd..2f16d9330cf 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -617,6 +617,16 @@ static void iseries_dedicated_idle(void) void __init iSeries_init_IRQ(void) { } #endif +static void __iomem *iseries_ioremap(unsigned long address, unsigned long size, + unsigned long flags) +{ + return (void __iomem *)address; +} + +static void iseries_iounmap(void __iomem *token) +{ +} + /* * iSeries has no legacy IO, anything calling this function has to * fail or bad things will happen @@ -655,6 +665,8 @@ define_machine(iseries) { .progress = iSeries_progress, .probe = iseries_probe, .check_legacy_ioport = iseries_check_legacy_ioport, + .ioremap = iseries_ioremap, + .iounmap = iseries_iounmap, /* XXX Implement enable_pmcs for iSeries */ }; diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h index 6a784396660..66481bbf270 100644 --- a/include/asm-powerpc/eeh.h +++ b/include/asm-powerpc/eeh.h @@ -120,10 +120,6 @@ static inline u8 eeh_readb(const volatile void __iomem *addr) return eeh_check_failure(addr, val); return val; } -static inline void eeh_writeb(u8 val, volatile void __iomem *addr) -{ - out_8(addr, val); -} static inline u16 eeh_readw(const volatile void __iomem *addr) { @@ -132,21 +128,6 @@ static inline u16 eeh_readw(const volatile void __iomem *addr) return eeh_check_failure(addr, val); return val; } -static inline void eeh_writew(u16 val, volatile void __iomem *addr) -{ - out_le16(addr, val); -} -static inline u16 eeh_raw_readw(const volatile void __iomem *addr) -{ - u16 val = in_be16(addr); - if (EEH_POSSIBLE_ERROR(val, u16)) - return eeh_check_failure(addr, val); - return val; -} -static inline void eeh_raw_writew(u16 val, volatile void __iomem *addr) { - volatile u16 __iomem *vaddr = (volatile u16 __iomem *) addr; - out_be16(vaddr, val); -} static inline u32 eeh_readl(const volatile void __iomem *addr) { @@ -155,44 +136,38 @@ static inline u32 eeh_readl(const volatile void __iomem *addr) return eeh_check_failure(addr, val); return val; } -static inline void eeh_writel(u32 val, volatile void __iomem *addr) -{ - out_le32(addr, val); -} -static inline u32 eeh_raw_readl(const volatile void __iomem *addr) + +static inline u64 eeh_readq(const volatile void __iomem *addr) { - u32 val = in_be32(addr); - if (EEH_POSSIBLE_ERROR(val, u32)) + u64 val = in_le64(addr); + if (EEH_POSSIBLE_ERROR(val, u64)) return eeh_check_failure(addr, val); return val; } -static inline void eeh_raw_writel(u32 val, volatile void __iomem *addr) -{ - out_be32(addr, val); -} -static inline u64 eeh_readq(const volatile void __iomem *addr) +static inline u16 eeh_readw_be(const volatile void __iomem *addr) { - u64 val = in_le64(addr); - if (EEH_POSSIBLE_ERROR(val, u64)) + u16 val = in_be16(addr); + if (EEH_POSSIBLE_ERROR(val, u16)) return eeh_check_failure(addr, val); return val; } -static inline void eeh_writeq(u64 val, volatile void __iomem *addr) + +static inline u32 eeh_readl_be(const volatile void __iomem *addr) { - out_le64(addr, val); + u32 val = in_be32(addr); + if (EEH_POSSIBLE_ERROR(val, u32)) + return eeh_check_failure(addr, val); + return val; } -static inline u64 eeh_raw_readq(const volatile void __iomem *addr) + +static inline u64 eeh_readq_be(const volatile void __iomem *addr) { u64 val = in_be64(addr); if (EEH_POSSIBLE_ERROR(val, u64)) return eeh_check_failure(addr, val); return val; } -static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr) -{ - out_be64(addr, val); -} #define EEH_CHECK_ALIGN(v,a) \ ((((unsigned long)(v)) & ((a) - 1)) == 0) @@ -292,68 +267,29 @@ static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src, #undef EEH_CHECK_ALIGN -static inline u8 eeh_inb(unsigned long port) -{ - u8 val; - val = in_8((u8 __iomem *)(port+pci_io_base)); - if (EEH_POSSIBLE_ERROR(val, u8)) - return eeh_check_failure((void __iomem *)(port), val); - return val; -} - -static inline void eeh_outb(u8 val, unsigned long port) -{ - out_8((u8 __iomem *)(port+pci_io_base), val); -} - -static inline u16 eeh_inw(unsigned long port) -{ - u16 val; - val = in_le16((u16 __iomem *)(port+pci_io_base)); - if (EEH_POSSIBLE_ERROR(val, u16)) - return eeh_check_failure((void __iomem *)(port), val); - return val; -} - -static inline void eeh_outw(u16 val, unsigned long port) -{ - out_le16((u16 __iomem *)(port+pci_io_base), val); -} - -static inline u32 eeh_inl(unsigned long port) -{ - u32 val; - val = in_le32((u32 __iomem *)(port+pci_io_base)); - if (EEH_POSSIBLE_ERROR(val, u32)) - return eeh_check_failure((void __iomem *)(port), val); - return val; -} - -static inline void eeh_outl(u32 val, unsigned long port) -{ - out_le32((u32 __iomem *)(port+pci_io_base), val); -} - /* in-string eeh macros */ -static inline void eeh_insb(unsigned long port, void * buf, int ns) +static inline void eeh_readsb(const volatile void __iomem *addr, void * buf, + int ns) { - _insb((u8 __iomem *)(port+pci_io_base), buf, ns); + _insb(addr, buf, ns); if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8)) - eeh_check_failure((void __iomem *)(port), *(u8*)buf); + eeh_check_failure(addr, *(u8*)buf); } -static inline void eeh_insw_ns(unsigned long port, void * buf, int ns) +static inline void eeh_readsw(const volatile void __iomem *addr, void * buf, + int ns) { - _insw_ns((u16 __iomem *)(port+pci_io_base), buf, ns); + _insw(addr, buf, ns); if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16)) - eeh_check_failure((void __iomem *)(port), *(u16*)buf); + eeh_check_failure(addr, *(u16*)buf); } -static inline void eeh_insl_ns(unsigned long port, void * buf, int nl) +static inline void eeh_readsl(const volatile void __iomem *addr, void * buf, + int nl) { - _insl_ns((u32 __iomem *)(port+pci_io_base), buf, nl); + _insl(addr, buf, nl); if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32)) - eeh_check_failure((void __iomem *)(port), *(u32*)buf); + eeh_check_failure(addr, *(u32*)buf); } #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h index c8390f9485d..60a8fc42997 100644 --- a/include/asm-powerpc/ide.h +++ b/include/asm-powerpc/ide.h @@ -22,10 +22,17 @@ #endif #endif +#ifdef __powerpc64__ +#define __ide_mm_insw(p, a, c) readsw((void __iomem *)(p), (a), (c)) +#define __ide_mm_insl(p, a, c) readsl((void __iomem *)(p), (a), (c)) +#define __ide_mm_outsw(p, a, c) writesw((void __iomem *)(p), (a), (c)) +#define __ide_mm_outsl(p, a, c) writesl((void __iomem *)(p), (a), (c)) +#else #define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 __iomem *)(p), (a), (c)) #define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 __iomem *)(p), (a), (c)) #define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 __iomem *)(p), (a), (c)) #define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 __iomem *)(p), (a), (c)) +#endif #ifndef __powerpc64__ #include diff --git a/include/asm-powerpc/io-defs.h b/include/asm-powerpc/io-defs.h new file mode 100644 index 00000000000..5a660f1130d --- /dev/null +++ b/include/asm-powerpc/io-defs.h @@ -0,0 +1,56 @@ +/* This file is meant to be include multiple times by other headers */ + +DEF_PCI_AC_RET(readb, u8, (const PCI_IO_ADDR addr), (addr)) +DEF_PCI_AC_RET(readw, u16, (const PCI_IO_ADDR addr), (addr)) +DEF_PCI_AC_RET(readl, u32, (const PCI_IO_ADDR addr), (addr)) +DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr)) +DEF_PCI_AC_RET(readw_be, u16, (const PCI_IO_ADDR addr), (addr)) +DEF_PCI_AC_RET(readl_be, u32, (const PCI_IO_ADDR addr), (addr)) +DEF_PCI_AC_RET(readq_be, u64, (const PCI_IO_ADDR addr), (addr)) +DEF_PCI_AC_NORET(writeb, (u8 val, PCI_IO_ADDR addr), (val, addr)) +DEF_PCI_AC_NORET(writew, (u16 val, PCI_IO_ADDR addr), (val, addr)) +DEF_PCI_AC_NORET(writel, (u32 val, PCI_IO_ADDR addr), (val, addr)) +DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr)) +DEF_PCI_AC_NORET(writew_be, (u16 val, PCI_IO_ADDR addr), (val, addr)) +DEF_PCI_AC_NORET(writel_be, (u32 val, PCI_IO_ADDR addr), (val, addr)) +DEF_PCI_AC_NORET(writeq_be, (u64 val, PCI_IO_ADDR addr), (val, addr)) + +DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port)) +DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port)) +DEF_PCI_AC_RET(inl, u32, (unsigned long port), (port)) +DEF_PCI_AC_NORET(outb, (u8 val, unsigned long port), (val, port)) +DEF_PCI_AC_NORET(outw, (u16 val, unsigned long port), (val, port)) +DEF_PCI_AC_NORET(outl, (u32 val, unsigned long port), (val, port)) + +DEF_PCI_AC_NORET(readsb, (const PCI_IO_ADDR a, void *b, unsigned long c), \ + (a, b, c)) +DEF_PCI_AC_NORET(readsw, (const PCI_IO_ADDR a, void *b, unsigned long c), \ + (a, b, c)) +DEF_PCI_AC_NORET(readsl, (const PCI_IO_ADDR a, void *b, unsigned long c), \ + (a, b, c)) +DEF_PCI_AC_NORET(writesb, (PCI_IO_ADDR a, const void *b, unsigned long c), \ + (a, b, c)) +DEF_PCI_AC_NORET(writesw, (PCI_IO_ADDR a, const void *b, unsigned long c), \ + (a, b, c)) +DEF_PCI_AC_NORET(writesl, (PCI_IO_ADDR a, const void *b, unsigned long c), \ + (a, b, c)) + +DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c), \ + (p, b, c)) +DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c), \ + (p, b, c)) +DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c), \ + (p, b, c)) +DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c), \ + (p, b, c)) +DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c), \ + (p, b, c)) +DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c), \ + (p, b, c)) + +DEF_PCI_AC_NORET(memset_io, (PCI_IO_ADDR a, int c, unsigned long n), \ + (a, c, n)) +DEF_PCI_AC_NORET(memcpy_fromio,(void *d,const PCI_IO_ADDR s,unsigned long n), \ + (d, s, n)) +DEF_PCI_AC_NORET(memcpy_toio,(PCI_IO_ADDR d,const void *s,unsigned long n), \ + (d, s, n)) diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index c2c5f14b5f5..03e843fc143 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h @@ -31,57 +31,122 @@ extern int check_legacy_ioport(unsigned long base_port); #define SLOW_DOWN_IO +/* + * + * Low level MMIO accessors + * + * This provides the non-bus specific accessors to MMIO. Those are PowerPC + * specific and thus shouldn't be used in generic code. The accessors + * provided here are: + * + * in_8, in_le16, in_be16, in_le32, in_be32, in_le64, in_be64 + * out_8, out_le16, out_be16, out_le32, out_be32, out_le64, out_be64 + * _insb, _insw_ns, _insl_ns, _outsb, _outsw_ns, _outsl_ns + * + * Those operate directly on a kernel virtual address. Note that the prototype + * for the out_* accessors has the arguments in opposite order from the usual + * linux PCI accessors. Unlike those, they take the address first and the value + * next. + * + * Note: I might drop the _ns suffix on the stream operations soon as it is + * simply normal for stream operations to not swap in the first place. + * + */ + +#define IO_SET_SYNC_FLAG() do { get_paca()->io_sync = 1; } while(0) + +#define DEF_MMIO_IN(name, type, insn) \ +static inline type name(const volatile type __iomem *addr) \ +{ \ + type ret; \ + __asm__ __volatile__("sync;" insn ";twi 0,%0,0;isync" \ + : "=r" (ret) : "r" (addr), "m" (*addr)); \ + return ret; \ +} + +#define DEF_MMIO_OUT(name, type, insn) \ +static inline void name(volatile type __iomem *addr, type val) \ +{ \ + __asm__ __volatile__("sync;" insn \ + : "=m" (*addr) : "r" (val), "r" (addr)); \ + IO_SET_SYNC_FLAG(); \ +} + + +#define DEF_MMIO_IN_BE(name, size, insn) \ + DEF_MMIO_IN(name, u##size, __stringify(insn)"%U2%X2 %0,%2") +#define DEF_MMIO_IN_LE(name, size, insn) \ + DEF_MMIO_IN(name, u##size, __stringify(insn)" %0,0,%1") + +#define DEF_MMIO_OUT_BE(name, size, insn) \ + DEF_MMIO_OUT(name, u##size, __stringify(insn)"%U0%X0 %1,%0") +#define DEF_MMIO_OUT_LE(name, size, insn) \ + DEF_MMIO_OUT(name, u##size, __stringify(insn)" %1,0,%2") + +DEF_MMIO_IN_BE(in_8, 8, lbz); +DEF_MMIO_IN_BE(in_be16, 16, lhz); +DEF_MMIO_IN_BE(in_be32, 32, lwz); +DEF_MMIO_IN_BE(in_be64, 64, ld); +DEF_MMIO_IN_LE(in_le16, 16, lhbrx); +DEF_MMIO_IN_LE(in_le32, 32, lwbrx); + +DEF_MMIO_OUT_BE(out_8, 8, stb); +DEF_MMIO_OUT_BE(out_be16, 16, sth); +DEF_MMIO_OUT_BE(out_be32, 32, stw); +DEF_MMIO_OUT_BE(out_be64, 64, std); +DEF_MMIO_OUT_LE(out_le16, 16, sthbrx); +DEF_MMIO_OUT_LE(out_le32, 32, stwbrx); + +/* There is no asm instructions for 64 bits reverse loads and stores */ +static inline u64 in_le64(const volatile u64 __iomem *addr) +{ + return le64_to_cpu(in_be64(addr)); +} + +static inline void out_le64(volatile u64 __iomem *addr, u64 val) +{ + out_be64(addr, cpu_to_le64(val)); +} + +/* + * Low level IO stream instructions are defined out of line for now + */ +extern void _insb(const volatile u8 __iomem *addr, void *buf, long count); +extern void _outsb(volatile u8 __iomem *addr,const void *buf,long count); +extern void _insw_ns(const volatile u16 __iomem *addr, void *buf, long count); +extern void _outsw_ns(volatile u16 __iomem *addr, const void *buf, long count); +extern void _insl_ns(const volatile u32 __iomem *addr, void *buf, long count); +extern void _outsl_ns(volatile u32 __iomem *addr, const void *buf, long count); + +/* The _ns naming is historical and will be removed. For now, just #define + * the non _ns equivalent names + */ +#define _insw _insw_ns +#define _insl _insl_ns +#define _outsw _outsw_ns +#define _outsl _outsl_ns + +/* + * + * PCI and standard ISA accessors + * + * Those are globally defined linux accessors for devices on PCI or ISA + * busses. They follow the Linux defined semantics. The current implementation + * for PowerPC is as close as possible to the x86 version of these, and thus + * provides fairly heavy weight barriers for the non-raw versions + * + * In addition, they support a hook mechanism when CONFIG_PPC_INDIRECT_IO + * allowing the platform to provide its own implementation of some or all + * of the accessors. + */ + extern unsigned long isa_io_base; extern unsigned long pci_io_base; -#ifdef CONFIG_PPC_ISERIES - -extern int in_8(const volatile unsigned char __iomem *addr); -extern void out_8(volatile unsigned char __iomem *addr, int val); -extern int in_le16(const volatile unsigned short __iomem *addr); -extern int in_be16(const volatile unsigned short __iomem *addr); -extern void out_le16(volatile unsigned short __iomem *addr, int val); -extern void out_be16(volatile unsigned short __iomem *addr, int val); -extern unsigned in_le32(const volatile unsigned __iomem *addr); -extern unsigned in_be32(const volatile unsigned __iomem *addr); -extern void out_le32(volatile unsigned __iomem *addr, int val); -extern void out_be32(volatile unsigned __iomem *addr, int val); -extern unsigned long in_le64(const volatile unsigned long __iomem *addr); -extern unsigned long in_be64(const volatile unsigned long __iomem *addr); -extern void out_le64(volatile unsigned long __iomem *addr, unsigned long val); -extern void out_be64(volatile unsigned long __iomem *addr, unsigned long val); - -extern unsigned char __raw_readb(const volatile void __iomem *addr); -extern unsigned short __raw_readw(const volatile void __iomem *addr); -extern unsigned int __raw_readl(const volatile void __iomem *addr); -extern unsigned long __raw_readq(const volatile void __iomem *addr); -extern void __raw_writeb(unsigned char v, volatile void __iomem *addr); -extern void __raw_writew(unsigned short v, volatile void __iomem *addr); -extern void __raw_writel(unsigned int v, volatile void __iomem *addr); -extern void __raw_writeq(unsigned long v, volatile void __iomem *addr); - -extern void memset_io(volatile void __iomem *addr, int c, unsigned long n); -extern void memcpy_fromio(void *dest, const volatile void __iomem *src, - unsigned long n); -extern void memcpy_toio(volatile void __iomem *dest, const void *src, - unsigned long n); - -#else /* CONFIG_PPC_ISERIES */ - -#define in_8(addr) __in_8((addr)) -#define out_8(addr, val) __out_8((addr), (val)) -#define in_le16(addr) __in_le16((addr)) -#define in_be16(addr) __in_be16((addr)) -#define out_le16(addr, val) __out_le16((addr), (val)) -#define out_be16(addr, val) __out_be16((addr), (val)) -#define in_le32(addr) __in_le32((addr)) -#define in_be32(addr) __in_be32((addr)) -#define out_le32(addr, val) __out_le32((addr), (val)) -#define out_be32(addr, val) __out_be32((addr), (val)) -#define in_le64(addr) __in_le64((addr)) -#define in_be64(addr) __in_be64((addr)) -#define out_le64(addr, val) __out_le64((addr), (val)) -#define out_be64(addr, val) __out_be64((addr), (val)) + +/* + * Non ordered and non-swapping "raw" accessors + */ static inline unsigned char __raw_readb(const volatile void __iomem *addr) { @@ -115,52 +180,203 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) { *(volatile unsigned long __force *)addr = v; } -#define memset_io(a,b,c) eeh_memset_io((a),(b),(c)) -#define memcpy_fromio(a,b,c) eeh_memcpy_fromio((a),(b),(c)) -#define memcpy_toio(a,b,c) eeh_memcpy_toio((a),(b),(c)) -#endif /* CONFIG_PPC_ISERIES */ /* - * The insw/outsw/insl/outsl macros don't do byte-swapping. - * They are only used in practice for transferring buffers which - * are arrays of bytes, and byte-swapping is not appropriate in - * that case. - paulus */ -#define insb(port, buf, ns) eeh_insb((port), (buf), (ns)) -#define insw(port, buf, ns) eeh_insw_ns((port), (buf), (ns)) -#define insl(port, buf, nl) eeh_insl_ns((port), (buf), (nl)) - -#define outsb(port, buf, ns) _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns)) -#define outsw(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns)) -#define outsl(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl)) - -#define readb(addr) eeh_readb(addr) -#define readw(addr) eeh_readw(addr) -#define readl(addr) eeh_readl(addr) -#define readq(addr) eeh_readq(addr) -#define writeb(data, addr) eeh_writeb((data), (addr)) -#define writew(data, addr) eeh_writew((data), (addr)) -#define writel(data, addr) eeh_writel((data), (addr)) -#define writeq(data, addr) eeh_writeq((data), (addr)) -#define inb(port) eeh_inb((unsigned long)port) -#define outb(val, port) eeh_outb(val, (unsigned long)port) -#define inw(port) eeh_inw((unsigned long)port) -#define outw(val, port) eeh_outw(val, (unsigned long)port) -#define inl(port) eeh_inl((unsigned long)port) -#define outl(val, port) eeh_outl(val, (unsigned long)port) + * + * PCI PIO and MMIO accessors. + * + */ + +#include + +/* Shortcut to the MMIO argument pointer */ +#define PCI_IO_ADDR volatile void __iomem * + +/* Indirect IO address tokens: + * + * When CONFIG_PPC_INDIRECT_IO is set, the platform can provide hooks + * on all IOs. + * + * To help platforms who may need to differenciate MMIO addresses in + * their hooks, a bitfield is reserved for use by the platform near the + * top of MMIO addresses (not PIO, those have to cope the hard way). + * + * This bit field is 12 bits and is at the top of the IO virtual + * addresses PCI_IO_INDIRECT_TOKEN_MASK. + * + * The kernel virtual space is thus: + * + * 0xD000000000000000 : vmalloc + * 0xD000080000000000 : PCI PHB IO space + * 0xD000080080000000 : ioremap + * 0xD0000fffffffffff : end of ioremap region + * + * Since the top 4 bits are reserved as the region ID, we use thus + * the next 12 bits and keep 4 bits available for the future if the + * virtual address space is ever to be extended. + * + * The direct IO mapping operations will then mask off those bits + * before doing the actual access, though that only happen when + * CONFIG_PPC_INDIRECT_IO is set, thus be careful when you use that + * mechanism + */ + +#ifdef CONFIG_PPC_INDIRECT_IO +#define PCI_IO_IND_TOKEN_MASK 0x0fff000000000000ul +#define PCI_IO_IND_TOKEN_SHIFT 48 +#define PCI_FIX_ADDR(addr) \ + ((PCI_IO_ADDR)(((unsigned long)(addr)) & ~PCI_IO_IND_TOKEN_MASK)) +#define PCI_GET_ADDR_TOKEN(addr) \ + (((unsigned long)(addr) & PCI_IO_IND_TOKEN_MASK) >> \ + PCI_IO_IND_TOKEN_SHIFT) +#define PCI_SET_ADDR_TOKEN(addr, token) \ +do { \ + unsigned long __a = (unsigned long)(addr); \ + __a &= ~PCI_IO_IND_TOKEN_MASK; \ + __a |= ((unsigned long)(token)) << PCI_IO_IND_TOKEN_SHIFT; \ + (addr) = (void __iomem *)__a; \ +} while(0) +#else +#define PCI_FIX_ADDR(addr) (addr) +#endif + +/* The "__do_*" operations below provide the actual "base" implementation + * for each of the defined acccessor. Some of them use the out_* functions + * directly, some of them still use EEH, though we might change that in the + * future. Those macros below provide the necessary argument swapping and + * handling of the IO base for PIO. + * + * They are themselves used by the macros that define the actual accessors + * and can be used by the hooks if any. + * + * Note that PIO operations are always defined in terms of their corresonding + * MMIO operations. That allows platforms like iSeries who want to modify the + * behaviour of both to only hook on the MMIO version and get both. It's also + * possible to hook directly at the toplevel PIO operation if they have to + * be handled differently + */ +#define __do_writeb(val, addr) out_8(PCI_FIX_ADDR(addr), val) +#define __do_writew(val, addr) out_le16(PCI_FIX_ADDR(addr), val) +#define __do_writel(val, addr) out_le32(PCI_FIX_ADDR(addr), val) +#define __do_writeq(val, addr) out_le64(PCI_FIX_ADDR(addr), val) +#define __do_writew_be(val, addr) out_be16(PCI_FIX_ADDR(addr), val) +#define __do_writel_be(val, addr) out_be32(PCI_FIX_ADDR(addr), val) +#define __do_writeq_be(val, addr) out_be64(PCI_FIX_ADDR(addr), val) +#define __do_readb(addr) eeh_readb(PCI_FIX_ADDR(addr)) +#define __do_readw(addr) eeh_readw(PCI_FIX_ADDR(addr)) +#define __do_readl(addr) eeh_readl(PCI_FIX_ADDR(addr)) +#define __do_readq(addr) eeh_readq(PCI_FIX_ADDR(addr)) +#define __do_readw_be(addr) eeh_readw_be(PCI_FIX_ADDR(addr)) +#define __do_readl_be(addr) eeh_readl_be(PCI_FIX_ADDR(addr)) +#define __do_readq_be(addr) eeh_readq_be(PCI_FIX_ADDR(addr)) + +#define __do_outb(val, port) writeb(val,(PCI_IO_ADDR)pci_io_base+port); +#define __do_outw(val, port) writew(val,(PCI_IO_ADDR)pci_io_base+port); +#define __do_outl(val, port) writel(val,(PCI_IO_ADDR)pci_io_base+port); +#define __do_inb(port) readb((PCI_IO_ADDR)pci_io_base + port); +#define __do_inw(port) readw((PCI_IO_ADDR)pci_io_base + port); +#define __do_inl(port) readl((PCI_IO_ADDR)pci_io_base + port); + +#define __do_readsb(a, b, n) eeh_readsb(PCI_FIX_ADDR(a), (b), (n)) +#define __do_readsw(a, b, n) eeh_readsw(PCI_FIX_ADDR(a), (b), (n)) +#define __do_readsl(a, b, n) eeh_readsl(PCI_FIX_ADDR(a), (b), (n)) +#define __do_writesb(a, b, n) _outsb(PCI_FIX_ADDR(a),(b),(n)) +#define __do_writesw(a, b, n) _outsw(PCI_FIX_ADDR(a),(b),(n)) +#define __do_writesl(a, b, n) _outsl(PCI_FIX_ADDR(a),(b),(n)) + +#define __do_insb(p, b, n) readsb((PCI_IO_ADDR)pci_io_base+(p), (b), (n)) +#define __do_insw(p, b, n) readsw((PCI_IO_ADDR)pci_io_base+(p), (b), (n)) +#define __do_insl(p, b, n) readsl((PCI_IO_ADDR)pci_io_base+(p), (b), (n)) +#define __do_outsb(p, b, n) writesb((PCI_IO_ADDR)pci_io_base+(p),(b),(n)) +#define __do_outsw(p, b, n) writesw((PCI_IO_ADDR)pci_io_base+(p),(b),(n)) +#define __do_outsl(p, b, n) writesl((PCI_IO_ADDR)pci_io_base+(p),(b),(n)) + +#define __do_memset_io(addr, c, n) eeh_memset_io(PCI_FIX_ADDR(addr), c, n) +#define __do_memcpy_fromio(dst, src, n) eeh_memcpy_fromio(dst, \ + PCI_FIX_ADDR(src), n) +#define __do_memcpy_toio(dst, src, n) eeh_memcpy_toio(PCI_FIX_ADDR(dst), \ + src, n) + +#ifdef CONFIG_PPC_INDIRECT_IO +#define DEF_PCI_HOOK(x) x +#else +#define DEF_PCI_HOOK(x) NULL +#endif + +/* Structure containing all the hooks */ +extern struct ppc_pci_io { + +#define DEF_PCI_AC_RET(name, ret, at, al) ret (*name) at; +#define DEF_PCI_AC_NORET(name, at, al) void (*name) at; + +#include + +#undef DEF_PCI_AC_RET +#undef DEF_PCI_AC_NORET + +} ppc_pci_io; + +/* The inline wrappers */ +#define DEF_PCI_AC_RET(name, ret, at, al) \ +static inline ret name at \ +{ \ + if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL) \ + return ppc_pci_io.name al; \ + return __do_##name al; \ +} + +#define DEF_PCI_AC_NORET(name, at, al) \ +static inline void name at \ +{ \ + if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL) \ + ppc_pci_io.name al; \ + else \ + __do_##name al; \ +} + +#include + +#undef DEF_PCI_AC_RET +#undef DEF_PCI_AC_NORET + +/* Some drivers check for the presence of readq & writeq with + * a #ifdef, so we make them happy here. + */ +#define readq readq +#define writeq writeq + +/* Nothing to do for cache stuff x*/ + +#define dma_cache_inv(_start,_size) do { } while (0) +#define dma_cache_wback(_start,_size) do { } while (0) +#define dma_cache_wback_inv(_start,_size) do { } while (0) + + +/* + * Convert a physical pointer to a virtual kernel pointer for /dev/mem + * access + */ +#define xlate_dev_mem_ptr(p) __va(p) + +/* + * Convert a virtual cached pointer to an uncached pointer + */ +#define xlate_dev_kmem_ptr(p) p +/* + * We don't do relaxed operations yet, at least not with this semantic + */ #define readb_relaxed(addr) readb(addr) #define readw_relaxed(addr) readw(addr) #define readl_relaxed(addr) readl(addr) #define readq_relaxed(addr) readq(addr) -extern void _insb(volatile u8 __iomem *port, void *buf, long count); -extern void _outsb(volatile u8 __iomem *port, const void *buf, long count); -extern void _insw_ns(volatile u16 __iomem *port, void *buf, long count); -extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count); -extern void _insl_ns(volatile u32 __iomem *port, void *buf, long count); -extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count); - +/* + * Enforce synchronisation of stores vs. spin_unlock + * (this does it explicitely, though our implementation of spin_unlock + * does it implicitely too) + */ static inline void mmiowb(void) { unsigned long tmp; @@ -170,6 +386,23 @@ static inline void mmiowb(void) : "memory"); } +static inline void iosync(void) +{ + __asm__ __volatile__ ("sync" : : : "memory"); +} + +/* Enforce in-order execution of data I/O. + * No distinction between read/write on PPC; use eieio for all three. + * Those are fairly week though. They don't provide a barrier between + * MMIO and cacheable storage nor do they provide a barrier vs. locks, + * they only provide barriers between 2 __raw MMIO operations and + * possibly break write combining. + */ +#define iobarrier_rw() eieio() +#define iobarrier_r() eieio() +#define iobarrier_w() eieio() + + /* * output pause versions need a delay at least for the * w83c105 ide controller in a p610. @@ -185,11 +418,6 @@ static inline void mmiowb(void) #define IO_SPACE_LIMIT ~(0UL) -extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr, - unsigned long size, unsigned long flags); -extern void __iomem *__ioremap(unsigned long address, unsigned long size, - unsigned long flags); - /** * ioremap - map bus memory into CPU space * @address: bus address of the memory @@ -200,14 +428,70 @@ extern void __iomem *__ioremap(unsigned long address, unsigned long size, * writew/writel functions and the other mmio helpers. The returned * address is not guaranteed to be usable directly as a virtual * address. + * + * We provide a few variations of it: + * + * * ioremap is the standard one and provides non-cacheable guarded mappings + * and can be hooked by the platform via ppc_md + * + * * ioremap_flags allows to specify the page flags as an argument and can + * also be hooked by the platform via ppc_md + * + * * ioremap_nocache is identical to ioremap + * + * * iounmap undoes such a mapping and can be hooked + * + * * __ioremap_explicit (and the pending __iounmap_explicit) are low level + * functions to create hand-made mappings for use only by the PCI code + * and cannot currently be hooked. + * + * * __ioremap is the low level implementation used by ioremap and + * ioremap_flags and cannot be hooked (but can be used by a hook on one + * of the previous ones) + * + * * __iounmap, is the low level implementation used by iounmap and cannot + * be hooked (but can be used by a hook on iounmap) + * */ extern void __iomem *ioremap(unsigned long address, unsigned long size); - +extern void __iomem *ioremap_flags(unsigned long address, unsigned long size, + unsigned long flags); #define ioremap_nocache(addr, size) ioremap((addr), (size)) -extern int iounmap_explicit(volatile void __iomem *addr, unsigned long size); -extern void iounmap(volatile void __iomem *addr); +extern void iounmap(void __iomem *addr); + +extern void __iomem *__ioremap(unsigned long address, unsigned long size, + unsigned long flags); +extern void __iounmap(void __iomem *addr); + +extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr, + unsigned long size, unsigned long flags); +extern int __iounmap_explicit(void __iomem *start, unsigned long size); + extern void __iomem * reserve_phb_iospace(unsigned long size); + +/* + * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation + * which needs some additional definitions here. They basically allow PIO + * space overall to be 1GB. This will work as long as we never try to use + * iomap to map MMIO below 1GB which should be fine on ppc64 + */ +#define HAVE_ARCH_PIO_SIZE 1 +#define PIO_OFFSET 0x00000000UL +#define PIO_MASK 0x3fffffffUL +#define PIO_RESERVED 0x40000000UL + +#define mmio_read16be(addr) readw_be(addr) +#define mmio_read32be(addr) readl_be(addr) +#define mmio_write16be(val, addr) writew_be(val, addr) +#define mmio_write32be(val, addr) writel_be(val, addr) +#define mmio_insb(addr, dst, count) readsb(addr, dst, count) +#define mmio_insw(addr, dst, count) readsw(addr, dst, count) +#define mmio_insl(addr, dst, count) readsl(addr, dst, count) +#define mmio_outsb(addr, src, count) writesb(addr, src, count) +#define mmio_outsw(addr, src, count) writesw(addr, src, count) +#define mmio_outsl(addr, src, count) writesl(addr, src, count) + /** * virt_to_phys - map virtual addresses to physical * @address: address to remap @@ -254,177 +538,6 @@ static inline void * phys_to_virt(unsigned long address) */ #define BIO_VMERGE_BOUNDARY 0 -static inline void iosync(void) -{ - __asm__ __volatile__ ("sync" : : : "memory"); -} - -/* Enforce in-order execution of data I/O. - * No distinction between read/write on PPC; use eieio for all three. - */ -#define iobarrier_rw() eieio() -#define iobarrier_r() eieio() -#define iobarrier_w() eieio() - -/* - * 8, 16 and 32 bit, big and little endian I/O operations, with barrier. - * These routines do not perform EEH-related I/O address translation, - * and should not be used directly by device drivers. Use inb/readb - * instead. - */ -static inline int __in_8(const volatile unsigned char __iomem *addr) -{ - int ret; - - __asm__ __volatile__("sync; lbz%U1%X1 %0,%1; twi 0,%0,0; isync" - : "=r" (ret) : "m" (*addr)); - return ret; -} - -static inline void __out_8(volatile unsigned char __iomem *addr, int val) -{ - __asm__ __volatile__("sync; stb%U0%X0 %1,%0" - : "=m" (*addr) : "r" (val)); - get_paca()->io_sync = 1; -} - -static inline int __in_le16(const volatile unsigned short __iomem *addr) -{ - int ret; - - __asm__ __volatile__("sync; lhbrx %0,0,%1; twi 0,%0,0; isync" - : "=r" (ret) : "r" (addr), "m" (*addr)); - return ret; -} - -static inline int __in_be16(const volatile unsigned short __iomem *addr) -{ - int ret; - - __asm__ __volatile__("sync; lhz%U1%X1 %0,%1; twi 0,%0,0; isync" - : "=r" (ret) : "m" (*addr)); - return ret; -} - -static inline void __out_le16(volatile unsigned short __iomem *addr, int val) -{ - __asm__ __volatile__("sync; sthbrx %1,0,%2" - : "=m" (*addr) : "r" (val), "r" (addr)); - get_paca()->io_sync = 1; -} - -static inline void __out_be16(volatile unsigned short __iomem *addr, int val) -{ - __asm__ __volatile__("sync; sth%U0%X0 %1,%0" - : "=m" (*addr) : "r" (val)); - get_paca()->io_sync = 1; -} - -static inline unsigned __in_le32(const volatile unsigned __iomem *addr) -{ - unsigned ret; - - __asm__ __volatile__("sync; lwbrx %0,0,%1; twi 0,%0,0; isync" - : "=r" (ret) : "r" (addr), "m" (*addr)); - return ret; -} - -static inline unsigned __in_be32(const volatile unsigned __iomem *addr) -{ - unsigned ret; - - __asm__ __volatile__("sync; lwz%U1%X1 %0,%1; twi 0,%0,0; isync" - : "=r" (ret) : "m" (*addr)); - return ret; -} - -static inline void __out_le32(volatile unsigned __iomem *addr, int val) -{ - __asm__ __volatile__("sync; stwbrx %1,0,%2" : "=m" (*addr) - : "r" (val), "r" (addr)); - get_paca()->io_sync = 1; -} - -static inline void __out_be32(volatile unsigned __iomem *addr, int val) -{ - __asm__ __volatile__("sync; stw%U0%X0 %1,%0" - : "=m" (*addr) : "r" (val)); - get_paca()->io_sync = 1; -} - -static inline unsigned long __in_le64(const volatile unsigned long __iomem *addr) -{ - unsigned long tmp, ret; - - __asm__ __volatile__( - "sync\n" - "ld %1,0(%2)\n" - "twi 0,%1,0\n" - "isync\n" - "rldimi %0,%1,5*8,1*8\n" - "rldimi %0,%1,3*8,2*8\n" - "rldimi %0,%1,1*8,3*8\n" - "rldimi %0,%1,7*8,4*8\n" - "rldicl %1,%1,32,0\n" - "rlwimi %0,%1,8,8,31\n" - "rlwimi %0,%1,24,16,23\n" - : "=r" (ret) , "=r" (tmp) : "b" (addr) , "m" (*addr)); - return ret; -} - -static inline unsigned long __in_be64(const volatile unsigned long __iomem *addr) -{ - unsigned long ret; - - __asm__ __volatile__("sync; ld%U1%X1 %0,%1; twi 0,%0,0; isync" - : "=r" (ret) : "m" (*addr)); - return ret; -} - -static inline void __out_le64(volatile unsigned long __iomem *addr, unsigned long val) -{ - unsigned long tmp; - - __asm__ __volatile__( - "rldimi %0,%1,5*8,1*8\n" - "rldimi %0,%1,3*8,2*8\n" - "rldimi %0,%1,1*8,3*8\n" - "rldimi %0,%1,7*8,4*8\n" - "rldicl %1,%1,32,0\n" - "rlwimi %0,%1,8,8,31\n" - "rlwimi %0,%1,24,16,23\n" - "sync\n" - "std %0,0(%3)" - : "=&r" (tmp) , "=&r" (val) : "1" (val) , "b" (addr) , "m" (*addr)); - get_paca()->io_sync = 1; -} - -static inline void __out_be64(volatile unsigned long __iomem *addr, unsigned long val) -{ - __asm__ __volatile__("sync; std%U0%X0 %1,%0" : "=m" (*addr) : "r" (val)); - get_paca()->io_sync = 1; -} - -#include - -/* Nothing to do */ - -#define dma_cache_inv(_start,_size) do { } while (0) -#define dma_cache_wback(_start,_size) do { } while (0) -#define dma_cache_wback_inv(_start,_size) do { } while (0) - - -/* - * Convert a physical pointer to a virtual kernel pointer for /dev/mem - * access - */ -#define xlate_dev_mem_ptr(p) __va(p) - -/* - * Convert a virtual cached pointer to an uncached pointer - */ -#define xlate_dev_kmem_ptr(p) p - #endif /* __KERNEL__ */ #endif /* CONFIG_PPC64 */ diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 23580cf5504..8c1a2dfe5cc 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -87,6 +87,10 @@ struct machdep_calls { void (*tce_flush)(struct iommu_table *tbl); void (*pci_dma_dev_setup)(struct pci_dev *dev); void (*pci_dma_bus_setup)(struct pci_bus *bus); + + void __iomem * (*ioremap)(unsigned long addr, unsigned long size, + unsigned long flags); + void (*iounmap)(void __iomem *token); #endif /* CONFIG_PPC64 */ int (*probe)(void); diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index b744baf9e20..bfb639f9e42 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -321,12 +321,12 @@ __do_out_asm(outl, "stwbrx") #define inl_p(port) inl((port)) #define outl_p(val, port) outl((val), (port)) -extern void _insb(volatile u8 __iomem *port, void *buf, long count); -extern void _outsb(volatile u8 __iomem *port, const void *buf, long count); -extern void _insw_ns(volatile u16 __iomem *port, void *buf, long count); -extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count); -extern void _insl_ns(volatile u32 __iomem *port, void *buf, long count); -extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count); +extern void _insb(const volatile u8 __iomem *addr, void *buf, long count); +extern void _outsb(volatile u8 __iomem *addr,const void *buf,long count); +extern void _insw_ns(const volatile u16 __iomem *addr, void *buf, long count); +extern void _outsw_ns(volatile u16 __iomem *addr, const void *buf, long count); +extern void _insl_ns(const volatile u32 __iomem *addr, void *buf, long count); +extern void _outsl_ns(volatile u32 __iomem *addr, const void *buf, long count); #define IO_SPACE_LIMIT ~0 -- cgit v1.2.3-70-g09d2 From 92b20c40dcca2d441f367da57e7665cce15c492a Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:25:14 +1100 Subject: [POWERPC] Add an optional offset to direct DMA on 64 bits This patch adds an optional global offset that can be added to DMA addresses when using the direct DMA operations. That brings it a step closer to the 32 bits direct DMA operations, and makes it useable on Cell when the MMU is disabled and we are using a spider southbridge. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/dma_64.c | 11 ++++++++--- include/asm-powerpc/dma-mapping.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c index 4e655119978..1d1dc76606a 100644 --- a/arch/powerpc/kernel/dma_64.c +++ b/arch/powerpc/kernel/dma_64.c @@ -111,7 +111,11 @@ EXPORT_SYMBOL(dma_iommu_ops); /* * Generic direct DMA implementation + * + * This implementation supports a global offset that can be applied if + * the address at which memory is visible to devices is not 0. */ +unsigned long dma_direct_offset; static void *dma_direct_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) @@ -122,7 +126,7 @@ static void *dma_direct_alloc_coherent(struct device *dev, size_t size, ret = (void *)__get_free_pages(flag, get_order(size)); if (ret != NULL) { memset(ret, 0, size); - *dma_handle = virt_to_abs(ret); + *dma_handle = virt_to_abs(ret) | dma_direct_offset; } return ret; } @@ -137,7 +141,7 @@ static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction direction) { - return virt_to_abs(ptr); + return virt_to_abs(ptr) | dma_direct_offset; } static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr, @@ -152,7 +156,8 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sg, int i; for (i = 0; i < nents; i++, sg++) { - sg->dma_address = page_to_phys(sg->page) + sg->offset; + sg->dma_address = (page_to_phys(sg->page) + sg->offset) | + dma_direct_offset; sg->dma_length = sg->length; } diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h index 8367810c994..7e38b5fddad 100644 --- a/include/asm-powerpc/dma-mapping.h +++ b/include/asm-powerpc/dma-mapping.h @@ -187,6 +187,8 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, extern struct dma_mapping_ops dma_iommu_ops; extern struct dma_mapping_ops dma_direct_ops; +extern unsigned long dma_direct_offset; + #else /* CONFIG_PPC64 */ #define dma_supported(dev, mask) (1) -- cgit v1.2.3-70-g09d2 From 165785e5c0be3ad43e8b8eadfbd25e92c2cd002a Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Sat, 11 Nov 2006 17:25:18 +1100 Subject: [POWERPC] Cell iommu support This patch adds full cell iommu support (and iommu disabled mode). It implements mapping/unmapping of iommu pages on demand using the standard powerpc iommu framework. It also supports running with iommu disabled for machines with less than 2GB of memory. (The default is off in that case, though it can be forced on with the kernel command line option iommu=force). Signed-off-by: Jeremy Kerr Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 14 +- arch/powerpc/platforms/cell/iommu.c | 1005 +++++++++++++++++++++++------------ arch/powerpc/platforms/cell/iommu.h | 67 --- arch/powerpc/platforms/cell/setup.c | 43 -- arch/powerpc/sysdev/dart_iommu.c | 3 - include/asm-powerpc/iommu.h | 6 +- 6 files changed, 663 insertions(+), 475 deletions(-) delete mode 100644 arch/powerpc/platforms/cell/iommu.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index b91761639d9..8671eb634a9 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -173,8 +173,8 @@ static unsigned long __initdata dt_string_start, dt_string_end; static unsigned long __initdata prom_initrd_start, prom_initrd_end; #ifdef CONFIG_PPC64 -static int __initdata iommu_force_on; -static int __initdata ppc64_iommu_off; +static int __initdata prom_iommu_force_on; +static int __initdata prom_iommu_off; static unsigned long __initdata prom_tce_alloc_start; static unsigned long __initdata prom_tce_alloc_end; #endif @@ -582,9 +582,9 @@ static void __init early_cmdline_parse(void) while (*opt && *opt == ' ') opt++; if (!strncmp(opt, RELOC("off"), 3)) - RELOC(ppc64_iommu_off) = 1; + RELOC(prom_iommu_off) = 1; else if (!strncmp(opt, RELOC("force"), 5)) - RELOC(iommu_force_on) = 1; + RELOC(prom_iommu_force_on) = 1; } #endif } @@ -1167,7 +1167,7 @@ static void __init prom_initialize_tce_table(void) u64 local_alloc_top, local_alloc_bottom; u64 i; - if (RELOC(ppc64_iommu_off)) + if (RELOC(prom_iommu_off)) return; prom_debug("starting prom_initialize_tce_table\n"); @@ -2283,11 +2283,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, * Fill in some infos for use by the kernel later on */ #ifdef CONFIG_PPC64 - if (RELOC(ppc64_iommu_off)) + if (RELOC(prom_iommu_off)) prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", NULL, 0); - if (RELOC(iommu_force_on)) + if (RELOC(prom_iommu_force_on)) prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on", NULL, 0); diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 6a97fe1319d..b43466ba809 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -1,446 +1,747 @@ /* * IOMMU implementation for Cell Broadband Processor Architecture - * We just establish a linear mapping at boot by setting all the - * IOPT cache entries in the CPU. - * The mapping functions should be identical to pci_direct_iommu, - * except for the handling of the high order bit that is required - * by the Spider bridge. These should be split into a separate - * file at the point where we get a different bridge chip. * - * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH, - * Arnd Bergmann + * (C) Copyright IBM Corporation 2006 * - * Based on linear mapping - * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * Author: Jeremy Kerr * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #undef DEBUG #include -#include -#include -#include #include -#include -#include -#include -#include -#include +#include +#include -#include -#include -#include #include -#include +#include #include -#include -#include -#include -#include +#include #include +#include +#include -#include "iommu.h" +#include "cbe_regs.h" +#include "interrupt.h" -static inline unsigned long -get_iopt_entry(unsigned long real_address, unsigned long ioid, - unsigned long prot) -{ - return (prot & IOPT_PROT_MASK) - | (IOPT_COHERENT) - | (IOPT_ORDER_VC) - | (real_address & IOPT_RPN_MASK) - | (ioid & IOPT_IOID_MASK); -} +/* Define CELL_IOMMU_REAL_UNMAP to actually unmap non-used pages + * instead of leaving them mapped to some dummy page. This can be + * enabled once the appropriate workarounds for spider bugs have + * been enabled + */ +#define CELL_IOMMU_REAL_UNMAP + +/* Define CELL_IOMMU_STRICT_PROTECTION to enforce protection of + * IO PTEs based on the transfer direction. That can be enabled + * once spider-net has been fixed to pass the correct direction + * to the DMA mapping functions + */ +#define CELL_IOMMU_STRICT_PROTECTION + + +#define NR_IOMMUS 2 + +/* IOC mmap registers */ +#define IOC_Reg_Size 0x2000 + +#define IOC_IOPT_CacheInvd 0x908 +#define IOC_IOPT_CacheInvd_NE_Mask 0xffe0000000000000ul +#define IOC_IOPT_CacheInvd_IOPTE_Mask 0x000003fffffffff8ul +#define IOC_IOPT_CacheInvd_Busy 0x0000000000000001ul + +#define IOC_IOST_Origin 0x918 +#define IOC_IOST_Origin_E 0x8000000000000000ul +#define IOC_IOST_Origin_HW 0x0000000000000800ul +#define IOC_IOST_Origin_HL 0x0000000000000400ul + +#define IOC_IO_ExcpStat 0x920 +#define IOC_IO_ExcpStat_V 0x8000000000000000ul +#define IOC_IO_ExcpStat_SPF_Mask 0x6000000000000000ul +#define IOC_IO_ExcpStat_SPF_S 0x6000000000000000ul +#define IOC_IO_ExcpStat_SPF_P 0x4000000000000000ul +#define IOC_IO_ExcpStat_ADDR_Mask 0x00000007fffff000ul +#define IOC_IO_ExcpStat_RW_Mask 0x0000000000000800ul +#define IOC_IO_ExcpStat_IOID_Mask 0x00000000000007fful + +#define IOC_IO_ExcpMask 0x928 +#define IOC_IO_ExcpMask_SFE 0x4000000000000000ul +#define IOC_IO_ExcpMask_PFE 0x2000000000000000ul + +#define IOC_IOCmd_Offset 0x1000 + +#define IOC_IOCmd_Cfg 0xc00 +#define IOC_IOCmd_Cfg_TE 0x0000800000000000ul + + +/* Segment table entries */ +#define IOSTE_V 0x8000000000000000ul /* valid */ +#define IOSTE_H 0x4000000000000000ul /* cache hint */ +#define IOSTE_PT_Base_RPN_Mask 0x3ffffffffffff000ul /* base RPN of IOPT */ +#define IOSTE_NPPT_Mask 0x0000000000000fe0ul /* no. pages in IOPT */ +#define IOSTE_PS_Mask 0x0000000000000007ul /* page size */ +#define IOSTE_PS_4K 0x0000000000000001ul /* - 4kB */ +#define IOSTE_PS_64K 0x0000000000000003ul /* - 64kB */ +#define IOSTE_PS_1M 0x0000000000000005ul /* - 1MB */ +#define IOSTE_PS_16M 0x0000000000000007ul /* - 16MB */ + +/* Page table entries */ +#define IOPTE_PP_W 0x8000000000000000ul /* protection: write */ +#define IOPTE_PP_R 0x4000000000000000ul /* protection: read */ +#define IOPTE_M 0x2000000000000000ul /* coherency required */ +#define IOPTE_SO_R 0x1000000000000000ul /* ordering: writes */ +#define IOPTE_SO_RW 0x1800000000000000ul /* ordering: r & w */ +#define IOPTE_RPN_Mask 0x07fffffffffff000ul /* RPN */ +#define IOPTE_H 0x0000000000000800ul /* cache hint */ +#define IOPTE_IOID_Mask 0x00000000000007fful /* ioid */ + + +/* IOMMU sizing */ +#define IO_SEGMENT_SHIFT 28 +#define IO_PAGENO_BITS (IO_SEGMENT_SHIFT - IOMMU_PAGE_SHIFT) + +/* The high bit needs to be set on every DMA address */ +#define SPIDER_DMA_OFFSET 0x80000000ul + +struct iommu_window { + struct list_head list; + struct cbe_iommu *iommu; + unsigned long offset; + unsigned long size; + unsigned long pte_offset; + unsigned int ioid; + struct iommu_table table; +}; -typedef struct { - unsigned long val; -} ioste; +#define NAMESIZE 8 +struct cbe_iommu { + int nid; + char name[NAMESIZE]; + void __iomem *xlate_regs; + void __iomem *cmd_regs; + unsigned long *stab; + unsigned long *ptab; + void *pad_page; + struct list_head windows; +}; -static inline ioste -mk_ioste(unsigned long val) -{ - ioste ioste = { .val = val, }; - return ioste; -} +/* Static array of iommus, one per node + * each contains a list of windows, keyed from dma_window property + * - on bus setup, look for a matching window, or create one + * - on dev setup, assign iommu_table ptr + */ +static struct cbe_iommu iommus[NR_IOMMUS]; +static int cbe_nr_iommus; -static inline ioste -get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size) +static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte, + long n_ptes) { - unsigned long ps; - unsigned long iostep; - unsigned long nnpt; - unsigned long shift; - - switch (page_size) { - case 0x1000000: - ps = IOST_PS_16M; - nnpt = 0; /* one page per segment */ - shift = 5; /* segment has 16 iopt entries */ - break; - - case 0x100000: - ps = IOST_PS_1M; - nnpt = 0; /* one page per segment */ - shift = 1; /* segment has 256 iopt entries */ - break; - - case 0x10000: - ps = IOST_PS_64K; - nnpt = 0x07; /* 8 pages per io page table */ - shift = 0; /* all entries are used */ - break; - - case 0x1000: - ps = IOST_PS_4K; - nnpt = 0x7f; /* 128 pages per io page table */ - shift = 0; /* all entries are used */ - break; - - default: /* not a known compile time constant */ - { - /* BUILD_BUG_ON() is not usable here */ - extern void __get_iost_entry_bad_page_size(void); - __get_iost_entry_bad_page_size(); - } - break; - } + unsigned long *reg, val; + long n; - iostep = iopt_base + - /* need 8 bytes per iopte */ - (((io_address / page_size * 8) - /* align io page tables on 4k page boundaries */ - << shift) - /* nnpt+1 pages go into each iopt */ - & ~(nnpt << 12)); - - nnpt++; /* this seems to work, but the documentation is not clear - about wether we put nnpt or nnpt-1 into the ioste bits. - In theory, this can't work for 4k pages. */ - return mk_ioste(IOST_VALID_MASK - | (iostep & IOST_PT_BASE_MASK) - | ((nnpt << 5) & IOST_NNPT_MASK) - | (ps & IOST_PS_MASK)); -} + reg = iommu->xlate_regs + IOC_IOPT_CacheInvd; -/* compute the address of an io pte */ -static inline unsigned long -get_ioptep(ioste iost_entry, unsigned long io_address) -{ - unsigned long iopt_base; - unsigned long page_size; - unsigned long page_number; - unsigned long iopt_offset; - - iopt_base = iost_entry.val & IOST_PT_BASE_MASK; - page_size = iost_entry.val & IOST_PS_MASK; - - /* decode page size to compute page number */ - page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size); - /* page number is an offset into the io page table */ - iopt_offset = (page_number << 3) & 0x7fff8ul; - return iopt_base + iopt_offset; -} + while (n_ptes > 0) { + /* we can invalidate up to 1 << 11 PTEs at once */ + n = min(n_ptes, 1l << 11); + val = (((n /*- 1*/) << 53) & IOC_IOPT_CacheInvd_NE_Mask) + | (__pa(pte) & IOC_IOPT_CacheInvd_IOPTE_Mask) + | IOC_IOPT_CacheInvd_Busy; -/* compute the tag field of the iopt cache entry */ -static inline unsigned long -get_ioc_tag(ioste iost_entry, unsigned long io_address) -{ - unsigned long iopte = get_ioptep(iost_entry, io_address); + out_be64(reg, val); + while (in_be64(reg) & IOC_IOPT_CacheInvd_Busy) + ; - return IOPT_VALID_MASK - | ((iopte & 0x00000000000000ff8ul) >> 3) - | ((iopte & 0x0000003fffffc0000ul) >> 9); + n_ptes -= n; + pte += n; + } } -/* compute the hashed 6 bit index for the 4-way associative pte cache */ -static inline unsigned long -get_ioc_hash(ioste iost_entry, unsigned long io_address) +static void tce_build_cell(struct iommu_table *tbl, long index, long npages, + unsigned long uaddr, enum dma_data_direction direction) { - unsigned long iopte = get_ioptep(iost_entry, io_address); - - return ((iopte & 0x000000000000001f8ul) >> 3) - ^ ((iopte & 0x00000000000020000ul) >> 17) - ^ ((iopte & 0x00000000000010000ul) >> 15) - ^ ((iopte & 0x00000000000008000ul) >> 13) - ^ ((iopte & 0x00000000000004000ul) >> 11) - ^ ((iopte & 0x00000000000002000ul) >> 9) - ^ ((iopte & 0x00000000000001000ul) >> 7); + int i; + unsigned long *io_pte, base_pte; + struct iommu_window *window = + container_of(tbl, struct iommu_window, table); + + /* implementing proper protection causes problems with the spidernet + * driver - check mapping directions later, but allow read & write by + * default for now.*/ +#ifdef CELL_IOMMU_STRICT_PROTECTION + /* to avoid referencing a global, we use a trick here to setup the + * protection bit. "prot" is setup to be 3 fields of 4 bits apprended + * together for each of the 3 supported direction values. It is then + * shifted left so that the fields matching the desired direction + * lands on the appropriate bits, and other bits are masked out. + */ + const unsigned long prot = 0xc48; + base_pte = + ((prot << (52 + 4 * direction)) & (IOPTE_PP_W | IOPTE_PP_R)) + | IOPTE_M | IOPTE_SO_RW | (window->ioid & IOPTE_IOID_Mask); +#else + base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW | + (window->ioid & IOPTE_IOID_Mask); +#endif + + io_pte = (unsigned long *)tbl->it_base + (index - window->pte_offset); + + for (i = 0; i < npages; i++, uaddr += IOMMU_PAGE_SIZE) + io_pte[i] = base_pte | (__pa(uaddr) & IOPTE_RPN_Mask); + + mb(); + + invalidate_tce_cache(window->iommu, io_pte, npages); + + pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n", + index, npages, direction, base_pte); } -/* same as above, but pretend that we have a simpler 1-way associative - pte cache with an 8 bit index */ -static inline unsigned long -get_ioc_hash_1way(ioste iost_entry, unsigned long io_address) +static void tce_free_cell(struct iommu_table *tbl, long index, long npages) { - unsigned long iopte = get_ioptep(iost_entry, io_address); - - return ((iopte & 0x000000000000001f8ul) >> 3) - ^ ((iopte & 0x00000000000020000ul) >> 17) - ^ ((iopte & 0x00000000000010000ul) >> 15) - ^ ((iopte & 0x00000000000008000ul) >> 13) - ^ ((iopte & 0x00000000000004000ul) >> 11) - ^ ((iopte & 0x00000000000002000ul) >> 9) - ^ ((iopte & 0x00000000000001000ul) >> 7) - ^ ((iopte & 0x0000000000000c000ul) >> 8); -} -static inline ioste -get_iost_cache(void __iomem *base, unsigned long index) -{ - unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); - return mk_ioste(in_be64(&p[index])); -} + int i; + unsigned long *io_pte, pte; + struct iommu_window *window = + container_of(tbl, struct iommu_window, table); -static inline void -set_iost_cache(void __iomem *base, unsigned long index, ioste ste) -{ - unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); - pr_debug("ioste %02lx was %016lx, store %016lx", index, - get_iost_cache(base, index).val, ste.val); - out_be64(&p[index], ste.val); - pr_debug(" now %016lx\n", get_iost_cache(base, index).val); -} + pr_debug("tce_free_cell(index=%lx,n=%lx)\n", index, npages); -static inline unsigned long -get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag) -{ - unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR); - unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG); +#ifdef CELL_IOMMU_REAL_UNMAP + pte = 0; +#else + /* spider bridge does PCI reads after freeing - insert a mapping + * to a scratch page instead of an invalid entry */ + pte = IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW | __pa(window->iommu->pad_page) + | (window->ioid & IOPTE_IOID_Mask); +#endif - *tag = tags[index]; - rmb(); - return *p; -} + io_pte = (unsigned long *)tbl->it_base + (index - window->pte_offset); -static inline void -set_iopt_cache(void __iomem *base, unsigned long index, - unsigned long tag, unsigned long val) -{ - unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR; - unsigned long __iomem *p = base + IOC_PT_CACHE_REG; + for (i = 0; i < npages; i++) + io_pte[i] = pte; + + mb(); - out_be64(p, val); - out_be64(&tags[index], tag); + invalidate_tce_cache(window->iommu, io_pte, npages); } -static inline void -set_iost_origin(void __iomem *base) +static irqreturn_t ioc_interrupt(int irq, void *data) { - unsigned long __iomem *p = base + IOC_ST_ORIGIN; - unsigned long origin = IOSTO_ENABLE | IOSTO_SW; - - pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin); - out_be64(p, origin); + unsigned long stat; + struct cbe_iommu *iommu = data; + + stat = in_be64(iommu->xlate_regs + IOC_IO_ExcpStat); + + /* Might want to rate limit it */ + printk(KERN_ERR "iommu: DMA exception 0x%016lx\n", stat); + printk(KERN_ERR " V=%d, SPF=[%c%c], RW=%s, IOID=0x%04x\n", + !!(stat & IOC_IO_ExcpStat_V), + (stat & IOC_IO_ExcpStat_SPF_S) ? 'S' : ' ', + (stat & IOC_IO_ExcpStat_SPF_P) ? 'P' : ' ', + (stat & IOC_IO_ExcpStat_RW_Mask) ? "Read" : "Write", + (unsigned int)(stat & IOC_IO_ExcpStat_IOID_Mask)); + printk(KERN_ERR " page=0x%016lx\n", + stat & IOC_IO_ExcpStat_ADDR_Mask); + + /* clear interrupt */ + stat &= ~IOC_IO_ExcpStat_V; + out_be64(iommu->xlate_regs + IOC_IO_ExcpStat, stat); + + return IRQ_HANDLED; } -static inline void -set_iocmd_config(void __iomem *base) +static int cell_iommu_find_ioc(int nid, unsigned long *base) { - unsigned long __iomem *p = base + 0xc00; - unsigned long conf; + struct device_node *np; + struct resource r; + + *base = 0; + + /* First look for new style /be nodes */ + for_each_node_by_name(np, "ioc") { + if (of_node_to_nid(np) != nid) + continue; + if (of_address_to_resource(np, 0, &r)) { + printk(KERN_ERR "iommu: can't get address for %s\n", + np->full_name); + continue; + } + *base = r.start; + of_node_put(np); + return 0; + } + + /* Ok, let's try the old way */ + for_each_node_by_type(np, "cpu") { + const unsigned int *nidp; + const unsigned long *tmp; + + nidp = get_property(np, "node-id", NULL); + if (nidp && *nidp == nid) { + tmp = get_property(np, "ioc-translation", NULL); + if (tmp) { + *base = *tmp; + of_node_put(np); + return 0; + } + } + } - conf = in_be64(p); - pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE); - out_be64(p, conf | IOCMD_CONF_TE); + return -ENODEV; } -static void enable_mapping(void __iomem *base, void __iomem *mmio_base) +static void cell_iommu_setup_hardware(struct cbe_iommu *iommu, unsigned long size) { - set_iocmd_config(base); - set_iost_origin(mmio_base); -} + struct page *page; + int ret, i; + unsigned long reg, segments, pages_per_segment, ptab_size, n_pte_pages; + unsigned long xlate_base; + unsigned int virq; + + if (cell_iommu_find_ioc(iommu->nid, &xlate_base)) + panic("%s: missing IOC register mappings for node %d\n", + __FUNCTION__, iommu->nid); + + iommu->xlate_regs = ioremap(xlate_base, IOC_Reg_Size); + iommu->cmd_regs = iommu->xlate_regs + IOC_IOCmd_Offset; + + segments = size >> IO_SEGMENT_SHIFT; + pages_per_segment = 1ull << IO_PAGENO_BITS; + + pr_debug("%s: iommu[%d]: segments: %lu, pages per segment: %lu\n", + __FUNCTION__, iommu->nid, segments, pages_per_segment); + + /* set up the segment table */ + page = alloc_pages_node(iommu->nid, GFP_KERNEL, 0); + BUG_ON(!page); + iommu->stab = page_address(page); + clear_page(iommu->stab); + + /* ... and the page tables. Since these are contiguous, we can treat + * the page tables as one array of ptes, like pSeries does. + */ + ptab_size = segments * pages_per_segment * sizeof(unsigned long); + pr_debug("%s: iommu[%d]: ptab_size: %lu, order: %d\n", __FUNCTION__, + iommu->nid, ptab_size, get_order(ptab_size)); + page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(ptab_size)); + BUG_ON(!page); + + iommu->ptab = page_address(page); + memset(iommu->ptab, 0, ptab_size); + + /* allocate a bogus page for the end of each mapping */ + page = alloc_pages_node(iommu->nid, GFP_KERNEL, 0); + BUG_ON(!page); + iommu->pad_page = page_address(page); + clear_page(iommu->pad_page); + + /* number of pages needed for a page table */ + n_pte_pages = (pages_per_segment * + sizeof(unsigned long)) >> IOMMU_PAGE_SHIFT; + + pr_debug("%s: iommu[%d]: stab at %p, ptab at %p, n_pte_pages: %lu\n", + __FUNCTION__, iommu->nid, iommu->stab, iommu->ptab, + n_pte_pages); + + /* initialise the STEs */ + reg = IOSTE_V | ((n_pte_pages - 1) << 5); + + if (IOMMU_PAGE_SIZE == 0x1000) + reg |= IOSTE_PS_4K; + else if (IOMMU_PAGE_SIZE == 0x10000) + reg |= IOSTE_PS_64K; + else { + extern void __unknown_page_size_error(void); + __unknown_page_size_error(); + } -struct cell_iommu { - unsigned long base; - unsigned long mmio_base; - void __iomem *mapped_base; - void __iomem *mapped_mmio_base; -}; + pr_debug("Setting up IOMMU stab:\n"); + for (i = 0; i * (1ul << IO_SEGMENT_SHIFT) < size; i++) { + iommu->stab[i] = reg | + (__pa(iommu->ptab) + n_pte_pages * IOMMU_PAGE_SIZE * i); + pr_debug("\t[%d] 0x%016lx\n", i, iommu->stab[i]); + } + + /* ensure that the STEs have updated */ + mb(); + + /* setup interrupts for the iommu. */ + reg = in_be64(iommu->xlate_regs + IOC_IO_ExcpStat); + out_be64(iommu->xlate_regs + IOC_IO_ExcpStat, + reg & ~IOC_IO_ExcpStat_V); + out_be64(iommu->xlate_regs + IOC_IO_ExcpMask, + IOC_IO_ExcpMask_PFE | IOC_IO_ExcpMask_SFE); + + virq = irq_create_mapping(NULL, + IIC_IRQ_IOEX_ATI | (iommu->nid << IIC_IRQ_NODE_SHIFT)); + BUG_ON(virq == NO_IRQ); + + ret = request_irq(virq, ioc_interrupt, IRQF_DISABLED, + iommu->name, iommu); + BUG_ON(ret); -static struct cell_iommu cell_iommus[NR_CPUS]; + /* set the IOC segment table origin register (and turn on the iommu) */ + reg = IOC_IOST_Origin_E | __pa(iommu->stab) | IOC_IOST_Origin_HW; + out_be64(iommu->xlate_regs + IOC_IOST_Origin, reg); + in_be64(iommu->xlate_regs + IOC_IOST_Origin); -/* initialize the iommu to support a simple linear mapping - * for each DMA window used by any device. For now, we - * happen to know that there is only one DMA window in use, - * starting at iopt_phys_offset. */ -static void cell_do_map_iommu(struct cell_iommu *iommu, - unsigned int ioid, - unsigned long map_start, - unsigned long map_size) + /* turn on IO translation */ + reg = in_be64(iommu->cmd_regs + IOC_IOCmd_Cfg) | IOC_IOCmd_Cfg_TE; + out_be64(iommu->cmd_regs + IOC_IOCmd_Cfg, reg); +} + +#if 0/* Unused for now */ +static struct iommu_window *find_window(struct cbe_iommu *iommu, + unsigned long offset, unsigned long size) { - unsigned long io_address, real_address; - void __iomem *ioc_base, *ioc_mmio_base; - ioste ioste; - unsigned long index; + struct iommu_window *window; - /* we pretend the io page table was at a very high address */ - const unsigned long fake_iopt = 0x10000000000ul; - const unsigned long io_page_size = 0x1000000; /* use 16M pages */ - const unsigned long io_segment_size = 0x10000000; /* 256M */ - - ioc_base = iommu->mapped_base; - ioc_mmio_base = iommu->mapped_mmio_base; - - for (real_address = 0, io_address = map_start; - io_address <= map_start + map_size; - real_address += io_page_size, io_address += io_page_size) { - ioste = get_iost_entry(fake_iopt, io_address, io_page_size); - if ((real_address % io_segment_size) == 0) /* segment start */ - set_iost_cache(ioc_mmio_base, - io_address >> 28, ioste); - index = get_ioc_hash_1way(ioste, io_address); - pr_debug("addr %08lx, index %02lx, ioste %016lx\n", - io_address, index, ioste.val); - set_iopt_cache(ioc_mmio_base, - get_ioc_hash_1way(ioste, io_address), - get_ioc_tag(ioste, io_address), - get_iopt_entry(real_address, ioid, IOPT_PROT_RW)); + /* todo: check for overlapping (but not equal) windows) */ + + list_for_each_entry(window, &(iommu->windows), list) { + if (window->offset == offset && window->size == size) + return window; } + + return NULL; } +#endif -static void pci_dma_cell_bus_setup(struct pci_bus *b) +static struct iommu_window * __init +cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np, + unsigned long offset, unsigned long size, + unsigned long pte_offset) { + struct iommu_window *window; const unsigned int *ioid; - unsigned long map_start, map_size, token; - const unsigned long *dma_window; - struct cell_iommu *iommu; - struct device_node *d; - - d = pci_bus_to_OF_node(b); - ioid = get_property(d, "ioid", NULL); - if (!ioid) - pr_debug("No ioid entry found !\n"); + ioid = get_property(np, "ioid", NULL); + if (ioid == NULL) + printk(KERN_WARNING "iommu: missing ioid for %s using 0\n", + np->full_name); + + window = kmalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid); + BUG_ON(window == NULL); + + window->offset = offset; + window->size = size; + window->ioid = ioid ? *ioid : 0; + window->iommu = iommu; + window->pte_offset = pte_offset; + + window->table.it_blocksize = 16; + window->table.it_base = (unsigned long)iommu->ptab; + window->table.it_index = iommu->nid; + window->table.it_offset = (offset >> IOMMU_PAGE_SHIFT) + + window->pte_offset; + window->table.it_size = size >> IOMMU_PAGE_SHIFT; + + iommu_init_table(&window->table, iommu->nid); + + pr_debug("\tioid %d\n", window->ioid); + pr_debug("\tblocksize %ld\n", window->table.it_blocksize); + pr_debug("\tbase 0x%016lx\n", window->table.it_base); + pr_debug("\toffset 0x%lx\n", window->table.it_offset); + pr_debug("\tsize %ld\n", window->table.it_size); + + list_add(&window->list, &iommu->windows); + + if (offset != 0) + return window; + + /* We need to map and reserve the first IOMMU page since it's used + * by the spider workaround. In theory, we only need to do that when + * running on spider but it doesn't really matter. + * + * This code also assumes that we have a window that starts at 0, + * which is the case on all spider based blades. + */ + __set_bit(0, window->table.it_map); + tce_build_cell(&window->table, window->table.it_offset, 1, + (unsigned long)iommu->pad_page, DMA_TO_DEVICE); + window->table.it_hint = window->table.it_blocksize; + + return window; +} - dma_window = get_property(d, "ibm,dma-window", NULL); - if (!dma_window) - pr_debug("No ibm,dma-window entry found !\n"); +static struct cbe_iommu *cell_iommu_for_node(int nid) +{ + int i; - map_start = dma_window[1]; - map_size = dma_window[2]; - token = dma_window[0] >> 32; + for (i = 0; i < cbe_nr_iommus; i++) + if (iommus[i].nid == nid) + return &iommus[i]; + return NULL; +} - iommu = &cell_iommus[token]; +static void cell_dma_dev_setup(struct device *dev) +{ + struct iommu_window *window; + struct cbe_iommu *iommu; + struct dev_archdata *archdata = &dev->archdata; + + /* If we run without iommu, no need to do anything */ + if (pci_dma_ops == &dma_direct_ops) + return; + + /* Current implementation uses the first window available in that + * node's iommu. We -might- do something smarter later though it may + * never be necessary + */ + iommu = cell_iommu_for_node(archdata->numa_node); + if (iommu == NULL || list_empty(&iommu->windows)) { + printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n", + archdata->of_node ? archdata->of_node->full_name : "?", + archdata->numa_node); + return; + } + window = list_entry(iommu->windows.next, struct iommu_window, list); - cell_do_map_iommu(iommu, *ioid, map_start, map_size); + archdata->dma_data = &window->table; } - -static int cell_map_iommu_hardcoded(int num_nodes) +static void cell_pci_dma_dev_setup(struct pci_dev *dev) { - struct cell_iommu *iommu = NULL; + cell_dma_dev_setup(&dev->dev); +} - pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); +static int cell_of_bus_notify(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct device *dev = data; - /* node 0 */ - iommu = &cell_iommus[0]; - iommu->mapped_base = ioremap(0x20000511000ul, 0x1000); - iommu->mapped_mmio_base = ioremap(0x20000510000ul, 0x1000); + /* We are only intereted in device addition */ + if (action != BUS_NOTIFY_ADD_DEVICE) + return 0; - enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); + /* We use the PCI DMA ops */ + dev->archdata.dma_ops = pci_dma_ops; - cell_do_map_iommu(iommu, 0x048a, - 0x20000000ul,0x20000000ul); + cell_dma_dev_setup(dev); - if (num_nodes < 2) - return 0; + return 0; +} - /* node 1 */ - iommu = &cell_iommus[1]; - iommu->mapped_base = ioremap(0x30000511000ul, 0x1000); - iommu->mapped_mmio_base = ioremap(0x30000510000ul, 0x1000); +static struct notifier_block cell_of_bus_notifier = { + .notifier_call = cell_of_bus_notify +}; - enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); +static int __init cell_iommu_get_window(struct device_node *np, + unsigned long *base, + unsigned long *size) +{ + const void *dma_window; + unsigned long index; - cell_do_map_iommu(iommu, 0x048a, - 0x20000000,0x20000000ul); + /* Use ibm,dma-window if available, else, hard code ! */ + dma_window = get_property(np, "ibm,dma-window", NULL); + if (dma_window == NULL) { + *base = 0; + *size = 0x80000000u; + return -ENODEV; + } + of_parse_dma_window(np, dma_window, &index, base, size); return 0; } - -static int cell_map_iommu(void) +static void __init cell_iommu_init_one(struct device_node *np, unsigned long offset) { - unsigned int num_nodes = 0; - const unsigned int *node_id; - const unsigned long *base, *mmio_base; - struct device_node *dn; - struct cell_iommu *iommu = NULL; - - /* determine number of nodes (=iommus) */ - pr_debug("%s(%d): determining number of nodes...", __FUNCTION__, __LINE__); - for(dn = of_find_node_by_type(NULL, "cpu"); - dn; - dn = of_find_node_by_type(dn, "cpu")) { - node_id = get_property(dn, "node-id", NULL); - - if (num_nodes < *node_id) - num_nodes = *node_id; - } + struct cbe_iommu *iommu; + unsigned long base, size; + int nid, i; + + /* Get node ID */ + nid = of_node_to_nid(np); + if (nid < 0) { + printk(KERN_ERR "iommu: failed to get node for %s\n", + np->full_name); + return; + } + pr_debug("iommu: setting up iommu for node %d (%s)\n", + nid, np->full_name); + + /* XXX todo: If we can have multiple windows on the same IOMMU, which + * isn't the case today, we probably want here to check wether the + * iommu for that node is already setup. + * However, there might be issue with getting the size right so let's + * ignore that for now. We might want to completely get rid of the + * multiple window support since the cell iommu supports per-page ioids + */ + + if (cbe_nr_iommus >= NR_IOMMUS) { + printk(KERN_ERR "iommu: too many IOMMUs detected ! (%s)\n", + np->full_name); + return; + } + + /* Init base fields */ + i = cbe_nr_iommus++; + iommu = &iommus[i]; + iommu->stab = 0; + iommu->nid = nid; + snprintf(iommu->name, sizeof(iommu->name), "iommu%d", i); + INIT_LIST_HEAD(&iommu->windows); - num_nodes++; - pr_debug("%i found.\n", num_nodes); + /* Obtain a window for it */ + cell_iommu_get_window(np, &base, &size); - /* map the iommu registers for each node */ - pr_debug("%s(%d): Looping through nodes\n", __FUNCTION__, __LINE__); - for(dn = of_find_node_by_type(NULL, "cpu"); - dn; - dn = of_find_node_by_type(dn, "cpu")) { + pr_debug("\ttranslating window 0x%lx...0x%lx\n", + base, base + size - 1); - node_id = get_property(dn, "node-id", NULL); - base = get_property(dn, "ioc-cache", NULL); - mmio_base = get_property(dn, "ioc-translation", NULL); + /* Initialize the hardware */ + cell_iommu_setup_hardware(iommu, size); - if (!base || !mmio_base || !node_id) - return cell_map_iommu_hardcoded(num_nodes); + /* Setup the iommu_table */ + cell_iommu_setup_window(iommu, np, base, size, + offset >> IOMMU_PAGE_SHIFT); +} - iommu = &cell_iommus[*node_id]; - iommu->base = *base; - iommu->mmio_base = *mmio_base; +static void __init cell_disable_iommus(void) +{ + int node; + unsigned long base, val; + void __iomem *xregs, *cregs; + + /* Make sure IOC translation is disabled on all nodes */ + for_each_online_node(node) { + if (cell_iommu_find_ioc(node, &base)) + continue; + xregs = ioremap(base, IOC_Reg_Size); + if (xregs == NULL) + continue; + cregs = xregs + IOC_IOCmd_Offset; + + pr_debug("iommu: cleaning up iommu on node %d\n", node); + + out_be64(xregs + IOC_IOST_Origin, 0); + (void)in_be64(xregs + IOC_IOST_Origin); + val = in_be64(cregs + IOC_IOCmd_Cfg); + val &= ~IOC_IOCmd_Cfg_TE; + out_be64(cregs + IOC_IOCmd_Cfg, val); + (void)in_be64(cregs + IOC_IOCmd_Cfg); + + iounmap(xregs); + } +} - iommu->mapped_base = ioremap(*base, 0x1000); - iommu->mapped_mmio_base = ioremap(*mmio_base, 0x1000); +static int __init cell_iommu_init_disabled(void) +{ + struct device_node *np = NULL; + unsigned long base = 0, size; - enable_mapping(iommu->mapped_base, - iommu->mapped_mmio_base); + /* When no iommu is present, we use direct DMA ops */ + pci_dma_ops = &dma_direct_ops; - /* everything else will be done in iommu_bus_setup */ + /* First make sure all IOC translation is turned off */ + cell_disable_iommus(); + + /* If we have no Axon, we set up the spider DMA magic offset */ + if (of_find_node_by_name(NULL, "axon") == NULL) + dma_direct_offset = SPIDER_DMA_OFFSET; + + /* Now we need to check to see where the memory is mapped + * in PCI space. We assume that all busses use the same dma + * window which is always the case so far on Cell, thus we + * pick up the first pci-internal node we can find and check + * the DMA window from there. + */ + for_each_node_by_name(np, "axon") { + if (np->parent == NULL || np->parent->parent != NULL) + continue; + if (cell_iommu_get_window(np, &base, &size) == 0) + break; + } + if (np == NULL) { + for_each_node_by_name(np, "pci-internal") { + if (np->parent == NULL || np->parent->parent != NULL) + continue; + if (cell_iommu_get_window(np, &base, &size) == 0) + break; + } + } + of_node_put(np); + + /* If we found a DMA window, we check if it's big enough to enclose + * all of physical memory. If not, we force enable IOMMU + */ + if (np && size < lmb_end_of_DRAM()) { + printk(KERN_WARNING "iommu: force-enabled, dma window" + " (%ldMB) smaller than total memory (%ldMB)\n", + size >> 20, lmb_end_of_DRAM() >> 20); + return -ENODEV; } - return 1; + dma_direct_offset += base; + + printk("iommu: disabled, direct DMA offset is 0x%lx\n", + dma_direct_offset); + + return 0; } -void cell_init_iommu(void) +static int __init cell_iommu_init(void) { - int setup_bus = 0; - - if (of_find_node_by_path("/mambo")) { - pr_info("Not using iommu on systemsim\n"); - } else { - /* If we don't have an Axon bridge, we assume we have a - * spider which requires a DMA offset - */ - if (of_find_node_by_name(NULL, "axon") == NULL) - dma_direct_offset = SPIDER_DMA_VALID; - - if (!(of_chosen && - get_property(of_chosen, "linux,iommu-off", NULL))) - setup_bus = cell_map_iommu(); - - if (setup_bus) { - pr_debug("%s: IOMMU mapping activated\n", __FUNCTION__); - ppc_md.pci_dma_bus_setup = pci_dma_cell_bus_setup; - } else { - pr_debug("%s: IOMMU mapping activated, " - "no device action necessary\n", __FUNCTION__); - /* Direct I/O, IOMMU off */ - } + struct device_node *np; + + if (!machine_is(cell)) + return -ENODEV; + + /* If IOMMU is disabled or we have little enough RAM to not need + * to enable it, we setup a direct mapping. + * + * Note: should we make sure we have the IOMMU actually disabled ? + */ + if (iommu_is_off || + (!iommu_force_on && lmb_end_of_DRAM() <= 0x80000000ull)) + if (cell_iommu_init_disabled() == 0) + goto bail; + + /* Setup various ppc_md. callbacks */ + ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup; + ppc_md.tce_build = tce_build_cell; + ppc_md.tce_free = tce_free_cell; + + /* Create an iommu for each /axon node. */ + for_each_node_by_name(np, "axon") { + if (np->parent == NULL || np->parent->parent != NULL) + continue; + cell_iommu_init_one(np, 0); } - pci_dma_ops = &dma_direct_ops; + /* Create an iommu for each toplevel /pci-internal node for + * old hardware/firmware + */ + for_each_node_by_name(np, "pci-internal") { + if (np->parent == NULL || np->parent->parent != NULL) + continue; + cell_iommu_init_one(np, SPIDER_DMA_OFFSET); + } + + /* Setup default PCI iommu ops */ + pci_dma_ops = &dma_iommu_ops; + + bail: + /* Register callbacks on OF platform device addition/removal + * to handle linking them to the right DMA operations + */ + bus_register_notifier(&of_platform_bus_type, &cell_of_bus_notifier); + + return 0; } +arch_initcall(cell_iommu_init); + diff --git a/arch/powerpc/platforms/cell/iommu.h b/arch/powerpc/platforms/cell/iommu.h deleted file mode 100644 index 2a9ab95604a..00000000000 --- a/arch/powerpc/platforms/cell/iommu.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef CELL_IOMMU_H -#define CELL_IOMMU_H - -/* some constants */ -enum { - /* segment table entries */ - IOST_VALID_MASK = 0x8000000000000000ul, - IOST_TAG_MASK = 0x3000000000000000ul, - IOST_PT_BASE_MASK = 0x000003fffffff000ul, - IOST_NNPT_MASK = 0x0000000000000fe0ul, - IOST_PS_MASK = 0x000000000000000ful, - - IOST_PS_4K = 0x1, - IOST_PS_64K = 0x3, - IOST_PS_1M = 0x5, - IOST_PS_16M = 0x7, - - /* iopt tag register */ - IOPT_VALID_MASK = 0x0000000200000000ul, - IOPT_TAG_MASK = 0x00000001fffffffful, - - /* iopt cache register */ - IOPT_PROT_MASK = 0xc000000000000000ul, - IOPT_PROT_NONE = 0x0000000000000000ul, - IOPT_PROT_READ = 0x4000000000000000ul, - IOPT_PROT_WRITE = 0x8000000000000000ul, - IOPT_PROT_RW = 0xc000000000000000ul, - IOPT_COHERENT = 0x2000000000000000ul, - - IOPT_ORDER_MASK = 0x1800000000000000ul, - /* order access to same IOID/VC on same address */ - IOPT_ORDER_ADDR = 0x0800000000000000ul, - /* similar, but only after a write access */ - IOPT_ORDER_WRITES = 0x1000000000000000ul, - /* Order all accesses to same IOID/VC */ - IOPT_ORDER_VC = 0x1800000000000000ul, - - IOPT_RPN_MASK = 0x000003fffffff000ul, - IOPT_HINT_MASK = 0x0000000000000800ul, - IOPT_IOID_MASK = 0x00000000000007fful, - - IOSTO_ENABLE = 0x8000000000000000ul, - IOSTO_ORIGIN = 0x000003fffffff000ul, - IOSTO_HW = 0x0000000000000800ul, - IOSTO_SW = 0x0000000000000400ul, - - IOCMD_CONF_TE = 0x0000800000000000ul, - - /* memory mapped registers */ - IOC_PT_CACHE_DIR = 0x000, - IOC_ST_CACHE_DIR = 0x800, - IOC_PT_CACHE_REG = 0x910, - IOC_ST_ORIGIN = 0x918, - IOC_CONF = 0x930, - - /* The high bit needs to be set on every DMA address when using - * a spider bridge and only 2GB are addressable with the current - * iommu code. - */ - SPIDER_DMA_VALID = 0x80000000, - CELL_DMA_MASK = 0x7fffffff, -}; - - -void cell_init_iommu(void); - -#endif diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 7e18420166c..83d5d0c2faf 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -55,7 +54,6 @@ #include #include "interrupt.h" -#include "iommu.h" #include "cbe_regs.h" #include "pervasive.h" #include "ras.h" @@ -83,38 +81,11 @@ static void cell_progress(char *s, unsigned short hex) printk("*** %04x : %s\n", hex, s ? s : ""); } -static int cell_of_bus_notify(struct notifier_block *nb, unsigned long action, - void *data) -{ - struct device *dev = data; - - if (action != BUS_NOTIFY_ADD_DEVICE) - return 0; - - /* For now, we just use the PCI DMA ops for everything, though - * we'll need something better when we have a real iommu - * implementation. - */ - dev->archdata.dma_ops = pci_dma_ops; - - return 0; -} - -static struct notifier_block cell_of_bus_notifier = { - .notifier_call = cell_of_bus_notify -}; - - static int __init cell_publish_devices(void) { if (!machine_is(cell)) return 0; - /* Register callbacks on OF platform device addition/removal - * to handle linking them to the right DMA operations - */ - bus_register_notifier(&of_platform_bus_type, &cell_of_bus_notifier); - /* Publish OF platform devices for southbridge IOs */ of_platform_bus_probe(NULL, NULL, NULL); @@ -205,19 +176,6 @@ static void __init cell_setup_arch(void) mmio_nvram_init(); } -/* - * Early initialization. Relocation is on but do not reference unbolted pages - */ -static void __init cell_init_early(void) -{ - DBG(" -> cell_init_early()\n"); - - cell_init_iommu(); - - DBG(" <- cell_init_early()\n"); -} - - static int __init cell_probe(void) { unsigned long root = of_get_flat_dt_root(); @@ -244,7 +202,6 @@ define_machine(cell) { .name = "Cell", .probe = cell_probe, .setup_arch = cell_setup_arch, - .init_early = cell_init_early, .show_cpuinfo = cell_show_cpuinfo, .restart = rtas_restart, .power_off = rtas_power_off, diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index ac784bb5728..1488535b0e1 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -48,9 +48,6 @@ #include "dart.h" -extern int iommu_is_off; -extern int iommu_force_on; - /* Physical base address and size of the DART table */ unsigned long dart_tablebase; /* exported to htab_initialize */ static unsigned long dart_tablesize; diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index 19403183dbb..f85dbd30555 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -34,7 +34,9 @@ #define IOMMU_PAGE_MASK (~((1 << IOMMU_PAGE_SHIFT) - 1)) #define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE) -#ifndef __ASSEMBLY__ +/* Boot time flags */ +extern int iommu_is_off; +extern int iommu_force_on; /* Pure 2^n version of get_order */ static __inline__ __attribute_const__ int get_iommu_order(unsigned long size) @@ -42,8 +44,6 @@ static __inline__ __attribute_const__ int get_iommu_order(unsigned long size) return __ilog2((size - 1) >> IOMMU_PAGE_SHIFT) + 1; } -#endif /* __ASSEMBLY__ */ - /* * IOMAP_MAX_ORDER defines the largest contiguous block -- cgit v1.2.3-70-g09d2 From 68a64357d15ae4f596e92715719071952006e83c Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 13 Nov 2006 09:27:39 +1100 Subject: [POWERPC] Merge 32 and 64 bits asm-powerpc/io.h powerpc: Merge 32 and 64 bits asm-powerpc/io.h The rework on io.h done for the new hookable accessors made it easier, so I just finished the work and merged 32 and 64 bits io.h for arch/powerpc. arch/ppc still uses the old version in asm-ppc, there is just too much gunk in there that I really can't be bothered trying to cleanup. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 2 +- arch/powerpc/kernel/io.c | 87 ++++++++++ arch/powerpc/kernel/iomap.c | 2 +- arch/powerpc/kernel/pci_32.c | 34 +--- arch/powerpc/kernel/rtas_pci.c | 1 + arch/powerpc/kernel/traps.c | 8 +- arch/powerpc/mm/pgtable_32.c | 22 +-- arch/powerpc/mm/pgtable_64.c | 16 +- arch/powerpc/platforms/chrp/setup.c | 1 - arch/powerpc/platforms/iseries/setup.c | 4 +- arch/powerpc/platforms/powermac/setup.c | 2 - include/asm-powerpc/eeh.h | 95 +---------- include/asm-powerpc/ide.h | 7 - include/asm-powerpc/io-defs.h | 9 +- include/asm-powerpc/io.h | 286 +++++++++++++++++++++++++++----- include/asm-powerpc/machdep.h | 4 +- 16 files changed, 367 insertions(+), 213 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 600954df07a..f9ce5d798de 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -72,7 +72,7 @@ obj-$(CONFIG_AUDIT) += audit.o obj64-$(CONFIG_AUDIT) += compat_audit.o ifneq ($(CONFIG_PPC_INDIRECT_IO),y) -pci64-$(CONFIG_PPC64) += iomap.o +obj-y += iomap.o endif ifeq ($(CONFIG_PPC_ISERIES),y) diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c index c1aa07524c2..34ae11494dd 100644 --- a/arch/powerpc/kernel/io.c +++ b/arch/powerpc/kernel/io.c @@ -117,3 +117,90 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count) asm volatile("sync"); } EXPORT_SYMBOL(_outsl_ns); + +#define IO_CHECK_ALIGN(v,a) ((((unsigned long)(v)) & ((a) - 1)) == 0) + +void _memset_io(volatile void __iomem *addr, int c, unsigned long n) +{ + void *p = (void __force *)addr; + u32 lc = c; + lc |= lc << 8; + lc |= lc << 16; + + __asm__ __volatile__ ("sync" : : : "memory"); + while(n && !IO_CHECK_ALIGN(p, 4)) { + *((volatile u8 *)p) = c; + p++; + n--; + } + while(n >= 4) { + *((volatile u32 *)p) = lc; + p += 4; + n -= 4; + } + while(n) { + *((volatile u8 *)p) = c; + p++; + n--; + } + __asm__ __volatile__ ("sync" : : : "memory"); +} +EXPORT_SYMBOL(_memset_io); + +void _memcpy_fromio(void *dest, const volatile void __iomem *src, + unsigned long n) +{ + void *vsrc = (void __force *) src; + + __asm__ __volatile__ ("sync" : : : "memory"); + while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) { + *((u8 *)dest) = *((volatile u8 *)vsrc); + __asm__ __volatile__ ("eieio" : : : "memory"); + vsrc++; + dest++; + n--; + } + while(n > 4) { + *((u32 *)dest) = *((volatile u32 *)vsrc); + __asm__ __volatile__ ("eieio" : : : "memory"); + vsrc += 4; + dest += 4; + n -= 4; + } + while(n) { + *((u8 *)dest) = *((volatile u8 *)vsrc); + __asm__ __volatile__ ("eieio" : : : "memory"); + vsrc++; + dest++; + n--; + } + __asm__ __volatile__ ("sync" : : : "memory"); +} +EXPORT_SYMBOL(_memcpy_fromio); + +void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) +{ + void *vdest = (void __force *) dest; + + __asm__ __volatile__ ("sync" : : : "memory"); + while(n && (!IO_CHECK_ALIGN(vdest, 4) || !IO_CHECK_ALIGN(src, 4))) { + *((volatile u8 *)vdest) = *((u8 *)src); + src++; + vdest++; + n--; + } + while(n > 4) { + *((volatile u32 *)vdest) = *((volatile u32 *)src); + src += 4; + vdest += 4; + n-=4; + } + while(n) { + *((volatile u8 *)vdest) = *((u8 *)src); + src++; + vdest++; + n--; + } + __asm__ __volatile__ ("sync" : : : "memory"); +} +EXPORT_SYMBOL(_memcpy_toio); diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index a13a93dfc65..c6811337105 100644 --- a/arch/powerpc/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c @@ -106,7 +106,7 @@ EXPORT_SYMBOL(iowrite32_rep); void __iomem *ioport_map(unsigned long port, unsigned int len) { - return (void __iomem *) (port+pci_io_base); + return (void __iomem *) (port + _IO_BASE); } void ioport_unmap(void __iomem *addr) diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 0ad101a5fc5..b08238f3050 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -1561,7 +1561,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, *offset += hose->pci_mem_offset; res_bit = IORESOURCE_MEM; } else { - io_offset = hose->io_base_virt - ___IO_BASE; + io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE; *offset += io_offset; res_bit = IORESOURCE_IO; } @@ -1816,7 +1816,8 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar, return; if (rsrc->flags & IORESOURCE_IO) - offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys; + offset = (void __iomem *)_IO_BASE - hose->io_base_virt + + hose->io_base_phys; *start = rsrc->start + offset; *end = rsrc->end + offset; @@ -1835,35 +1836,6 @@ pci_init_resource(struct resource *res, unsigned long start, unsigned long end, res->child = NULL; } -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) -{ - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); - unsigned long flags = pci_resource_flags(dev, bar); - - if (!len) - return NULL; - if (max && len > max) - len = max; - if (flags & IORESOURCE_IO) - return ioport_map(start, len); - if (flags & IORESOURCE_MEM) - /* Not checking IORESOURCE_CACHEABLE because PPC does - * not currently distinguish between ioremap and - * ioremap_nocache. - */ - return ioremap(start, len); - /* What? */ - return NULL; -} - -void pci_iounmap(struct pci_dev *dev, void __iomem *addr) -{ - /* Nothing to do */ -} -EXPORT_SYMBOL(pci_iomap); -EXPORT_SYMBOL(pci_iounmap); - unsigned long pci_address_to_pio(phys_addr_t address) { struct pci_controller* hose = hose_head; diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 03cacc25a0a..ace9f4c86e6 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -38,6 +38,7 @@ #include #include #include +#include /* RTAS tokens */ static int read_pci_config; diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index c66b4771ef4..0d4e203fa7a 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -53,10 +53,6 @@ #endif #include -#ifdef CONFIG_PPC64 /* XXX */ -#define _IO_BASE pci_io_base -#endif - #ifdef CONFIG_DEBUGGER int (*__debugger)(struct pt_regs *regs); int (*__debugger_ipi)(struct pt_regs *regs); @@ -241,7 +237,7 @@ void system_reset_exception(struct pt_regs *regs) */ static inline int check_io_access(struct pt_regs *regs) { -#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) +#ifdef CONFIG_PPC32 unsigned long msr = regs->msr; const struct exception_table_entry *entry; unsigned int *nip = (unsigned int *)regs->nip; @@ -274,7 +270,7 @@ static inline int check_io_access(struct pt_regs *regs) return 1; } } -#endif /* CONFIG_PPC_PMAC && CONFIG_PPC32 */ +#endif /* CONFIG_PPC32 */ return 0; } diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 7750c442568..1891dbeeb8e 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -148,6 +148,13 @@ ioremap(phys_addr_t addr, unsigned long size) } EXPORT_SYMBOL(ioremap); +void __iomem * +ioremap_flags(phys_addr_t addr, unsigned long size, unsigned long flags) +{ + return __ioremap(addr, size, flags); +} +EXPORT_SYMBOL(ioremap_flags); + void __iomem * __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) { @@ -247,20 +254,7 @@ void iounmap(volatile void __iomem *addr) } EXPORT_SYMBOL(iounmap); -void __iomem *ioport_map(unsigned long port, unsigned int len) -{ - return (void __iomem *) (port + _IO_BASE); -} - -void ioport_unmap(void __iomem *addr) -{ - /* Nothing to do */ -} -EXPORT_SYMBOL(ioport_map); -EXPORT_SYMBOL(ioport_unmap); - -int -map_page(unsigned long va, phys_addr_t pa, int flags) +int map_page(unsigned long va, phys_addr_t pa, int flags) { pmd_t *pd; pte_t *pg; diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index e9b21846ccb..16e4ee1c231 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -113,7 +113,7 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) } -static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa, +static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, unsigned long ea, unsigned long size, unsigned long flags) { @@ -129,7 +129,7 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa, return (void __iomem *) (ea + (addr & ~PAGE_MASK)); } -void __iomem * __ioremap(unsigned long addr, unsigned long size, +void __iomem * __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) { unsigned long pa, ea; @@ -169,7 +169,7 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size, } -void __iomem * ioremap(unsigned long addr, unsigned long size) +void __iomem * ioremap(phys_addr_t addr, unsigned long size) { unsigned long flags = _PAGE_NO_CACHE | _PAGE_GUARDED; @@ -178,7 +178,7 @@ void __iomem * ioremap(unsigned long addr, unsigned long size) return __ioremap(addr, size, flags); } -void __iomem * ioremap_flags(unsigned long addr, unsigned long size, +void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size, unsigned long flags) { if (ppc_md.ioremap) @@ -189,7 +189,7 @@ void __iomem * ioremap_flags(unsigned long addr, unsigned long size, #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) -int __ioremap_explicit(unsigned long pa, unsigned long ea, +int __ioremap_explicit(phys_addr_t pa, unsigned long ea, unsigned long size, unsigned long flags) { struct vm_struct *area; @@ -244,7 +244,7 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea, * * XXX what about calls before mem_init_done (ie python_countermeasures()) */ -void __iounmap(void __iomem *token) +void __iounmap(volatile void __iomem *token) { void *addr; @@ -256,7 +256,7 @@ void __iounmap(void __iomem *token) im_free(addr); } -void iounmap(void __iomem *token) +void iounmap(volatile void __iomem *token) { if (ppc_md.iounmap) ppc_md.iounmap(token); @@ -282,7 +282,7 @@ static int iounmap_subset_regions(unsigned long addr, unsigned long size) return 0; } -int __iounmap_explicit(void __iomem *start, unsigned long size) +int __iounmap_explicit(volatile void __iomem *start, unsigned long size) { struct vm_struct *area; unsigned long addr; diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index e6807d6d75b..e1f51d45598 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -588,7 +588,6 @@ static int __init chrp_probe(void) ISA_DMA_THRESHOLD = ~0L; DMA_MODE_READ = 0x44; DMA_MODE_WRITE = 0x48; - isa_io_base = CHRP_ISA_IO_BASE; /* default value */ return 1; } diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 2f16d9330cf..0f39bdbbf91 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -617,13 +617,13 @@ static void iseries_dedicated_idle(void) void __init iSeries_init_IRQ(void) { } #endif -static void __iomem *iseries_ioremap(unsigned long address, unsigned long size, +static void __iomem *iseries_ioremap(phys_addr_t address, unsigned long size, unsigned long flags) { return (void __iomem *)address; } -static void iseries_iounmap(void __iomem *token) +static void iseries_iounmap(volatile void __iomem *token) { } diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 4ec6a5a65f3..d949e9df41e 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -677,8 +677,6 @@ static int __init pmac_probe(void) #ifdef CONFIG_PPC32 /* isa_io_base gets set in pmac_pci_init */ - isa_mem_base = PMAC_ISA_MEM_BASE; - pci_dram_offset = PMAC_PCI_DRAM_OFFSET; ISA_DMA_THRESHOLD = ~0L; DMA_MODE_READ = 1; DMA_MODE_WRITE = 2; diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h index 66481bbf270..b886bec6701 100644 --- a/include/asm-powerpc/eeh.h +++ b/include/asm-powerpc/eeh.h @@ -169,104 +169,19 @@ static inline u64 eeh_readq_be(const volatile void __iomem *addr) return val; } -#define EEH_CHECK_ALIGN(v,a) \ - ((((unsigned long)(v)) & ((a) - 1)) == 0) - -static inline void eeh_memset_io(volatile void __iomem *addr, int c, - unsigned long n) -{ - void *p = (void __force *)addr; - u32 lc = c; - lc |= lc << 8; - lc |= lc << 16; - - __asm__ __volatile__ ("sync" : : : "memory"); - while(n && !EEH_CHECK_ALIGN(p, 4)) { - *((volatile u8 *)p) = c; - p++; - n--; - } - while(n >= 4) { - *((volatile u32 *)p) = lc; - p += 4; - n -= 4; - } - while(n) { - *((volatile u8 *)p) = c; - p++; - n--; - } - __asm__ __volatile__ ("sync" : : : "memory"); -} -static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *src, +static inline void eeh_memcpy_fromio(void *dest, const + volatile void __iomem *src, unsigned long n) { - void *vsrc = (void __force *) src; - void *destsave = dest; - unsigned long nsave = n; - - __asm__ __volatile__ ("sync" : : : "memory"); - while(n && (!EEH_CHECK_ALIGN(vsrc, 4) || !EEH_CHECK_ALIGN(dest, 4))) { - *((u8 *)dest) = *((volatile u8 *)vsrc); - __asm__ __volatile__ ("eieio" : : : "memory"); - vsrc++; - dest++; - n--; - } - while(n > 4) { - *((u32 *)dest) = *((volatile u32 *)vsrc); - __asm__ __volatile__ ("eieio" : : : "memory"); - vsrc += 4; - dest += 4; - n -= 4; - } - while(n) { - *((u8 *)dest) = *((volatile u8 *)vsrc); - __asm__ __volatile__ ("eieio" : : : "memory"); - vsrc++; - dest++; - n--; - } - __asm__ __volatile__ ("sync" : : : "memory"); + _memcpy_fromio(dest, src, n); /* Look for ffff's here at dest[n]. Assume that at least 4 bytes * were copied. Check all four bytes. */ - if ((nsave >= 4) && - (EEH_POSSIBLE_ERROR((*((u32 *) destsave+nsave-4)), u32))) { - eeh_check_failure(src, (*((u32 *) destsave+nsave-4))); - } + if (n >= 4 && EEH_POSSIBLE_ERROR(*((u32 *)(dest + n - 4)), u32)) + eeh_check_failure(src, *((u32 *)(dest + n - 4))); } -static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src, - unsigned long n) -{ - void *vdest = (void __force *) dest; - - __asm__ __volatile__ ("sync" : : : "memory"); - while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) { - *((volatile u8 *)vdest) = *((u8 *)src); - src++; - vdest++; - n--; - } - while(n > 4) { - *((volatile u32 *)vdest) = *((volatile u32 *)src); - src += 4; - vdest += 4; - n-=4; - } - while(n) { - *((volatile u8 *)vdest) = *((u8 *)src); - src++; - vdest++; - n--; - } - __asm__ __volatile__ ("sync" : : : "memory"); -} - -#undef EEH_CHECK_ALIGN - /* in-string eeh macros */ static inline void eeh_readsb(const volatile void __iomem *addr, void * buf, int ns) diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h index 60a8fc42997..0f66f0f82c3 100644 --- a/include/asm-powerpc/ide.h +++ b/include/asm-powerpc/ide.h @@ -22,17 +22,10 @@ #endif #endif -#ifdef __powerpc64__ #define __ide_mm_insw(p, a, c) readsw((void __iomem *)(p), (a), (c)) #define __ide_mm_insl(p, a, c) readsl((void __iomem *)(p), (a), (c)) #define __ide_mm_outsw(p, a, c) writesw((void __iomem *)(p), (a), (c)) #define __ide_mm_outsl(p, a, c) writesl((void __iomem *)(p), (a), (c)) -#else -#define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 __iomem *)(p), (a), (c)) -#define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 __iomem *)(p), (a), (c)) -#define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 __iomem *)(p), (a), (c)) -#define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 __iomem *)(p), (a), (c)) -#endif #ifndef __powerpc64__ #include diff --git a/include/asm-powerpc/io-defs.h b/include/asm-powerpc/io-defs.h index 5a660f1130d..03691ab6921 100644 --- a/include/asm-powerpc/io-defs.h +++ b/include/asm-powerpc/io-defs.h @@ -3,17 +3,20 @@ DEF_PCI_AC_RET(readb, u8, (const PCI_IO_ADDR addr), (addr)) DEF_PCI_AC_RET(readw, u16, (const PCI_IO_ADDR addr), (addr)) DEF_PCI_AC_RET(readl, u32, (const PCI_IO_ADDR addr), (addr)) -DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr)) DEF_PCI_AC_RET(readw_be, u16, (const PCI_IO_ADDR addr), (addr)) DEF_PCI_AC_RET(readl_be, u32, (const PCI_IO_ADDR addr), (addr)) -DEF_PCI_AC_RET(readq_be, u64, (const PCI_IO_ADDR addr), (addr)) DEF_PCI_AC_NORET(writeb, (u8 val, PCI_IO_ADDR addr), (val, addr)) DEF_PCI_AC_NORET(writew, (u16 val, PCI_IO_ADDR addr), (val, addr)) DEF_PCI_AC_NORET(writel, (u32 val, PCI_IO_ADDR addr), (val, addr)) -DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr)) DEF_PCI_AC_NORET(writew_be, (u16 val, PCI_IO_ADDR addr), (val, addr)) DEF_PCI_AC_NORET(writel_be, (u32 val, PCI_IO_ADDR addr), (val, addr)) + +#ifdef __powerpc64__ +DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr)) +DEF_PCI_AC_RET(readq_be, u64, (const PCI_IO_ADDR addr), (addr)) +DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr)) DEF_PCI_AC_NORET(writeq_be, (u64 val, PCI_IO_ADDR addr), (val, addr)) +#endif /* __powerpc64__ */ DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port)) DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port)) diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index 03e843fc143..53bff8bd39b 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h @@ -13,24 +13,51 @@ extern int check_legacy_ioport(unsigned long base_port); #define PNPBIOS_BASE 0xf000 /* only relevant for PReP */ -#ifndef CONFIG_PPC64 -#include -#else - #include #include #include -#include #include #include +#include #include +#ifdef CONFIG_PPC64 +#include +#endif + #define SIO_CONFIG_RA 0x398 #define SIO_CONFIG_RD 0x399 #define SLOW_DOWN_IO +/* 32 bits uses slightly different variables for the various IO + * bases. Most of this file only uses _IO_BASE though which we + * define properly based on the platform + */ +#ifndef CONFIG_PCI +#define _IO_BASE 0 +#define _ISA_MEM_BASE 0 +#define PCI_DRAM_OFFSET 0 +#elif defined(CONFIG_PPC32) +#define _IO_BASE isa_io_base +#define _ISA_MEM_BASE isa_mem_base +#define PCI_DRAM_OFFSET pci_dram_offset +#else +#define _IO_BASE pci_io_base +#define _ISA_MEM_BASE 0 +#define PCI_DRAM_OFFSET 0 +#endif + +extern unsigned long isa_io_base; +extern unsigned long isa_mem_base; +extern unsigned long pci_io_base; +extern unsigned long pci_dram_offset; + +#if defined(CONFIG_PPC32) && defined(CONFIG_PPC_INDIRECT_IO) +#error CONFIG_PPC_INDIRECT_IO is not yet supported on 32 bits +#endif + /* * * Low level MMIO accessors @@ -53,7 +80,11 @@ extern int check_legacy_ioport(unsigned long base_port); * */ +#ifdef CONFIG_PPC64 #define IO_SET_SYNC_FLAG() do { get_paca()->io_sync = 1; } while(0) +#else +#define IO_SET_SYNC_FLAG() +#endif #define DEF_MMIO_IN(name, type, insn) \ static inline type name(const volatile type __iomem *addr) \ @@ -86,17 +117,19 @@ static inline void name(volatile type __iomem *addr, type val) \ DEF_MMIO_IN_BE(in_8, 8, lbz); DEF_MMIO_IN_BE(in_be16, 16, lhz); DEF_MMIO_IN_BE(in_be32, 32, lwz); -DEF_MMIO_IN_BE(in_be64, 64, ld); DEF_MMIO_IN_LE(in_le16, 16, lhbrx); DEF_MMIO_IN_LE(in_le32, 32, lwbrx); DEF_MMIO_OUT_BE(out_8, 8, stb); DEF_MMIO_OUT_BE(out_be16, 16, sth); DEF_MMIO_OUT_BE(out_be32, 32, stw); -DEF_MMIO_OUT_BE(out_be64, 64, std); DEF_MMIO_OUT_LE(out_le16, 16, sthbrx); DEF_MMIO_OUT_LE(out_le32, 32, stwbrx); +#ifdef __powerpc64__ +DEF_MMIO_OUT_BE(out_be64, 64, std); +DEF_MMIO_IN_BE(in_be64, 64, ld); + /* There is no asm instructions for 64 bits reverse loads and stores */ static inline u64 in_le64(const volatile u64 __iomem *addr) { @@ -107,6 +140,7 @@ static inline void out_le64(volatile u64 __iomem *addr, u64 val) { out_be64(addr, cpu_to_le64(val)); } +#endif /* __powerpc64__ */ /* * Low level IO stream instructions are defined out of line for now @@ -126,6 +160,17 @@ extern void _outsl_ns(volatile u32 __iomem *addr, const void *buf, long count); #define _outsw _outsw_ns #define _outsl _outsl_ns + +/* + * memset_io, memcpy_toio, memcpy_fromio base implementations are out of line + */ + +extern void _memset_io(volatile void __iomem *addr, int c, unsigned long n); +extern void _memcpy_fromio(void *dest, const volatile void __iomem *src, + unsigned long n); +extern void _memcpy_toio(volatile void __iomem *dest, const void *src, + unsigned long n); + /* * * PCI and standard ISA accessors @@ -140,9 +185,6 @@ extern void _outsl_ns(volatile u32 __iomem *addr, const void *buf, long count); * of the accessors. */ -extern unsigned long isa_io_base; -extern unsigned long pci_io_base; - /* * Non ordered and non-swapping "raw" accessors @@ -160,10 +202,6 @@ static inline unsigned int __raw_readl(const volatile void __iomem *addr) { return *(volatile unsigned int __force *)addr; } -static inline unsigned long __raw_readq(const volatile void __iomem *addr) -{ - return *(volatile unsigned long __force *)addr; -} static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr) { *(volatile unsigned char __force *)addr = v; @@ -176,11 +214,17 @@ static inline void __raw_writel(unsigned int v, volatile void __iomem *addr) { *(volatile unsigned int __force *)addr = v; } + +#ifdef __powerpc64__ +static inline unsigned long __raw_readq(const volatile void __iomem *addr) +{ + return *(volatile unsigned long __force *)addr; +} static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) { *(volatile unsigned long __force *)addr = v; } - +#endif /* __powerpc64__ */ /* * @@ -188,7 +232,13 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) * */ +/* + * Include the EEH definitions when EEH is enabled only so they don't get + * in the way when building for 32 bits + */ +#ifdef CONFIG_EEH #include +#endif /* Shortcut to the MMIO argument pointer */ #define PCI_IO_ADDR volatile void __iomem * @@ -196,7 +246,7 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) /* Indirect IO address tokens: * * When CONFIG_PPC_INDIRECT_IO is set, the platform can provide hooks - * on all IOs. + * on all IOs. (Note that this is all 64 bits only for now) * * To help platforms who may need to differenciate MMIO addresses in * their hooks, a bitfield is reserved for use by the platform near the @@ -241,6 +291,70 @@ do { \ #define PCI_FIX_ADDR(addr) (addr) #endif +/* + * On 32 bits, PIO operations have a recovery mechanism in case they trigger + * machine checks (which they occasionally do when probing non existing + * IO ports on some platforms, like PowerMac and 8xx). + * I always found it to be of dubious reliability and I am tempted to get + * rid of it one of these days. So if you think it's important to keep it, + * please voice up asap. We never had it for 64 bits and I do not intend + * to port it over + */ + +#ifdef CONFIG_PPC32 + +#define __do_in_asm(name, op) \ +extern __inline__ unsigned int name(unsigned int port) \ +{ \ + unsigned int x; \ + __asm__ __volatile__( \ + "sync\n" \ + "0:" op " %0,0,%1\n" \ + "1: twi 0,%0,0\n" \ + "2: isync\n" \ + "3: nop\n" \ + "4:\n" \ + ".section .fixup,\"ax\"\n" \ + "5: li %0,-1\n" \ + " b 4b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 2\n" \ + " .long 0b,5b\n" \ + " .long 1b,5b\n" \ + " .long 2b,5b\n" \ + " .long 3b,5b\n" \ + ".previous" \ + : "=&r" (x) \ + : "r" (port + _IO_BASE)); \ + return x; \ +} + +#define __do_out_asm(name, op) \ +extern __inline__ void name(unsigned int val, unsigned int port) \ +{ \ + __asm__ __volatile__( \ + "sync\n" \ + "0:" op " %0,0,%1\n" \ + "1: sync\n" \ + "2:\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 2\n" \ + " .long 0b,2b\n" \ + " .long 1b,2b\n" \ + ".previous" \ + : : "r" (val), "r" (port + _IO_BASE)); \ +} + +__do_in_asm(_rec_inb, "lbzx") +__do_in_asm(_rec_inw, "lhbrx") +__do_in_asm(_rec_inl, "lwbrx") +__do_out_asm(_rec_outb, "stbx") +__do_out_asm(_rec_outw, "sthbrx") +__do_out_asm(_rec_outl, "stwbrx") + +#endif /* CONFIG_PPC32 */ + /* The "__do_*" operations below provide the actual "base" implementation * for each of the defined acccessor. Some of them use the out_* functions * directly, some of them still use EEH, though we might change that in the @@ -263,6 +377,8 @@ do { \ #define __do_writew_be(val, addr) out_be16(PCI_FIX_ADDR(addr), val) #define __do_writel_be(val, addr) out_be32(PCI_FIX_ADDR(addr), val) #define __do_writeq_be(val, addr) out_be64(PCI_FIX_ADDR(addr), val) + +#ifdef CONFIG_EEH #define __do_readb(addr) eeh_readb(PCI_FIX_ADDR(addr)) #define __do_readw(addr) eeh_readw(PCI_FIX_ADDR(addr)) #define __do_readl(addr) eeh_readl(PCI_FIX_ADDR(addr)) @@ -270,33 +386,64 @@ do { \ #define __do_readw_be(addr) eeh_readw_be(PCI_FIX_ADDR(addr)) #define __do_readl_be(addr) eeh_readl_be(PCI_FIX_ADDR(addr)) #define __do_readq_be(addr) eeh_readq_be(PCI_FIX_ADDR(addr)) - -#define __do_outb(val, port) writeb(val,(PCI_IO_ADDR)pci_io_base+port); -#define __do_outw(val, port) writew(val,(PCI_IO_ADDR)pci_io_base+port); -#define __do_outl(val, port) writel(val,(PCI_IO_ADDR)pci_io_base+port); -#define __do_inb(port) readb((PCI_IO_ADDR)pci_io_base + port); -#define __do_inw(port) readw((PCI_IO_ADDR)pci_io_base + port); -#define __do_inl(port) readl((PCI_IO_ADDR)pci_io_base + port); - +#else /* CONFIG_EEH */ +#define __do_readb(addr) in_8(PCI_FIX_ADDR(addr)) +#define __do_readw(addr) in_le16(PCI_FIX_ADDR(addr)) +#define __do_readl(addr) in_le32(PCI_FIX_ADDR(addr)) +#define __do_readq(addr) in_le64(PCI_FIX_ADDR(addr)) +#define __do_readw_be(addr) in_be16(PCI_FIX_ADDR(addr)) +#define __do_readl_be(addr) in_be32(PCI_FIX_ADDR(addr)) +#define __do_readq_be(addr) in_be64(PCI_FIX_ADDR(addr)) +#endif /* !defined(CONFIG_EEH) */ + +#ifdef CONFIG_PPC32 +#define __do_outb(val, port) _rec_outb(val, port) +#define __do_outw(val, port) _rec_outw(val, port) +#define __do_outl(val, port) _rec_outl(val, port) +#define __do_inb(port) _rec_inb(port) +#define __do_inw(port) _rec_inw(port) +#define __do_inl(port) _rec_inl(port) +#else /* CONFIG_PPC32 */ +#define __do_outb(val, port) writeb(val,(PCI_IO_ADDR)_IO_BASE+port); +#define __do_outw(val, port) writew(val,(PCI_IO_ADDR)_IO_BASE+port); +#define __do_outl(val, port) writel(val,(PCI_IO_ADDR)_IO_BASE+port); +#define __do_inb(port) readb((PCI_IO_ADDR)_IO_BASE + port); +#define __do_inw(port) readw((PCI_IO_ADDR)_IO_BASE + port); +#define __do_inl(port) readl((PCI_IO_ADDR)_IO_BASE + port); +#endif /* !CONFIG_PPC32 */ + +#ifdef CONFIG_EEH #define __do_readsb(a, b, n) eeh_readsb(PCI_FIX_ADDR(a), (b), (n)) #define __do_readsw(a, b, n) eeh_readsw(PCI_FIX_ADDR(a), (b), (n)) #define __do_readsl(a, b, n) eeh_readsl(PCI_FIX_ADDR(a), (b), (n)) +#else /* CONFIG_EEH */ +#define __do_readsb(a, b, n) _insb(PCI_FIX_ADDR(a), (b), (n)) +#define __do_readsw(a, b, n) _insw(PCI_FIX_ADDR(a), (b), (n)) +#define __do_readsl(a, b, n) _insl(PCI_FIX_ADDR(a), (b), (n)) +#endif /* !CONFIG_EEH */ #define __do_writesb(a, b, n) _outsb(PCI_FIX_ADDR(a),(b),(n)) #define __do_writesw(a, b, n) _outsw(PCI_FIX_ADDR(a),(b),(n)) #define __do_writesl(a, b, n) _outsl(PCI_FIX_ADDR(a),(b),(n)) -#define __do_insb(p, b, n) readsb((PCI_IO_ADDR)pci_io_base+(p), (b), (n)) -#define __do_insw(p, b, n) readsw((PCI_IO_ADDR)pci_io_base+(p), (b), (n)) -#define __do_insl(p, b, n) readsl((PCI_IO_ADDR)pci_io_base+(p), (b), (n)) -#define __do_outsb(p, b, n) writesb((PCI_IO_ADDR)pci_io_base+(p),(b),(n)) -#define __do_outsw(p, b, n) writesw((PCI_IO_ADDR)pci_io_base+(p),(b),(n)) -#define __do_outsl(p, b, n) writesl((PCI_IO_ADDR)pci_io_base+(p),(b),(n)) - -#define __do_memset_io(addr, c, n) eeh_memset_io(PCI_FIX_ADDR(addr), c, n) -#define __do_memcpy_fromio(dst, src, n) eeh_memcpy_fromio(dst, \ - PCI_FIX_ADDR(src), n) -#define __do_memcpy_toio(dst, src, n) eeh_memcpy_toio(PCI_FIX_ADDR(dst), \ - src, n) +#define __do_insb(p, b, n) readsb((PCI_IO_ADDR)_IO_BASE+(p), (b), (n)) +#define __do_insw(p, b, n) readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n)) +#define __do_insl(p, b, n) readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n)) +#define __do_outsb(p, b, n) writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n)) +#define __do_outsw(p, b, n) writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n)) +#define __do_outsl(p, b, n) writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n)) + +#define __do_memset_io(addr, c, n) \ + _memset_io(PCI_FIX_ADDR(addr), c, n) +#define __do_memcpy_toio(dst, src, n) \ + _memcpy_toio(PCI_FIX_ADDR(dst), src, n) + +#ifdef CONFIG_EEH +#define __do_memcpy_fromio(dst, src, n) \ + eeh_memcpy_fromio(dst, PCI_FIX_ADDR(src), n) +#else /* CONFIG_EEH */ +#define __do_memcpy_fromio(dst, src, n) \ + _memcpy_fromio(dst,PCI_FIX_ADDR(src),n) +#endif /* !CONFIG_EEH */ #ifdef CONFIG_PPC_INDIRECT_IO #define DEF_PCI_HOOK(x) x @@ -343,15 +490,27 @@ static inline void name at \ /* Some drivers check for the presence of readq & writeq with * a #ifdef, so we make them happy here. */ +#ifdef __powerpc64__ #define readq readq #define writeq writeq +#endif + +#ifdef CONFIG_NOT_COHERENT_CACHE -/* Nothing to do for cache stuff x*/ +#define dma_cache_inv(_start,_size) \ + invalidate_dcache_range(_start, (_start + _size)) +#define dma_cache_wback(_start,_size) \ + clean_dcache_range(_start, (_start + _size)) +#define dma_cache_wback_inv(_start,_size) \ + flush_dcache_range(_start, (_start + _size)) + +#else /* CONFIG_NOT_COHERENT_CACHE */ #define dma_cache_inv(_start,_size) do { } while (0) #define dma_cache_wback(_start,_size) do { } while (0) #define dma_cache_wback_inv(_start,_size) do { } while (0) +#endif /* !CONFIG_NOT_COHERENT_CACHE */ /* * Convert a physical pointer to a virtual kernel pointer for /dev/mem @@ -372,6 +531,9 @@ static inline void name at \ #define readl_relaxed(addr) readl(addr) #define readq_relaxed(addr) readq(addr) +#ifdef CONFIG_PPC32 +#define mmiowb() +#else /* * Enforce synchronisation of stores vs. spin_unlock * (this does it explicitely, though our implementation of spin_unlock @@ -385,6 +547,7 @@ static inline void mmiowb(void) : "=&r" (tmp) : "i" (offsetof(struct paca_struct, io_sync)) : "memory"); } +#endif /* !CONFIG_PPC32 */ static inline void iosync(void) { @@ -453,22 +616,29 @@ static inline void iosync(void) * be hooked (but can be used by a hook on iounmap) * */ -extern void __iomem *ioremap(unsigned long address, unsigned long size); -extern void __iomem *ioremap_flags(unsigned long address, unsigned long size, +extern void __iomem *ioremap(phys_addr_t address, unsigned long size); +extern void __iomem *ioremap_flags(phys_addr_t address, unsigned long size, unsigned long flags); #define ioremap_nocache(addr, size) ioremap((addr), (size)) -extern void iounmap(void __iomem *addr); +extern void iounmap(volatile void __iomem *addr); -extern void __iomem *__ioremap(unsigned long address, unsigned long size, +extern void __iomem *__ioremap(phys_addr_t, unsigned long size, unsigned long flags); -extern void __iounmap(void __iomem *addr); +extern void __iounmap(volatile void __iomem *addr); -extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr, +extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr, unsigned long size, unsigned long flags); -extern int __iounmap_explicit(void __iomem *start, unsigned long size); +extern int __iounmap_explicit(volatile void __iomem *start, + unsigned long size); extern void __iomem * reserve_phb_iospace(unsigned long size); +/* Those are more 32 bits only functions */ +extern unsigned long iopa(unsigned long addr); +extern unsigned long mm_ptov(unsigned long addr) __attribute_const__; +extern void io_block_mapping(unsigned long virt, phys_addr_t phys, + unsigned int size, int flags); + /* * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation @@ -538,7 +708,33 @@ static inline void * phys_to_virt(unsigned long address) */ #define BIO_VMERGE_BOUNDARY 0 +/* + * 32 bits still uses virt_to_bus() for it's implementation of DMA + * mappings se we have to keep it defined here. We also have some old + * drivers (shame shame shame) that use bus_to_virt() and haven't been + * fixed yet so I need to define it here. + */ +#ifdef CONFIG_PPC32 + +static inline unsigned long virt_to_bus(volatile void * address) +{ + if (address == NULL) + return 0; + return __pa(address) + PCI_DRAM_OFFSET; +} + +static inline void * bus_to_virt(unsigned long address) +{ + if (address == 0) + return NULL; + return __va(address - PCI_DRAM_OFFSET); +} + +#define page_to_bus(page) (page_to_phys(page) + PCI_DRAM_OFFSET) + +#endif /* CONFIG_PPC32 */ + + #endif /* __KERNEL__ */ -#endif /* CONFIG_PPC64 */ #endif /* _ASM_POWERPC_IO_H */ diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 8c1a2dfe5cc..1b04e572354 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -88,9 +88,9 @@ struct machdep_calls { void (*pci_dma_dev_setup)(struct pci_dev *dev); void (*pci_dma_bus_setup)(struct pci_bus *bus); - void __iomem * (*ioremap)(unsigned long addr, unsigned long size, + void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size, unsigned long flags); - void (*iounmap)(void __iomem *token); + void (*iounmap)(volatile void __iomem *token); #endif /* CONFIG_PPC64 */ int (*probe)(void); -- cgit v1.2.3-70-g09d2 From 757db1ed9b50d28cd4c1e7d9925c9ea7783b2f91 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 21 Nov 2006 12:35:29 +1100 Subject: [POWERPC] Fix __raw* accessors The new IO accessor code allows to stick a token in the top bit of MMIO addresses which gets masked out during actual accesses. However, the __raw_* accessors forgot to mask it out. This fixes it. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- include/asm-powerpc/io.h | 92 +++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 47 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index 53bff8bd39b..75df3bce9cc 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h @@ -185,53 +185,6 @@ extern void _memcpy_toio(volatile void __iomem *dest, const void *src, * of the accessors. */ - -/* - * Non ordered and non-swapping "raw" accessors - */ - -static inline unsigned char __raw_readb(const volatile void __iomem *addr) -{ - return *(volatile unsigned char __force *)addr; -} -static inline unsigned short __raw_readw(const volatile void __iomem *addr) -{ - return *(volatile unsigned short __force *)addr; -} -static inline unsigned int __raw_readl(const volatile void __iomem *addr) -{ - return *(volatile unsigned int __force *)addr; -} -static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr) -{ - *(volatile unsigned char __force *)addr = v; -} -static inline void __raw_writew(unsigned short v, volatile void __iomem *addr) -{ - *(volatile unsigned short __force *)addr = v; -} -static inline void __raw_writel(unsigned int v, volatile void __iomem *addr) -{ - *(volatile unsigned int __force *)addr = v; -} - -#ifdef __powerpc64__ -static inline unsigned long __raw_readq(const volatile void __iomem *addr) -{ - return *(volatile unsigned long __force *)addr; -} -static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) -{ - *(volatile unsigned long __force *)addr = v; -} -#endif /* __powerpc64__ */ - -/* - * - * PCI PIO and MMIO accessors. - * - */ - /* * Include the EEH definitions when EEH is enabled only so they don't get * in the way when building for 32 bits @@ -291,7 +244,52 @@ do { \ #define PCI_FIX_ADDR(addr) (addr) #endif + +/* + * Non ordered and non-swapping "raw" accessors + */ + +static inline unsigned char __raw_readb(const volatile void __iomem *addr) +{ + return *(volatile unsigned char __force *)PCI_FIX_ADDR(addr); +} +static inline unsigned short __raw_readw(const volatile void __iomem *addr) +{ + return *(volatile unsigned short __force *)PCI_FIX_ADDR(addr); +} +static inline unsigned int __raw_readl(const volatile void __iomem *addr) +{ + return *(volatile unsigned int __force *)PCI_FIX_ADDR(addr); +} +static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr) +{ + *(volatile unsigned char __force *)PCI_FIX_ADDR(addr) = v; +} +static inline void __raw_writew(unsigned short v, volatile void __iomem *addr) +{ + *(volatile unsigned short __force *)PCI_FIX_ADDR(addr) = v; +} +static inline void __raw_writel(unsigned int v, volatile void __iomem *addr) +{ + *(volatile unsigned int __force *)PCI_FIX_ADDR(addr) = v; +} + +#ifdef __powerpc64__ +static inline unsigned long __raw_readq(const volatile void __iomem *addr) +{ + return *(volatile unsigned long __force *)PCI_FIX_ADDR(addr); +} +static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) +{ + *(volatile unsigned long __force *)PCI_FIX_ADDR(addr) = v; +} +#endif /* __powerpc64__ */ + /* + * + * PCI PIO and MMIO accessors. + * + * * On 32 bits, PIO operations have a recovery mechanism in case they trigger * machine checks (which they occasionally do when probing non existing * IO ports on some platforms, like PowerMac and 8xx). -- cgit v1.2.3-70-g09d2 From ef2b343e99e772e35f0f9d00f7db318b6629c16e Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 10 Nov 2006 21:32:40 +0000 Subject: [POWERPC] Make soft_enabled irqs preempt safe Rewrite local_get_flags and local_irq_disable to use r13 explicitly, to avoid the risk that gcc will split get_paca()->soft_enabled into a sequence unsafe against preemption. Similar care in local_irq_restore. Signed-off-by: Hugh Dickins Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/irq.c | 57 ++++++++++++++++++++++++++++++++++++++++---- include/asm-powerpc/hw_irq.h | 20 ++++++++++++---- 2 files changed, 67 insertions(+), 10 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index e1936952017..0bd8c766583 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -97,22 +97,69 @@ EXPORT_SYMBOL(irq_desc); int distribute_irqs = 1; +static inline unsigned long get_hard_enabled(void) +{ + unsigned long enabled; + + __asm__ __volatile__("lbz %0,%1(13)" + : "=r" (enabled) : "i" (offsetof(struct paca_struct, hard_enabled))); + + return enabled; +} + +static inline void set_soft_enabled(unsigned long enable) +{ + __asm__ __volatile__("stb %0,%1(13)" + : : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled))); +} + void local_irq_restore(unsigned long en) { - get_paca()->soft_enabled = en; + /* + * get_paca()->soft_enabled = en; + * Is it ever valid to use local_irq_restore(0) when soft_enabled is 1? + * That was allowed before, and in such a case we do need to take care + * that gcc will set soft_enabled directly via r13, not choose to use + * an intermediate register, lest we're preempted to a different cpu. + */ + set_soft_enabled(en); if (!en) return; if (firmware_has_feature(FW_FEATURE_ISERIES)) { - if (get_paca()->lppaca_ptr->int_dword.any_int) + /* + * Do we need to disable preemption here? Not really: in the + * unlikely event that we're preempted to a different cpu in + * between getting r13, loading its lppaca_ptr, and loading + * its any_int, we might call iseries_handle_interrupts without + * an interrupt pending on the new cpu, but that's no disaster, + * is it? And the business of preempting us off the old cpu + * would itself involve a local_irq_restore which handles the + * interrupt to that cpu. + * + * But use "local_paca->lppaca_ptr" instead of "get_lppaca()" + * to avoid any preemption checking added into get_paca(). + */ + if (local_paca->lppaca_ptr->int_dword.any_int) iseries_handle_interrupts(); return; } - if (get_paca()->hard_enabled) + /* + * if (get_paca()->hard_enabled) return; + * But again we need to take care that gcc gets hard_enabled directly + * via r13, not choose to use an intermediate register, lest we're + * preempted to a different cpu in between the two instructions. + */ + if (get_hard_enabled()) return; - /* need to hard-enable interrupts here */ - get_paca()->hard_enabled = en; + + /* + * Need to hard-enable interrupts here. Since currently disabled, + * no need to take further asm precautions against preemption; but + * use local_paca instead of get_paca() to avoid preemption checking. + */ + local_paca->hard_enabled = en; if ((int)mfspr(SPRN_DEC) < 0) mtspr(SPRN_DEC, 1); hard_irq_enable(); diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h index c4a1ab608f6..fd3f2a20627 100644 --- a/include/asm-powerpc/hw_irq.h +++ b/include/asm-powerpc/hw_irq.h @@ -18,15 +18,25 @@ extern void timer_interrupt(struct pt_regs *); static inline unsigned long local_get_flags(void) { - return get_paca()->soft_enabled; + unsigned long flags; + + __asm__ __volatile__("lbz %0,%1(13)" + : "=r" (flags) + : "i" (offsetof(struct paca_struct, soft_enabled))); + + return flags; } static inline unsigned long local_irq_disable(void) { - unsigned long flag = get_paca()->soft_enabled; - get_paca()->soft_enabled = 0; - barrier(); - return flag; + unsigned long flags, zero; + + __asm__ __volatile__("li %1,0; lbz %0,%2(13); stb %1,%2(13)" + : "=r" (flags), "=&r" (zero) + : "i" (offsetof(struct paca_struct, soft_enabled)) + : "memory"); + + return flags; } extern void local_irq_restore(unsigned long); -- cgit v1.2.3-70-g09d2 From 088df4d256227b3d927bb6ed57e66d138da0565c Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Thu, 16 Nov 2006 15:41:15 -0600 Subject: [POWERPC] Wrap cpu_die() with CONFIG_HOTPLUG_CPU Per email discussion, it appears that rtas_stop_self() and pSeries_mach_cpu_die() should not be compiled if CONFIG_HOTPLUG_CPU is not defined. This patch adds #ifdefs around these bits of code. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 5 +++-- arch/powerpc/platforms/pseries/setup.c | 4 ++++ include/asm-powerpc/rtas.h | 2 -- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 6ef80d4e38d..387ed0d9ad6 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -810,9 +810,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) return 0; } +#ifdef CONFIG_HOTPLUG_CPU /* This version can't take the spinlock, because it never returns */ - -struct rtas_args rtas_stop_self_args = { +static struct rtas_args rtas_stop_self_args = { /* The token is initialized for real in setup_system() */ .token = RTAS_UNKNOWN_SERVICE, .nargs = 0, @@ -834,6 +834,7 @@ void rtas_stop_self(void) panic("Alas, I survived.\n"); } +#endif /* * Call early during boot, before mem init or bootmem, to retrieve the RTAS diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index a8f3812aa38..0dc2548ca9b 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -347,6 +347,7 @@ static int __init pSeries_init_panel(void) } arch_initcall(pSeries_init_panel); +#ifdef CONFIG_HOTPLUG_CPU static void pSeries_mach_cpu_die(void) { local_irq_disable(); @@ -357,6 +358,9 @@ static void pSeries_mach_cpu_die(void) BUG(); for(;;); } +#else +#define pSeries_mach_cpu_die NULL +#endif static int pseries_set_dabr(unsigned long dabr) { diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index d34f9e1f242..5a0c136c041 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h @@ -54,8 +54,6 @@ struct rtas_args { rtas_arg_t *rets; /* Pointer to return values in args[]. */ }; -extern struct rtas_args rtas_stop_self_args; - struct rtas_t { unsigned long entry; /* physical address pointer */ unsigned long base; /* physical address pointer */ -- cgit v1.2.3-70-g09d2 From 3e00a5aec3d6af687e37f4e7482f5c7ecdcabd0b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 16 Nov 2006 14:03:33 +1100 Subject: [POWERPC] Xserve cpu-meter driver This is a small driver for the Xserve G5 CPU-meter blue LEDs on the front-panel. It might work on the Xserve G4 as well though that was not tested. It's pretty basic and could use some improvements if somebody cares doing them. :) Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- drivers/macintosh/Kconfig | 7 + drivers/macintosh/Makefile | 1 + drivers/macintosh/rack-meter.c | 612 +++++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/dbdma.h | 8 +- 4 files changed, 627 insertions(+), 1 deletion(-) create mode 100644 drivers/macintosh/rack-meter.c (limited to 'include/asm-powerpc') diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 7f8477d3a66..92ccee85e2a 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig @@ -228,4 +228,11 @@ config ANSLCD tristate "Support for ANS LCD display" depends on ADB_CUDA && PPC_PMAC +config PMAC_RACKMETER + tristate "Support for Apple XServe front panel LEDs" + depends on PPC_PMAC + help + This driver procides some support to control the front panel + blue LEDs "vu-meter" of the XServer macs. + endmenu diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index b53d45f87b0..2dfc3f4eaf4 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile @@ -42,3 +42,4 @@ obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \ windfarm_smu_sensors.o \ windfarm_max6690_sensor.o \ windfarm_lm75_sensor.o windfarm_pid.o +obj-$(CONFIG_PMAC_RACKMETER) += rack-meter.o diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c new file mode 100644 index 00000000000..f1b6f563673 --- /dev/null +++ b/drivers/macintosh/rack-meter.c @@ -0,0 +1,612 @@ +/* + * RackMac vu-meter driver + * + * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp. + * + * + * Released under the term of the GNU GPL v2. + * + * Support the CPU-meter LEDs of the Xserve G5 + * + * TODO: Implement PWM to do variable intensity and provide userland + * interface for fun. Also, the CPU-meter could be made nicer by being + * a bit less "immediate" but giving instead a more average load over + * time. Patches welcome :-) + * + */ +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Number of samples in a sample buffer */ +#define SAMPLE_COUNT 256 + +/* CPU meter sampling rate in ms */ +#define CPU_SAMPLING_RATE 250 + +struct rackmeter_dma { + struct dbdma_cmd cmd[4] ____cacheline_aligned; + u32 mark ____cacheline_aligned; + u32 buf1[SAMPLE_COUNT] ____cacheline_aligned; + u32 buf2[SAMPLE_COUNT] ____cacheline_aligned; +} ____cacheline_aligned; + +struct rackmeter_cpu { + struct work_struct sniffer; + cputime64_t prev_wall; + cputime64_t prev_idle; + int zero; +} ____cacheline_aligned; + +struct rackmeter { + struct macio_dev *mdev; + unsigned int irq; + struct device_node *i2s; + u8 *ubuf; + struct dbdma_regs __iomem *dma_regs; + void __iomem *i2s_regs; + dma_addr_t dma_buf_p; + struct rackmeter_dma *dma_buf_v; + int stale_irq; + struct rackmeter_cpu cpu[2]; + int paused; + struct mutex sem; +}; + +/* To be set as a tunable */ +static int rackmeter_ignore_nice; + +/* This GPIO is whacked by the OS X driver when initializing */ +#define RACKMETER_MAGIC_GPIO 0x78 + +/* This is copied from cpufreq_ondemand, maybe we should put it in + * a common header somewhere + */ +static inline cputime64_t get_cpu_idle_time(unsigned int cpu) +{ + cputime64_t retval; + + retval = cputime64_add(kstat_cpu(cpu).cpustat.idle, + kstat_cpu(cpu).cpustat.iowait); + + if (rackmeter_ignore_nice) + retval = cputime64_add(retval, kstat_cpu(cpu).cpustat.nice); + + return retval; +} + +static void rackmeter_setup_i2s(struct rackmeter *rm) +{ + struct macio_chip *macio = rm->mdev->bus->chip; + + /* First whack magic GPIO */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, RACKMETER_MAGIC_GPIO, 5); + + + /* Call feature code to enable the sound channel and the proper + * clock sources + */ + pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, rm->i2s, 0, 1); + + /* Power i2s and stop i2s clock. We whack MacIO FCRs directly for now. + * This is a bit racy, thus we should add new platform functions to + * handle that. snd-aoa needs that too + */ + MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE); + MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT); + (void)MACIO_IN32(KEYLARGO_FCR1); + udelay(10); + + /* Then setup i2s. For now, we use the same magic value that + * the OS X driver seems to use. We might want to play around + * with the clock divisors later + */ + out_le32(rm->i2s_regs + 0x10, 0x01fa0000); + (void)in_le32(rm->i2s_regs + 0x10); + udelay(10); + + /* Fully restart i2s*/ + MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE | + KL1_I2S0_CLK_ENABLE_BIT); + (void)MACIO_IN32(KEYLARGO_FCR1); + udelay(10); +} + +static void rackmeter_set_default_pattern(struct rackmeter *rm) +{ + int i; + + for (i = 0; i < 16; i++) { + if (i < 8) + rm->ubuf[i] = (i & 1) * 255; + else + rm->ubuf[i] = ((~i) & 1) * 255; + } +} + +static void rackmeter_do_pause(struct rackmeter *rm, int pause) +{ + struct rackmeter_dma *rdma = rm->dma_buf_v; + + pr_debug("rackmeter: %s\n", pause ? "paused" : "started"); + + rm->paused = pause; + if (pause) { + DBDMA_DO_STOP(rm->dma_regs); + return; + } + memset(rdma->buf1, 0, SAMPLE_COUNT & sizeof(u32)); + memset(rdma->buf2, 0, SAMPLE_COUNT & sizeof(u32)); + + rm->dma_buf_v->mark = 0; + + mb(); + out_le32(&rm->dma_regs->cmdptr_hi, 0); + out_le32(&rm->dma_regs->cmdptr, rm->dma_buf_p); + out_le32(&rm->dma_regs->control, (RUN << 16) | RUN); +} + +static void rackmeter_setup_dbdma(struct rackmeter *rm) +{ + struct rackmeter_dma *db = rm->dma_buf_v; + struct dbdma_cmd *cmd = db->cmd; + + /* Make sure dbdma is reset */ + DBDMA_DO_RESET(rm->dma_regs); + + pr_debug("rackmeter: mark offset=0x%lx\n", + offsetof(struct rackmeter_dma, mark)); + pr_debug("rackmeter: buf1 offset=0x%lx\n", + offsetof(struct rackmeter_dma, buf1)); + pr_debug("rackmeter: buf2 offset=0x%lx\n", + offsetof(struct rackmeter_dma, buf2)); + + /* Prepare 4 dbdma commands for the 2 buffers */ + memset(cmd, 0, 4 * sizeof(struct dbdma_cmd)); + st_le16(&cmd->req_count, 4); + st_le16(&cmd->command, STORE_WORD | INTR_ALWAYS | KEY_SYSTEM); + st_le32(&cmd->phy_addr, rm->dma_buf_p + + offsetof(struct rackmeter_dma, mark)); + st_le32(&cmd->cmd_dep, 0x02000000); + cmd++; + + st_le16(&cmd->req_count, SAMPLE_COUNT * 4); + st_le16(&cmd->command, OUTPUT_MORE); + st_le32(&cmd->phy_addr, rm->dma_buf_p + + offsetof(struct rackmeter_dma, buf1)); + cmd++; + + st_le16(&cmd->req_count, 4); + st_le16(&cmd->command, STORE_WORD | INTR_ALWAYS | KEY_SYSTEM); + st_le32(&cmd->phy_addr, rm->dma_buf_p + + offsetof(struct rackmeter_dma, mark)); + st_le32(&cmd->cmd_dep, 0x01000000); + cmd++; + + st_le16(&cmd->req_count, SAMPLE_COUNT * 4); + st_le16(&cmd->command, OUTPUT_MORE | BR_ALWAYS); + st_le32(&cmd->phy_addr, rm->dma_buf_p + + offsetof(struct rackmeter_dma, buf2)); + st_le32(&cmd->cmd_dep, rm->dma_buf_p); + + rackmeter_do_pause(rm, 0); +} + +static void rackmeter_do_timer(void *data) +{ + struct rackmeter *rm = data; + unsigned int cpu = smp_processor_id(); + struct rackmeter_cpu *rcpu = &rm->cpu[cpu]; + cputime64_t cur_jiffies, total_idle_ticks; + unsigned int total_ticks, idle_ticks; + int i, offset, load, cumm, pause; + + cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); + total_ticks = (unsigned int)cputime64_sub(cur_jiffies, + rcpu->prev_wall); + rcpu->prev_wall = cur_jiffies; + + total_idle_ticks = get_cpu_idle_time(cpu); + idle_ticks = (unsigned int) cputime64_sub(total_idle_ticks, + rcpu->prev_idle); + rcpu->prev_idle = total_idle_ticks; + + /* We do a very dumb calculation to update the LEDs for now, + * we'll do better once we have actual PWM implemented + */ + load = (9 * (total_ticks - idle_ticks)) / total_ticks; + + offset = cpu << 3; + cumm = 0; + for (i = 0; i < 8; i++) { + u8 ub = (load > i) ? 0xff : 0; + rm->ubuf[i + offset] = ub; + cumm |= ub; + } + rcpu->zero = (cumm == 0); + + /* Now check if LEDs are all 0, we can stop DMA */ + pause = (rm->cpu[0].zero && rm->cpu[1].zero); + if (pause != rm->paused) { + mutex_lock(&rm->sem); + pause = (rm->cpu[0].zero && rm->cpu[1].zero); + rackmeter_do_pause(rm, pause); + mutex_unlock(&rm->sem); + } + schedule_delayed_work_on(cpu, &rcpu->sniffer, + msecs_to_jiffies(CPU_SAMPLING_RATE)); +} + +static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm) +{ + unsigned int cpu; + + /* This driver works only with 1 or 2 CPUs numbered 0 and 1, + * but that's really all we have on Apple Xserve. It doesn't + * play very nice with CPU hotplug neither but we don't do that + * on those machines yet + */ + + INIT_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer, rm); + INIT_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer, rm); + + for_each_online_cpu(cpu) { + struct rackmeter_cpu *rcpu; + + if (cpu > 1) + continue; + rcpu = &rm->cpu[cpu];; + rcpu->prev_idle = get_cpu_idle_time(cpu); + rcpu->prev_wall = jiffies64_to_cputime64(get_jiffies_64()); + schedule_delayed_work_on(cpu, &rm->cpu[cpu].sniffer, + msecs_to_jiffies(CPU_SAMPLING_RATE)); + } +} + +static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm) +{ + cancel_rearming_delayed_work(&rm->cpu[0].sniffer); + cancel_rearming_delayed_work(&rm->cpu[1].sniffer); +} + +static int rackmeter_setup(struct rackmeter *rm) +{ + pr_debug("rackmeter: setting up i2s..\n"); + rackmeter_setup_i2s(rm); + + pr_debug("rackmeter: setting up default pattern..\n"); + rackmeter_set_default_pattern(rm); + + pr_debug("rackmeter: setting up dbdma..\n"); + rackmeter_setup_dbdma(rm); + + pr_debug("rackmeter: start CPU measurements..\n"); + rackmeter_init_cpu_sniffer(rm); + + printk(KERN_INFO "RackMeter initialized\n"); + + return 0; +} + +/* XXX FIXME: No PWM yet, this is 0/1 */ +static u32 rackmeter_calc_sample(struct rackmeter *rm, unsigned int index) +{ + int led; + u32 sample = 0; + + for (led = 0; led < 16; led++) { + sample >>= 1; + sample |= ((rm->ubuf[led] >= 0x80) << 15); + } + return (sample << 17) | (sample >> 15); +} + +static irqreturn_t rackmeter_irq(int irq, void *arg) +{ + struct rackmeter *rm = arg; + struct rackmeter_dma *db = rm->dma_buf_v; + unsigned int mark, i; + u32 *buf; + + /* Flush PCI buffers with an MMIO read. Maybe we could actually + * check the status one day ... in case things go wrong, though + * this never happened to me + */ + (void)in_le32(&rm->dma_regs->status); + + /* Make sure the CPU gets us in order */ + rmb(); + + /* Read mark */ + mark = db->mark; + if (mark != 1 && mark != 2) { + printk(KERN_WARNING "rackmeter: Incorrect DMA mark 0x%08x\n", + mark); + /* We allow for 3 errors like that (stale DBDMA irqs) */ + if (++rm->stale_irq > 3) { + printk(KERN_ERR "rackmeter: Too many errors," + " stopping DMA\n"); + DBDMA_DO_RESET(rm->dma_regs); + } + return IRQ_HANDLED; + } + + /* Next buffer we need to fill is mark value */ + buf = mark == 1 ? db->buf1 : db->buf2; + + /* Fill it now. This routine converts the 8 bits depth sample array + * into the PWM bitmap for each LED. + */ + for (i = 0; i < SAMPLE_COUNT; i++) + buf[i] = rackmeter_calc_sample(rm, i); + + + return IRQ_HANDLED; +} + +static int __devinit rackmeter_probe(struct macio_dev* mdev, + const struct of_device_id *match) +{ + struct device_node *i2s = NULL, *np = NULL; + struct rackmeter *rm = NULL; + struct resource ri2s, rdma; + int rc = -ENODEV; + + pr_debug("rackmeter_probe()\n"); + + /* Get i2s-a node */ + while ((i2s = of_get_next_child(mdev->ofdev.node, i2s)) != NULL) + if (strcmp(i2s->name, "i2s-a") == 0) + break; + if (i2s == NULL) { + pr_debug(" i2s-a child not found\n"); + goto bail; + } + /* Get lightshow or virtual sound */ + while ((np = of_get_next_child(i2s, np)) != NULL) { + if (strcmp(np->name, "lightshow") == 0) + break; + if ((strcmp(np->name, "sound") == 0) && + get_property(np, "virtual", NULL) != NULL) + break; + } + if (np == NULL) { + pr_debug(" lightshow or sound+virtual child not found\n"); + goto bail; + } + + /* Create and initialize our instance data */ + rm = kzalloc(sizeof(struct rackmeter), GFP_KERNEL); + if (rm == NULL) { + printk(KERN_ERR "rackmeter: failed to allocate memory !\n"); + rc = -ENOMEM; + goto bail_release; + } + rm->mdev = mdev; + rm->i2s = i2s; + mutex_init(&rm->sem); + dev_set_drvdata(&mdev->ofdev.dev, rm); + /* Check resources availability. We need at least resource 0 and 1 */ +#if 0 /* Use that when i2s-a is finally an mdev per-se */ + if (macio_resource_count(mdev) < 2 || macio_irq_count(mdev) < 2) { + printk(KERN_ERR + "rackmeter: found match but lacks resources: %s" + " (%d resources, %d interrupts)\n", + mdev->ofdev.node->full_name); + rc = -ENXIO; + goto bail_free; + } + if (macio_request_resources(mdev, "rackmeter")) { + printk(KERN_ERR + "rackmeter: failed to request resources: %s\n", + mdev->ofdev.node->full_name); + rc = -EBUSY; + goto bail_free; + } + rm->irq = macio_irq(mdev, 1); +#else + rm->irq = irq_of_parse_and_map(i2s, 1); + if (rm->irq == NO_IRQ || + of_address_to_resource(i2s, 0, &ri2s) || + of_address_to_resource(i2s, 1, &rdma)) { + printk(KERN_ERR + "rackmeter: found match but lacks resources: %s", + mdev->ofdev.node->full_name); + rc = -ENXIO; + goto bail_free; + } +#endif + + pr_debug(" i2s @0x%08x\n", (unsigned int)ri2s.start); + pr_debug(" dma @0x%08x\n", (unsigned int)rdma.start); + pr_debug(" irq %d\n", rm->irq); + + rm->ubuf = (u8 *)__get_free_page(GFP_KERNEL); + if (rm->ubuf == NULL) { + printk(KERN_ERR + "rackmeter: failed to allocate samples page !\n"); + rc = -ENOMEM; + goto bail_release; + } + + rm->dma_buf_v = dma_alloc_coherent(&macio_get_pci_dev(mdev)->dev, + sizeof(struct rackmeter_dma), + &rm->dma_buf_p, GFP_KERNEL); + if (rm->dma_buf_v == NULL) { + printk(KERN_ERR + "rackmeter: failed to allocate dma buffer !\n"); + rc = -ENOMEM; + goto bail_free_samples; + } +#if 0 + rm->i2s_regs = ioremap(macio_resource_start(mdev, 0), 0x1000); +#else + rm->i2s_regs = ioremap(ri2s.start, 0x1000); +#endif + if (rm->i2s_regs == NULL) { + printk(KERN_ERR + "rackmeter: failed to map i2s registers !\n"); + rc = -ENXIO; + goto bail_free_dma; + } +#if 0 + rm->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x100); +#else + rm->dma_regs = ioremap(rdma.start, 0x100); +#endif + if (rm->dma_regs == NULL) { + printk(KERN_ERR + "rackmeter: failed to map dma registers !\n"); + rc = -ENXIO; + goto bail_unmap_i2s; + } + + rc = rackmeter_setup(rm); + if (rc) { + printk(KERN_ERR + "rackmeter: failed to initialize !\n"); + rc = -ENXIO; + goto bail_unmap_dma; + } + + rc = request_irq(rm->irq, rackmeter_irq, 0, "rackmeter", rm); + if (rc != 0) { + printk(KERN_ERR + "rackmeter: failed to request interrupt !\n"); + goto bail_stop_dma; + } + of_node_put(np); + return 0; + + bail_stop_dma: + DBDMA_DO_RESET(rm->dma_regs); + bail_unmap_dma: + iounmap(rm->dma_regs); + bail_unmap_i2s: + iounmap(rm->i2s_regs); + bail_free_dma: + dma_free_coherent(&macio_get_pci_dev(mdev)->dev, + sizeof(struct rackmeter_dma), + rm->dma_buf_v, rm->dma_buf_p); + bail_free_samples: + free_page((unsigned long)rm->ubuf); + bail_release: +#if 0 + macio_release_resources(mdev); +#endif + bail_free: + kfree(rm); + bail: + of_node_put(i2s); + of_node_put(np); + dev_set_drvdata(&mdev->ofdev.dev, NULL); + return rc; +} + +static int __devexit rackmeter_remove(struct macio_dev* mdev) +{ + struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev); + + /* Stop CPU sniffer timer & work queues */ + rackmeter_stop_cpu_sniffer(rm); + + /* Clear reference to private data */ + dev_set_drvdata(&mdev->ofdev.dev, NULL); + + /* Stop/reset dbdma */ + DBDMA_DO_RESET(rm->dma_regs); + + /* Release the IRQ */ + free_irq(rm->irq, rm); + + /* Unmap registers */ + iounmap(rm->dma_regs); + iounmap(rm->i2s_regs); + + /* Free DMA */ + dma_free_coherent(&macio_get_pci_dev(mdev)->dev, + sizeof(struct rackmeter_dma), + rm->dma_buf_v, rm->dma_buf_p); + + /* Free samples */ + free_page((unsigned long)rm->ubuf); + +#if 0 + /* Release resources */ + macio_release_resources(mdev); +#endif + + /* Get rid of me */ + kfree(rm); + + return 0; +} + +static int rackmeter_shutdown(struct macio_dev* mdev) +{ + struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev); + + if (rm == NULL) + return -ENODEV; + + /* Stop CPU sniffer timer & work queues */ + rackmeter_stop_cpu_sniffer(rm); + + /* Stop/reset dbdma */ + DBDMA_DO_RESET(rm->dma_regs); + + return 0; +} + +static struct of_device_id rackmeter_match[] = { + { .name = "i2s" }, + { } +}; + +static struct macio_driver rackmeter_drv = { + .name = "rackmeter", + .owner = THIS_MODULE, + .match_table = rackmeter_match, + .probe = rackmeter_probe, + .remove = rackmeter_remove, + .shutdown = rackmeter_shutdown, +}; + + +static int __init rackmeter_init(void) +{ + pr_debug("rackmeter_init()\n"); + + return macio_register_driver(&rackmeter_drv); +} + +static void __exit rackmeter_exit(void) +{ + pr_debug("rackmeter_exit()\n"); + + macio_unregister_driver(&rackmeter_drv); +} + +module_init(rackmeter_init); +module_exit(rackmeter_exit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("RackMeter: Support vu-meter on XServe front panel"); diff --git a/include/asm-powerpc/dbdma.h b/include/asm-powerpc/dbdma.h index 8973565f95d..e23f07e73cb 100644 --- a/include/asm-powerpc/dbdma.h +++ b/include/asm-powerpc/dbdma.h @@ -95,7 +95,13 @@ struct dbdma_cmd { #define DBDMA_DO_STOP(regs) do { \ out_le32(&((regs)->control), (RUN|FLUSH)<<16); \ while(in_le32(&((regs)->status)) & (ACTIVE|FLUSH)) \ - ; \ + ; \ +} while(0) + +#define DBDMA_DO_RESET(regs) do { \ + out_le32(&((regs)->control), (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);\ + while(in_le32(&((regs)->status)) & (RUN)) \ + ; \ } while(0) #endif /* _ASM_DBDMA_H_ */ -- cgit v1.2.3-70-g09d2 From 8dc86ab954d28513f75918d743c40cddbff7388a Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Mon, 20 Nov 2006 18:44:56 +0100 Subject: [POWERPC] Change ppc_rtas declaration to weak Change the definition of powerpc's cond_syscall() to use the standard gcc weak attribute specifier which provides proper support for C linkage as needed by spu_syscall_table[]. Fixes this powerpc build error with CONFIG_SPU_FS=y, CONFIG_PPC_RTAS=n: arch/powerpc/platforms/built-in.o: undefined reference to `ppc_rtas' Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- include/asm-powerpc/unistd.h | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index 0e4ea37f646..04b6c17cc59 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h @@ -446,7 +446,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 #include #include #include -#include #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR @@ -481,16 +480,9 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 /* * "Conditional" syscalls - * - * What we want is __attribute__((weak,alias("sys_ni_syscall"))), - * but it doesn't work on all toolchains, so we just do it by hand */ -#ifdef CONFIG_PPC32 -#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") -#else -#define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall") -#endif - +#define cond_syscall(x) \ + asmlinkage long x (void) __attribute__((weak,alias("sys_ni_syscall"))) #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ -- cgit v1.2.3-70-g09d2 From b9e3bd774bb1a90fee9b90f461a51e4ba295fe6d Mon Sep 17 00:00:00 2001 From: Dwayne Grant McConnell Date: Mon, 20 Nov 2006 18:44:58 +0100 Subject: [POWERPC] spufs: Add /lslr, /dma_info and /proxydma files The /lslr file gives read access to the SPU_LSLR register in hex; 0x3fff for example The /dma_info file provides read access to the SPU Command Queue in a binary format. The /proxydma_info files provides read access access to the Proxy Command Queue in a binary format. The spu_info.h file provides data structures for interpreting the binary format of /dma_info and /proxydma_info. Signed-off-by: Dwayne Grant McConnell Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/backing_ops.c | 1 + arch/powerpc/platforms/cell/spufs/file.c | 133 +++++++++++++++++++++++- arch/powerpc/platforms/cell/spufs/spufs.h | 9 +- include/asm-powerpc/Kbuild | 1 + include/asm-powerpc/spu_info.h | 54 ++++++++++ 5 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 include/asm-powerpc/spu_info.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c index 2d22cd59d6f..21b28f61b00 100644 --- a/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include "spufs.h" diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 7f126270667..5bfabffd117 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "spufs.h" @@ -1482,6 +1483,23 @@ static u64 spufs_event_mask_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, spufs_event_mask_set, "0x%llx\n") +static u64 spufs_event_status_get(void *data) +{ + struct spu_context *ctx = data; + struct spu_state *state = &ctx->csa; + u64 ret = 0; + u64 stat; + + spu_acquire_saved(ctx); + stat = state->spu_chnlcnt_RW[0]; + if (stat) + ret = state->spu_chnldata_RW[0]; + spu_release(ctx); + return ret; +} +DEFINE_SIMPLE_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get, + NULL, "0x%llx\n") + static void spufs_srr0_set(void *data, u64 val) { struct spu_context *ctx = data; @@ -1535,6 +1553,109 @@ static void spufs_object_id_set(void *data, u64 id) DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, spufs_object_id_set, "0x%llx\n"); +static u64 spufs_lslr_get(void *data) +{ + struct spu_context *ctx = data; + u64 ret; + + spu_acquire_saved(ctx); + ret = ctx->csa.priv2.spu_lslr_RW; + spu_release(ctx); + + return ret; +} +DEFINE_SIMPLE_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n") + +static int spufs_info_open(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + file->private_data = ctx; + return 0; +} + +static ssize_t spufs_dma_info_read(struct file *file, char __user *buf, + size_t len, loff_t *pos) +{ + struct spu_context *ctx = file->private_data; + struct spu_dma_info info; + struct mfc_cq_sr *qp, *spuqp; + int i; + + if (!access_ok(VERIFY_WRITE, buf, len)) + return -EFAULT; + + spu_acquire_saved(ctx); + spin_lock(&ctx->csa.register_lock); + info.dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW; + info.dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0]; + info.dma_info_status = ctx->csa.spu_chnldata_RW[24]; + info.dma_info_stall_and_notify = ctx->csa.spu_chnldata_RW[25]; + info.dma_info_atomic_command_status = ctx->csa.spu_chnldata_RW[27]; + for (i = 0; i < 16; i++) { + qp = &info.dma_info_command_data[i]; + spuqp = &ctx->csa.priv2.spuq[i]; + + qp->mfc_cq_data0_RW = spuqp->mfc_cq_data0_RW; + qp->mfc_cq_data1_RW = spuqp->mfc_cq_data1_RW; + qp->mfc_cq_data2_RW = spuqp->mfc_cq_data2_RW; + qp->mfc_cq_data3_RW = spuqp->mfc_cq_data3_RW; + } + spin_unlock(&ctx->csa.register_lock); + spu_release(ctx); + + return simple_read_from_buffer(buf, len, pos, &info, + sizeof info); +} + +static struct file_operations spufs_dma_info_fops = { + .open = spufs_info_open, + .read = spufs_dma_info_read, +}; + +static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf, + size_t len, loff_t *pos) +{ + struct spu_context *ctx = file->private_data; + struct spu_proxydma_info info; + int ret = sizeof info; + struct mfc_cq_sr *qp, *puqp; + int i; + + if (len < ret) + return -EINVAL; + + if (!access_ok(VERIFY_WRITE, buf, len)) + return -EFAULT; + + spu_acquire_saved(ctx); + spin_lock(&ctx->csa.register_lock); + info.proxydma_info_type = ctx->csa.prob.dma_querytype_RW; + info.proxydma_info_mask = ctx->csa.prob.dma_querymask_RW; + info.proxydma_info_status = ctx->csa.prob.dma_tagstatus_R; + for (i = 0; i < 8; i++) { + qp = &info.proxydma_info_command_data[i]; + puqp = &ctx->csa.priv2.puq[i]; + + qp->mfc_cq_data0_RW = puqp->mfc_cq_data0_RW; + qp->mfc_cq_data1_RW = puqp->mfc_cq_data1_RW; + qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW; + qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW; + } + spin_unlock(&ctx->csa.register_lock); + spu_release(ctx); + + if (copy_to_user(buf, &info, sizeof info)) + ret = -EFAULT; + + return ret; +} + +static struct file_operations spufs_proxydma_info_fops = { + .open = spufs_info_open, + .read = spufs_proxydma_info_read, +}; + struct tree_descr spufs_dir_contents[] = { { "mem", &spufs_mem_fops, 0666, }, { "regs", &spufs_regs_fops, 0666, }, @@ -1548,19 +1669,23 @@ struct tree_descr spufs_dir_contents[] = { { "signal2", &spufs_signal2_fops, 0666, }, { "signal1_type", &spufs_signal1_type, 0666, }, { "signal2_type", &spufs_signal2_type, 0666, }, - { "mss", &spufs_mss_fops, 0666, }, - { "mfc", &spufs_mfc_fops, 0666, }, { "cntl", &spufs_cntl_fops, 0666, }, - { "npc", &spufs_npc_ops, 0666, }, { "fpcr", &spufs_fpcr_fops, 0666, }, + { "lslr", &spufs_lslr_ops, 0444, }, + { "mfc", &spufs_mfc_fops, 0666, }, + { "mss", &spufs_mss_fops, 0666, }, + { "npc", &spufs_npc_ops, 0666, }, + { "srr0", &spufs_srr0_ops, 0666, }, { "decr", &spufs_decr_ops, 0666, }, { "decr_status", &spufs_decr_status_ops, 0666, }, { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, }, { "event_mask", &spufs_event_mask_ops, 0666, }, - { "srr0", &spufs_srr0_ops, 0666, }, + { "event_status", &spufs_event_status_ops, 0444, }, { "psmap", &spufs_psmap_fops, 0666, }, { "phys-id", &spufs_id_ops, 0666, }, { "object-id", &spufs_object_id_ops, 0666, }, + { "dma_info", &spufs_dma_info_fops, 0444, }, + { "proxydma_info", &spufs_proxydma_info_fops, 0444, }, {}, }; diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index f438f0b8525..3e7cfc24614 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -29,6 +29,7 @@ #include #include +#include /* The magic number for our file system */ enum { @@ -119,8 +120,12 @@ struct spu_context_ops { int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode); u32 (*read_mfc_tagstatus)(struct spu_context * ctx); u32 (*get_mfc_free_elements)(struct spu_context *ctx); - int (*send_mfc_command)(struct spu_context *ctx, - struct mfc_dma_command *cmd); + int (*send_mfc_command)(struct spu_context * ctx, + struct mfc_dma_command * cmd); + void (*dma_info_read) (struct spu_context * ctx, + struct spu_dma_info * info); + void (*proxydma_info_read) (struct spu_context * ctx, + struct spu_proxydma_info * info); }; extern struct spu_context_ops spu_hw_ops; diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild index 9827849953a..1e637381c11 100644 --- a/include/asm-powerpc/Kbuild +++ b/include/asm-powerpc/Kbuild @@ -17,6 +17,7 @@ header-y += ipc.h header-y += poll.h header-y += shmparam.h header-y += sockios.h +header-y += spu_info.h header-y += ucontext.h header-y += ioctl.h header-y += linkage.h diff --git a/include/asm-powerpc/spu_info.h b/include/asm-powerpc/spu_info.h new file mode 100644 index 00000000000..3545efbf989 --- /dev/null +++ b/include/asm-powerpc/spu_info.h @@ -0,0 +1,54 @@ +/* + * SPU info structures + * + * (C) Copyright 2006 IBM Corp. + * + * Author: Dwayne Grant McConnell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _SPU_INFO_H +#define _SPU_INFO_H + +#ifdef __KERNEL__ +#include +#include +#else +struct mfc_cq_sr { + __u64 mfc_cq_data0_RW; + __u64 mfc_cq_data1_RW; + __u64 mfc_cq_data2_RW; + __u64 mfc_cq_data3_RW; +}; +#endif /* __KERNEL__ */ + +struct spu_dma_info { + __u64 dma_info_type; + __u64 dma_info_mask; + __u64 dma_info_status; + __u64 dma_info_stall_and_notify; + __u64 dma_info_atomic_command_status; + struct mfc_cq_sr dma_info_command_data[16]; +}; + +struct spu_proxydma_info { + __u64 proxydma_info_type; + __u64 proxydma_info_mask; + __u64 proxydma_info_status; + struct mfc_cq_sr proxydma_info_command_data[8]; +}; + +#endif -- cgit v1.2.3-70-g09d2 From e4f6948cfc8b9626022db0f93e7cf2ce5c0998cd Mon Sep 17 00:00:00 2001 From: Kevin Corry Date: Mon, 20 Nov 2006 18:45:14 +0100 Subject: [POWERPC] cell: Move PMU-related stuff to include/asm-powerpc/cell-pmu.h Move some PMU-related macros and function prototypes from cbe_regs.h and pmu.h in arch/powerpc/platforms/cell/ to a new header at include/asm-powerpc/cell-pmu.h This is cleaner to use from the oprofile code, since that sits in arch/powerpc/oprofile, not in the cell platform directory. Signed-off-by: Kevin Corry Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/cbe_regs.h | 31 +----------- arch/powerpc/platforms/cell/pmu.c | 1 - arch/powerpc/platforms/cell/pmu.h | 57 --------------------- include/asm-powerpc/cell-pmu.h | 90 ++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 87 deletions(-) delete mode 100644 arch/powerpc/platforms/cell/pmu.h create mode 100644 include/asm-powerpc/cell-pmu.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h index bc94e664c61..a29f4a5f52c 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -15,6 +15,8 @@ #ifndef CBE_REGS_H #define CBE_REGS_H +#include + /* * * Some HID register definitions @@ -35,32 +37,6 @@ * */ -/* Macros for the pm_control register. */ -#define CBE_PM_16BIT_CTR(ctr) (1 << (24 - ((ctr) & (NR_PHYS_CTRS - 1)))) -#define CBE_PM_ENABLE_PERF_MON 0x80000000 -#define CBE_PM_STOP_AT_MAX 0x40000000 -#define CBE_PM_TRACE_MODE_GET(pm_control) (((pm_control) >> 28) & 0x3) -#define CBE_PM_TRACE_MODE_SET(mode) (((mode) & 0x3) << 28) -#define CBE_PM_COUNT_MODE_SET(count) (((count) & 0x3) << 18) -#define CBE_PM_FREEZE_ALL_CTRS 0x00100000 -#define CBE_PM_ENABLE_EXT_TRACE 0x00008000 - -/* Macros for the trace_address register. */ -#define CBE_PM_TRACE_BUF_FULL 0x00000800 -#define CBE_PM_TRACE_BUF_EMPTY 0x00000400 -#define CBE_PM_TRACE_BUF_DATA_COUNT(ta) ((ta) & 0x3ff) -#define CBE_PM_TRACE_BUF_MAX_COUNT 0x400 - -/* Macros for the pm07_control registers. */ -#define CBE_PM_CTR_INPUT_MUX(pm07_control) (((pm07_control) >> 26) & 0x3f) -#define CBE_PM_CTR_INPUT_CONTROL 0x02000000 -#define CBE_PM_CTR_POLARITY 0x01000000 -#define CBE_PM_CTR_COUNT_CYCLES 0x00800000 -#define CBE_PM_CTR_ENABLE 0x00400000 - -/* Macros for the pm_status register. */ -#define CBE_PM_CTR_OVERFLOW_INTR(ctr) (1 << (31 - ((ctr) & 7))) - union spe_reg { u64 val; u8 spe[8]; @@ -160,9 +136,6 @@ extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); * counters currently have a value waiting to be written. */ -#define NR_PHYS_CTRS 4 -#define NR_CTRS (NR_PHYS_CTRS * 2) - struct cbe_pmd_shadow_regs { u32 group_control; u32 debug_bus_control; diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c index 22ac732b1f8..ae6fd1c12d4 100644 --- a/arch/powerpc/platforms/cell/pmu.c +++ b/arch/powerpc/platforms/cell/pmu.c @@ -30,7 +30,6 @@ #include "cbe_regs.h" #include "interrupt.h" -#include "pmu.h" /* * When writing to write-only mmio addresses, save a shadow copy. All of the diff --git a/arch/powerpc/platforms/cell/pmu.h b/arch/powerpc/platforms/cell/pmu.h deleted file mode 100644 index eb1e8e0af91..00000000000 --- a/arch/powerpc/platforms/cell/pmu.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Cell Broadband Engine Performance Monitor - * - * (C) Copyright IBM Corporation 2001,2006 - * - * Author: - * David Erb (djerb@us.ibm.com) - * Kevin Corry (kevcorry@us.ibm.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __PERFMON_H__ -#define __PERFMON_H__ - -enum pm_reg_name { - group_control, - debug_bus_control, - trace_address, - ext_tr_timer, - pm_status, - pm_control, - pm_interval, - pm_start_stop, -}; - -extern u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr); -extern void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val); -extern u32 cbe_read_ctr(u32 cpu, u32 ctr); -extern void cbe_write_ctr(u32 cpu, u32 ctr, u32 val); - -extern u32 cbe_read_pm07_control(u32 cpu, u32 ctr); -extern void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val); -extern u32 cbe_read_pm (u32 cpu, enum pm_reg_name reg); -extern void cbe_write_pm (u32 cpu, enum pm_reg_name reg, u32 val); - -extern u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr); -extern void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size); - -extern void cbe_enable_pm(u32 cpu); -extern void cbe_disable_pm(u32 cpu); - -extern void cbe_read_trace_buffer(u32 cpu, u64 *buf); - -#endif diff --git a/include/asm-powerpc/cell-pmu.h b/include/asm-powerpc/cell-pmu.h new file mode 100644 index 00000000000..c416fe30dee --- /dev/null +++ b/include/asm-powerpc/cell-pmu.h @@ -0,0 +1,90 @@ +/* + * Cell Broadband Engine Performance Monitor + * + * (C) Copyright IBM Corporation 2006 + * + * Author: + * David Erb (djerb@us.ibm.com) + * Kevin Corry (kevcorry@us.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_CELL_PMU_H__ +#define __ASM_CELL_PMU_H__ + +/* The Cell PMU has four hardware performance counters, which can be + * configured as four 32-bit counters or eight 16-bit counters. + */ +#define NR_PHYS_CTRS 4 +#define NR_CTRS (NR_PHYS_CTRS * 2) + +/* Macros for the pm_control register. */ +#define CBE_PM_16BIT_CTR(ctr) (1 << (24 - ((ctr) & (NR_PHYS_CTRS - 1)))) +#define CBE_PM_ENABLE_PERF_MON 0x80000000 +#define CBE_PM_STOP_AT_MAX 0x40000000 +#define CBE_PM_TRACE_MODE_GET(pm_control) (((pm_control) >> 28) & 0x3) +#define CBE_PM_TRACE_MODE_SET(mode) (((mode) & 0x3) << 28) +#define CBE_PM_COUNT_MODE_SET(count) (((count) & 0x3) << 18) +#define CBE_PM_FREEZE_ALL_CTRS 0x00100000 +#define CBE_PM_ENABLE_EXT_TRACE 0x00008000 + +/* Macros for the trace_address register. */ +#define CBE_PM_TRACE_BUF_FULL 0x00000800 +#define CBE_PM_TRACE_BUF_EMPTY 0x00000400 +#define CBE_PM_TRACE_BUF_DATA_COUNT(ta) ((ta) & 0x3ff) +#define CBE_PM_TRACE_BUF_MAX_COUNT 0x400 + +/* Macros for the pm07_control registers. */ +#define CBE_PM_CTR_INPUT_MUX(pm07_control) (((pm07_control) >> 26) & 0x3f) +#define CBE_PM_CTR_INPUT_CONTROL 0x02000000 +#define CBE_PM_CTR_POLARITY 0x01000000 +#define CBE_PM_CTR_COUNT_CYCLES 0x00800000 +#define CBE_PM_CTR_ENABLE 0x00400000 + +/* Macros for the pm_status register. */ +#define CBE_PM_CTR_OVERFLOW_INTR(ctr) (1 << (31 - ((ctr) & 7))) + +enum pm_reg_name { + group_control, + debug_bus_control, + trace_address, + ext_tr_timer, + pm_status, + pm_control, + pm_interval, + pm_start_stop, +}; + +/* Routines for reading/writing the PMU registers. */ +extern u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr); +extern void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val); +extern u32 cbe_read_ctr(u32 cpu, u32 ctr); +extern void cbe_write_ctr(u32 cpu, u32 ctr, u32 val); + +extern u32 cbe_read_pm07_control(u32 cpu, u32 ctr); +extern void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val); +extern u32 cbe_read_pm(u32 cpu, enum pm_reg_name reg); +extern void cbe_write_pm(u32 cpu, enum pm_reg_name reg, u32 val); + +extern u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr); +extern void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size); + +extern void cbe_enable_pm(u32 cpu); +extern void cbe_disable_pm(u32 cpu); + +extern void cbe_read_trace_buffer(u32 cpu, u64 *buf); + +#endif /* __ASM_CELL_PMU_H__ */ -- cgit v1.2.3-70-g09d2 From 0443bbd3d8496f9c2bc3e8c9d1833c6638722743 Mon Sep 17 00:00:00 2001 From: Kevin Corry Date: Mon, 20 Nov 2006 18:45:15 +0100 Subject: [POWERPC] cell: Add routines for managing PMU interrupts The following routines are added to arch/powerpc/platforms/cell/pmu.c: cbe_clear_pm_interrupts() cbe_enable_pm_interrupts() cbe_disable_pm_interrupts() cbe_query_pm_interrupts() cbe_pm_irq() cbe_init_pm_irq() This also adds a routine in arch/powerpc/platforms/cell/interrupt.c and some macros in cbe_regs.h to manipulate the IIC_IR register: iic_set_interrupt_routing() Signed-off-by: Kevin Corry Signed-off-by: Carl Love Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/cbe_regs.h | 8 ++++ arch/powerpc/platforms/cell/interrupt.c | 16 ++++++++ arch/powerpc/platforms/cell/interrupt.h | 2 + arch/powerpc/platforms/cell/pmu.c | 70 +++++++++++++++++++++++++++++++++ include/asm-powerpc/cell-pmu.h | 5 +++ 5 files changed, 101 insertions(+) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h index a29f4a5f52c..440a7ecc66e 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -185,6 +185,14 @@ struct cbe_iic_regs { struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ u64 iic_ir; /* 0x0440 */ +#define CBE_IIC_IR_PRIO(x) (((x) & 0xf) << 12) +#define CBE_IIC_IR_DEST_NODE(x) (((x) & 0xf) << 4) +#define CBE_IIC_IR_DEST_UNIT(x) ((x) & 0xf) +#define CBE_IIC_IR_IOC_0 0x0 +#define CBE_IIC_IR_IOC_1S 0xb +#define CBE_IIC_IR_PT_0 0xe +#define CBE_IIC_IR_PT_1 0xf + u64 iic_is; /* 0x0448 */ #define CBE_IIC_IS_PMI 0x2 diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index a914c12b406..6666d037eb4 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -396,3 +396,19 @@ void __init iic_init_IRQ(void) /* Enable on current CPU */ iic_setup_cpu(); } + +void iic_set_interrupt_routing(int cpu, int thread, int priority) +{ + struct cbe_iic_regs __iomem *iic_regs = cbe_get_cpu_iic_regs(cpu); + u64 iic_ir = 0; + int node = cpu >> 1; + + /* Set which node and thread will handle the next interrupt */ + iic_ir |= CBE_IIC_IR_PRIO(priority) | + CBE_IIC_IR_DEST_NODE(node); + if (thread == 0) + iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_0); + else + iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_1); + out_be64(&iic_regs->iic_ir, iic_ir); +} diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h index 9ba1d3c17b4..942dc39d604 100644 --- a/arch/powerpc/platforms/cell/interrupt.h +++ b/arch/powerpc/platforms/cell/interrupt.h @@ -83,5 +83,7 @@ extern u8 iic_get_target_id(int cpu); extern void spider_init_IRQ(void); +extern void iic_set_interrupt_routing(int cpu, int thread, int priority); + #endif #endif /* ASM_CELL_PIC_H */ diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c index ae6fd1c12d4..f28abf2fc27 100644 --- a/arch/powerpc/platforms/cell/pmu.c +++ b/arch/powerpc/platforms/cell/pmu.c @@ -22,9 +22,11 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include +#include #include #include @@ -338,3 +340,71 @@ void cbe_read_trace_buffer(u32 cpu, u64 *buf) } EXPORT_SYMBOL_GPL(cbe_read_trace_buffer); +/* + * Enabling/disabling interrupts for the entire performance monitoring unit. + */ + +u32 cbe_query_pm_interrupts(u32 cpu) +{ + return cbe_read_pm(cpu, pm_status); +} +EXPORT_SYMBOL_GPL(cbe_query_pm_interrupts); + +u32 cbe_clear_pm_interrupts(u32 cpu) +{ + /* Reading pm_status clears the interrupt bits. */ + return cbe_query_pm_interrupts(cpu); +} +EXPORT_SYMBOL_GPL(cbe_clear_pm_interrupts); + +void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask) +{ + /* Set which node and thread will handle the next interrupt. */ + iic_set_interrupt_routing(cpu, thread, 0); + + /* Enable the interrupt bits in the pm_status register. */ + if (mask) + cbe_write_pm(cpu, pm_status, mask); +} +EXPORT_SYMBOL_GPL(cbe_enable_pm_interrupts); + +void cbe_disable_pm_interrupts(u32 cpu) +{ + cbe_clear_pm_interrupts(cpu); + cbe_write_pm(cpu, pm_status, 0); +} +EXPORT_SYMBOL_GPL(cbe_disable_pm_interrupts); + +static irqreturn_t cbe_pm_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + perf_irq(regs); + return IRQ_HANDLED; +} + +int __init cbe_init_pm_irq(void) +{ + unsigned int irq; + int rc, node; + + for_each_node(node) { + irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI | + (node << IIC_IRQ_NODE_SHIFT)); + if (irq == NO_IRQ) { + printk("ERROR: Unable to allocate irq for node %d\n", + node); + return -EINVAL; + } + + rc = request_irq(irq, cbe_pm_irq, + IRQF_DISABLED, "cbe-pmu-0", NULL); + if (rc) { + printk("ERROR: Request for irq on node %d failed\n", + node); + return rc; + } + } + + return 0; +} +arch_initcall(cbe_init_pm_irq); + diff --git a/include/asm-powerpc/cell-pmu.h b/include/asm-powerpc/cell-pmu.h index c416fe30dee..63037c352fd 100644 --- a/include/asm-powerpc/cell-pmu.h +++ b/include/asm-powerpc/cell-pmu.h @@ -87,4 +87,9 @@ extern void cbe_disable_pm(u32 cpu); extern void cbe_read_trace_buffer(u32 cpu, u64 *buf); +extern void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask); +extern void cbe_disable_pm_interrupts(u32 cpu); +extern u32 cbe_query_pm_interrupts(u32 cpu); +extern u32 cbe_clear_pm_interrupts(u32 cpu); + #endif /* __ASM_CELL_PMU_H__ */ -- cgit v1.2.3-70-g09d2 From 18f2190d796198fbb5d4bc4c87511acf3ced7d47 Mon Sep 17 00:00:00 2001 From: Maynard Johnson Date: Mon, 20 Nov 2006 18:45:16 +0100 Subject: [POWERPC] cell: Add oprofile support Add PPU event-based and cycle-based profiling support to Oprofile for Cell. Oprofile is expected to collect data on all CPUs simultaneously. However, there is one set of performance counters per node. There are two hardware threads or virtual CPUs on each node. Hence, OProfile must multiplex in time the performance counter collection on the two virtual CPUs. The multiplexing of the performance counters is done by a virtual counter routine. Initially, the counters are configured to collect data on the even CPUs in the system, one CPU per node. In order to capture the PC for the virtual CPU when the performance counter interrupt occurs (the specified number of events between samples has occurred), the even processors are configured to handle the performance counter interrupts for their node. The virtual counter routine is called via a kernel timer after the virtual sample time. The routine stops the counters, saves the current counts, loads the last counts for the other virtual CPU on the node, sets interrupts to be handled by the other virtual CPU and restarts the counters, the virtual timer routine is scheduled to run again. The virtual sample time is kept relatively small to make sure sampling occurs on both CPUs on the node with a relatively small granularity. Whenever the counters overflow, the performance counter interrupt is called to collect the PC for the CPU where data is being collected. The oprofile driver relies on a firmware RTAS call to setup the debug bus to route the desired signals to the performance counter hardware to be counted. The RTAS call must set the routing registers appropriately in each of the islands to pass the signals down the debug bus as well as routing the signals from a particular island onto the bus. There is a second firmware RTAS call to reset the debug bus to the non pass thru state when the counters are not in use. Signed-off-by: Carl Love Signed-off-by: Maynard Johnson Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/configs/cell_defconfig | 3 +- arch/powerpc/kernel/cputable.c | 3 + arch/powerpc/oprofile/Makefile | 1 + arch/powerpc/oprofile/common.c | 15 +- arch/powerpc/oprofile/op_model_cell.c | 724 +++++++++++++++++++++++++++++++++ arch/powerpc/platforms/cell/cbe_regs.c | 12 + arch/powerpc/platforms/cell/pmu.c | 23 +- include/asm-powerpc/cell-pmu.h | 18 + include/asm-powerpc/cputable.h | 1 + include/asm-powerpc/oprofile_impl.h | 3 + 10 files changed, 798 insertions(+), 5 deletions(-) create mode 100644 arch/powerpc/oprofile/op_model_cell.c (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index dbcd4e3329d..3d6a2f10a7d 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -1121,7 +1121,8 @@ CONFIG_PLIST=y # # Instrumentation Support # -# CONFIG_PROFILING is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=y # CONFIG_KPROBES is not set # diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 1e4ed0731d1..992121b2d26 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -304,6 +304,9 @@ static struct cpu_spec cpu_specs[] = { PPC_FEATURE_SMT, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 4, + .oprofile_cpu_type = "ppc64/cell-be", + .oprofile_type = PPC_OPROFILE_CELL, .platform = "ppc-cell-be", }, { /* PA Semi PA6T */ diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 0b5df9c96ae..51c510fed7f 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile @@ -11,6 +11,7 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ timer_int.o ) oprofile-y := $(DRIVER_OBJS) common.o backtrace.o +oprofile-$(CONFIG_PPC_CELL) += op_model_cell.o oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o oprofile-$(CONFIG_6xx) += op_model_7450.o diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 63bbef3b63f..7a423437977 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -69,7 +69,10 @@ static void op_powerpc_cpu_start(void *dummy) static int op_powerpc_start(void) { - on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1); + if (model->global_start) + model->global_start(ctr); + if (model->start) + on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1); return 0; } @@ -80,7 +83,10 @@ static inline void op_powerpc_cpu_stop(void *dummy) static void op_powerpc_stop(void) { - on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1); + if (model->stop) + on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1); + if (model->global_stop) + model->global_stop(); } static int op_powerpc_create_files(struct super_block *sb, struct dentry *root) @@ -141,6 +147,11 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) switch (cur_cpu_spec->oprofile_type) { #ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_CELL + case PPC_OPROFILE_CELL: + model = &op_model_cell; + break; +#endif case PPC_OPROFILE_RS64: model = &op_model_rs64; break; diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c new file mode 100644 index 00000000000..2eb15f38810 --- /dev/null +++ b/arch/powerpc/oprofile/op_model_cell.c @@ -0,0 +1,724 @@ +/* + * Cell Broadband Engine OProfile Support + * + * (C) Copyright IBM Corporation 2006 + * + * Author: David Erb (djerb@us.ibm.com) + * Modifications: + * Carl Love + * Maynard Johnson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../platforms/cell/interrupt.h" + +#define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */ +#define CBE_COUNT_ALL_CYCLES 0x42800000 /* PPU cycle event specifier */ + +#define NUM_THREADS 2 +#define VIRT_CNTR_SW_TIME_NS 100000000 // 0.5 seconds + +struct pmc_cntrl_data { + unsigned long vcntr; + unsigned long evnts; + unsigned long masks; + unsigned long enabled; +}; + +/* + * ibm,cbe-perftools rtas parameters + */ + +struct pm_signal { + u16 cpu; /* Processor to modify */ + u16 sub_unit; /* hw subunit this applies to (if applicable) */ + u16 signal_group; /* Signal Group to Enable/Disable */ + u8 bus_word; /* Enable/Disable on this Trace/Trigger/Event + * Bus Word(s) (bitmask) + */ + u8 bit; /* Trigger/Event bit (if applicable) */ +}; + +/* + * rtas call arguments + */ +enum { + SUBFUNC_RESET = 1, + SUBFUNC_ACTIVATE = 2, + SUBFUNC_DEACTIVATE = 3, + + PASSTHRU_IGNORE = 0, + PASSTHRU_ENABLE = 1, + PASSTHRU_DISABLE = 2, +}; + +struct pm_cntrl { + u16 enable; + u16 stop_at_max; + u16 trace_mode; + u16 freeze; + u16 count_mode; +}; + +static struct { + u32 group_control; + u32 debug_bus_control; + struct pm_cntrl pm_cntrl; + u32 pm07_cntrl[NR_PHYS_CTRS]; +} pm_regs; + + +#define GET_SUB_UNIT(x) ((x & 0x0000f000) >> 12) +#define GET_BUS_WORD(x) ((x & 0x000000f0) >> 4) +#define GET_BUS_TYPE(x) ((x & 0x00000300) >> 8) +#define GET_POLARITY(x) ((x & 0x00000002) >> 1) +#define GET_COUNT_CYCLES(x) (x & 0x00000001) +#define GET_INPUT_CONTROL(x) ((x & 0x00000004) >> 2) + + +static DEFINE_PER_CPU(unsigned long[NR_PHYS_CTRS], pmc_values); + +static struct pmc_cntrl_data pmc_cntrl[NUM_THREADS][NR_PHYS_CTRS]; + +/* Interpetation of hdw_thread: + * 0 - even virtual cpus 0, 2, 4,... + * 1 - odd virtual cpus 1, 3, 5, ... + */ +static u32 hdw_thread; + +static u32 virt_cntr_inter_mask; +static struct timer_list timer_virt_cntr; + +/* pm_signal needs to be global since it is initialized in + * cell_reg_setup at the time when the necessary information + * is available. + */ +static struct pm_signal pm_signal[NR_PHYS_CTRS]; +static int pm_rtas_token; + +static u32 reset_value[NR_PHYS_CTRS]; +static int num_counters; +static int oprofile_running; +static spinlock_t virt_cntr_lock = SPIN_LOCK_UNLOCKED; + +static u32 ctr_enabled; + +static unsigned char trace_bus[4]; +static unsigned char input_bus[2]; + +/* + * Firmware interface functions + */ +static int +rtas_ibm_cbe_perftools(int subfunc, int passthru, + void *address, unsigned long length) +{ + u64 paddr = __pa(address); + + return rtas_call(pm_rtas_token, 5, 1, NULL, subfunc, passthru, + paddr >> 32, paddr & 0xffffffff, length); +} + +static void pm_rtas_reset_signals(u32 node) +{ + int ret; + struct pm_signal pm_signal_local; + + /* The debug bus is being set to the passthru disable state. + * However, the FW still expects atleast one legal signal routing + * entry or it will return an error on the arguments. If we don't + * supply a valid entry, we must ignore all return values. Ignoring + * all return values means we might miss an error we should be + * concerned about. + */ + + /* fw expects physical cpu #. */ + pm_signal_local.cpu = node; + pm_signal_local.signal_group = 21; + pm_signal_local.bus_word = 1; + pm_signal_local.sub_unit = 0; + pm_signal_local.bit = 0; + + ret = rtas_ibm_cbe_perftools(SUBFUNC_RESET, PASSTHRU_DISABLE, + &pm_signal_local, + sizeof(struct pm_signal)); + + if (ret) + printk(KERN_WARNING "%s: rtas returned: %d\n", + __FUNCTION__, ret); +} + +static void pm_rtas_activate_signals(u32 node, u32 count) +{ + int ret; + int j; + struct pm_signal pm_signal_local[NR_PHYS_CTRS]; + + for (j = 0; j < count; j++) { + /* fw expects physical cpu # */ + pm_signal_local[j].cpu = node; + pm_signal_local[j].signal_group = pm_signal[j].signal_group; + pm_signal_local[j].bus_word = pm_signal[j].bus_word; + pm_signal_local[j].sub_unit = pm_signal[j].sub_unit; + pm_signal_local[j].bit = pm_signal[j].bit; + } + + ret = rtas_ibm_cbe_perftools(SUBFUNC_ACTIVATE, PASSTHRU_ENABLE, + pm_signal_local, + count * sizeof(struct pm_signal)); + + if (ret) + printk(KERN_WARNING "%s: rtas returned: %d\n", + __FUNCTION__, ret); +} + +/* + * PM Signal functions + */ +static void set_pm_event(u32 ctr, int event, u32 unit_mask) +{ + struct pm_signal *p; + u32 signal_bit; + u32 bus_word, bus_type, count_cycles, polarity, input_control; + int j, i; + + if (event == PPU_CYCLES_EVENT_NUM) { + /* Special Event: Count all cpu cycles */ + pm_regs.pm07_cntrl[ctr] = CBE_COUNT_ALL_CYCLES; + p = &(pm_signal[ctr]); + p->signal_group = 21; + p->bus_word = 1; + p->sub_unit = 0; + p->bit = 0; + goto out; + } else { + pm_regs.pm07_cntrl[ctr] = 0; + } + + bus_word = GET_BUS_WORD(unit_mask); + bus_type = GET_BUS_TYPE(unit_mask); + count_cycles = GET_COUNT_CYCLES(unit_mask); + polarity = GET_POLARITY(unit_mask); + input_control = GET_INPUT_CONTROL(unit_mask); + signal_bit = (event % 100); + + p = &(pm_signal[ctr]); + + p->signal_group = event / 100; + p->bus_word = bus_word; + p->sub_unit = unit_mask & 0x0000f000; + + pm_regs.pm07_cntrl[ctr] = 0; + pm_regs.pm07_cntrl[ctr] |= PM07_CTR_COUNT_CYCLES(count_cycles); + pm_regs.pm07_cntrl[ctr] |= PM07_CTR_POLARITY(polarity); + pm_regs.pm07_cntrl[ctr] |= PM07_CTR_INPUT_CONTROL(input_control); + + if (input_control == 0) { + if (signal_bit > 31) { + signal_bit -= 32; + if (bus_word == 0x3) + bus_word = 0x2; + else if (bus_word == 0xc) + bus_word = 0x8; + } + + if ((bus_type == 0) && p->signal_group >= 60) + bus_type = 2; + if ((bus_type == 1) && p->signal_group >= 50) + bus_type = 0; + + pm_regs.pm07_cntrl[ctr] |= PM07_CTR_INPUT_MUX(signal_bit); + } else { + pm_regs.pm07_cntrl[ctr] = 0; + p->bit = signal_bit; + } + + for (i = 0; i < 4; i++) { + if (bus_word & (1 << i)) { + pm_regs.debug_bus_control |= + (bus_type << (31 - (2 * i) + 1)); + + for (j = 0; j < 2; j++) { + if (input_bus[j] == 0xff) { + input_bus[j] = i; + pm_regs.group_control |= + (i << (31 - i)); + break; + } + } + } + } +out: + ; +} + +static void write_pm_cntrl(int cpu, struct pm_cntrl *pm_cntrl) +{ + /* Oprofile will use 32 bit counters, set bits 7:10 to 0 */ + u32 val = 0; + if (pm_cntrl->enable == 1) + val |= CBE_PM_ENABLE_PERF_MON; + + if (pm_cntrl->stop_at_max == 1) + val |= CBE_PM_STOP_AT_MAX; + + if (pm_cntrl->trace_mode == 1) + val |= CBE_PM_TRACE_MODE_SET(pm_cntrl->trace_mode); + + if (pm_cntrl->freeze == 1) + val |= CBE_PM_FREEZE_ALL_CTRS; + + /* Routine set_count_mode must be called previously to set + * the count mode based on the user selection of user and kernel. + */ + val |= CBE_PM_COUNT_MODE_SET(pm_cntrl->count_mode); + cbe_write_pm(cpu, pm_control, val); +} + +static inline void +set_count_mode(u32 kernel, u32 user, struct pm_cntrl *pm_cntrl) +{ + /* The user must specify user and kernel if they want them. If + * neither is specified, OProfile will count in hypervisor mode + */ + if (kernel) { + if (user) + pm_cntrl->count_mode = CBE_COUNT_ALL_MODES; + else + pm_cntrl->count_mode = CBE_COUNT_SUPERVISOR_MODE; + } else { + if (user) + pm_cntrl->count_mode = CBE_COUNT_PROBLEM_MODE; + else + pm_cntrl->count_mode = CBE_COUNT_HYPERVISOR_MODE; + } +} + +static inline void enable_ctr(u32 cpu, u32 ctr, u32 * pm07_cntrl) +{ + + pm07_cntrl[ctr] |= PM07_CTR_ENABLE(1); + cbe_write_pm07_control(cpu, ctr, pm07_cntrl[ctr]); +} + +/* + * Oprofile is expected to collect data on all CPUs simultaneously. + * However, there is one set of performance counters per node. There are + * two hardware threads or virtual CPUs on each node. Hence, OProfile must + * multiplex in time the performance counter collection on the two virtual + * CPUs. The multiplexing of the performance counters is done by this + * virtual counter routine. + * + * The pmc_values used below is defined as 'per-cpu' but its use is + * more akin to 'per-node'. We need to store two sets of counter + * values per node -- one for the previous run and one for the next. + * The per-cpu[NR_PHYS_CTRS] gives us the storage we need. Each odd/even + * pair of per-cpu arrays is used for storing the previous and next + * pmc values for a given node. + * NOTE: We use the per-cpu variable to improve cache performance. + */ +static void cell_virtual_cntr(unsigned long data) +{ + /* This routine will alternate loading the virtual counters for + * virtual CPUs + */ + int i, prev_hdw_thread, next_hdw_thread; + u32 cpu; + unsigned long flags; + + /* Make sure that the interrupt_hander and + * the virt counter are not both playing with + * the counters on the same node. + */ + + spin_lock_irqsave(&virt_cntr_lock, flags); + + prev_hdw_thread = hdw_thread; + + /* switch the cpu handling the interrupts */ + hdw_thread = 1 ^ hdw_thread; + next_hdw_thread = hdw_thread; + + /* The following is done only once per each node, but + * we need cpu #, not node #, to pass to the cbe_xxx functions. + */ + for_each_online_cpu(cpu) { + if (cbe_get_hw_thread_id(cpu)) + continue; + + /* stop counters, save counter values, restore counts + * for previous thread + */ + cbe_disable_pm(cpu); + cbe_disable_pm_interrupts(cpu); + for (i = 0; i < num_counters; i++) { + per_cpu(pmc_values, cpu + prev_hdw_thread)[i] + = cbe_read_ctr(cpu, i); + + if (per_cpu(pmc_values, cpu + next_hdw_thread)[i] + == 0xFFFFFFFF) + /* If the cntr value is 0xffffffff, we must + * reset that to 0xfffffff0 when the current + * thread is restarted. This will generate a new + * interrupt and make sure that we never restore + * the counters to the max value. If the counters + * were restored to the max value, they do not + * increment and no interrupts are generated. Hence + * no more samples will be collected on that cpu. + */ + cbe_write_ctr(cpu, i, 0xFFFFFFF0); + else + cbe_write_ctr(cpu, i, + per_cpu(pmc_values, + cpu + + next_hdw_thread)[i]); + } + + /* Switch to the other thread. Change the interrupt + * and control regs to be scheduled on the CPU + * corresponding to the thread to execute. + */ + for (i = 0; i < num_counters; i++) { + if (pmc_cntrl[next_hdw_thread][i].enabled) { + /* There are some per thread events. + * Must do the set event, enable_cntr + * for each cpu. + */ + set_pm_event(i, + pmc_cntrl[next_hdw_thread][i].evnts, + pmc_cntrl[next_hdw_thread][i].masks); + enable_ctr(cpu, i, + pm_regs.pm07_cntrl); + } else { + cbe_write_pm07_control(cpu, i, 0); + } + } + + /* Enable interrupts on the CPU thread that is starting */ + cbe_enable_pm_interrupts(cpu, next_hdw_thread, + virt_cntr_inter_mask); + cbe_enable_pm(cpu); + } + + spin_unlock_irqrestore(&virt_cntr_lock, flags); + + mod_timer(&timer_virt_cntr, jiffies + HZ / 10); +} + +static void start_virt_cntrs(void) +{ + init_timer(&timer_virt_cntr); + timer_virt_cntr.function = cell_virtual_cntr; + timer_virt_cntr.data = 0UL; + timer_virt_cntr.expires = jiffies + HZ / 10; + add_timer(&timer_virt_cntr); +} + +/* This function is called once for all cpus combined */ +static void +cell_reg_setup(struct op_counter_config *ctr, + struct op_system_config *sys, int num_ctrs) +{ + int i, j, cpu; + + pm_rtas_token = rtas_token("ibm,cbe-perftools"); + if (pm_rtas_token == RTAS_UNKNOWN_SERVICE) { + printk(KERN_WARNING "%s: RTAS_UNKNOWN_SERVICE\n", + __FUNCTION__); + goto out; + } + + num_counters = num_ctrs; + + pm_regs.group_control = 0; + pm_regs.debug_bus_control = 0; + + /* setup the pm_control register */ + memset(&pm_regs.pm_cntrl, 0, sizeof(struct pm_cntrl)); + pm_regs.pm_cntrl.stop_at_max = 1; + pm_regs.pm_cntrl.trace_mode = 0; + pm_regs.pm_cntrl.freeze = 1; + + set_count_mode(sys->enable_kernel, sys->enable_user, + &pm_regs.pm_cntrl); + + /* Setup the thread 0 events */ + for (i = 0; i < num_ctrs; ++i) { + + pmc_cntrl[0][i].evnts = ctr[i].event; + pmc_cntrl[0][i].masks = ctr[i].unit_mask; + pmc_cntrl[0][i].enabled = ctr[i].enabled; + pmc_cntrl[0][i].vcntr = i; + + for_each_possible_cpu(j) + per_cpu(pmc_values, j)[i] = 0; + } + + /* Setup the thread 1 events, map the thread 0 event to the + * equivalent thread 1 event. + */ + for (i = 0; i < num_ctrs; ++i) { + if ((ctr[i].event >= 2100) && (ctr[i].event <= 2111)) + pmc_cntrl[1][i].evnts = ctr[i].event + 19; + else if (ctr[i].event == 2203) + pmc_cntrl[1][i].evnts = ctr[i].event; + else if ((ctr[i].event >= 2200) && (ctr[i].event <= 2215)) + pmc_cntrl[1][i].evnts = ctr[i].event + 16; + else + pmc_cntrl[1][i].evnts = ctr[i].event; + + pmc_cntrl[1][i].masks = ctr[i].unit_mask; + pmc_cntrl[1][i].enabled = ctr[i].enabled; + pmc_cntrl[1][i].vcntr = i; + } + + for (i = 0; i < 4; i++) + trace_bus[i] = 0xff; + + for (i = 0; i < 2; i++) + input_bus[i] = 0xff; + + /* Our counters count up, and "count" refers to + * how much before the next interrupt, and we interrupt + * on overflow. So we calculate the starting value + * which will give us "count" until overflow. + * Then we set the events on the enabled counters. + */ + for (i = 0; i < num_counters; ++i) { + /* start with virtual counter set 0 */ + if (pmc_cntrl[0][i].enabled) { + /* Using 32bit counters, reset max - count */ + reset_value[i] = 0xFFFFFFFF - ctr[i].count; + set_pm_event(i, + pmc_cntrl[0][i].evnts, + pmc_cntrl[0][i].masks); + + /* global, used by cell_cpu_setup */ + ctr_enabled |= (1 << i); + } + } + + /* initialize the previous counts for the virtual cntrs */ + for_each_online_cpu(cpu) + for (i = 0; i < num_counters; ++i) { + per_cpu(pmc_values, cpu)[i] = reset_value[i]; + } +out: + ; +} + +/* This function is called once for each cpu */ +static void cell_cpu_setup(struct op_counter_config *cntr) +{ + u32 cpu = smp_processor_id(); + u32 num_enabled = 0; + int i; + + /* There is one performance monitor per processor chip (i.e. node), + * so we only need to perform this function once per node. + */ + if (cbe_get_hw_thread_id(cpu)) + goto out; + + if (pm_rtas_token == RTAS_UNKNOWN_SERVICE) { + printk(KERN_WARNING "%s: RTAS_UNKNOWN_SERVICE\n", + __FUNCTION__); + goto out; + } + + /* Stop all counters */ + cbe_disable_pm(cpu); + cbe_disable_pm_interrupts(cpu); + + cbe_write_pm(cpu, pm_interval, 0); + cbe_write_pm(cpu, pm_start_stop, 0); + cbe_write_pm(cpu, group_control, pm_regs.group_control); + cbe_write_pm(cpu, debug_bus_control, pm_regs.debug_bus_control); + write_pm_cntrl(cpu, &pm_regs.pm_cntrl); + + for (i = 0; i < num_counters; ++i) { + if (ctr_enabled & (1 << i)) { + pm_signal[num_enabled].cpu = cbe_cpu_to_node(cpu); + num_enabled++; + } + } + + pm_rtas_activate_signals(cbe_cpu_to_node(cpu), num_enabled); +out: + ; +} + +static void cell_global_start(struct op_counter_config *ctr) +{ + u32 cpu; + u32 interrupt_mask = 0; + u32 i; + + /* This routine gets called once for the system. + * There is one performance monitor per node, so we + * only need to perform this function once per node. + */ + for_each_online_cpu(cpu) { + if (cbe_get_hw_thread_id(cpu)) + continue; + + interrupt_mask = 0; + + for (i = 0; i < num_counters; ++i) { + if (ctr_enabled & (1 << i)) { + cbe_write_ctr(cpu, i, reset_value[i]); + enable_ctr(cpu, i, pm_regs.pm07_cntrl); + interrupt_mask |= + CBE_PM_CTR_OVERFLOW_INTR(i); + } else { + /* Disable counter */ + cbe_write_pm07_control(cpu, i, 0); + } + } + + cbe_clear_pm_interrupts(cpu); + cbe_enable_pm_interrupts(cpu, hdw_thread, interrupt_mask); + cbe_enable_pm(cpu); + } + + virt_cntr_inter_mask = interrupt_mask; + oprofile_running = 1; + smp_wmb(); + + /* NOTE: start_virt_cntrs will result in cell_virtual_cntr() being + * executed which manipulates the PMU. We start the "virtual counter" + * here so that we do not need to synchronize access to the PMU in + * the above for-loop. + */ + start_virt_cntrs(); +} + +static void cell_global_stop(void) +{ + int cpu; + + /* This routine will be called once for the system. + * There is one performance monitor per node, so we + * only need to perform this function once per node. + */ + del_timer_sync(&timer_virt_cntr); + oprofile_running = 0; + smp_wmb(); + + for_each_online_cpu(cpu) { + if (cbe_get_hw_thread_id(cpu)) + continue; + + cbe_sync_irq(cbe_cpu_to_node(cpu)); + /* Stop the counters */ + cbe_disable_pm(cpu); + + /* Deactivate the signals */ + pm_rtas_reset_signals(cbe_cpu_to_node(cpu)); + + /* Deactivate interrupts */ + cbe_disable_pm_interrupts(cpu); + } +} + +static void +cell_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr) +{ + u32 cpu; + u64 pc; + int is_kernel; + unsigned long flags = 0; + u32 interrupt_mask; + int i; + + cpu = smp_processor_id(); + + /* Need to make sure the interrupt handler and the virt counter + * routine are not running at the same time. See the + * cell_virtual_cntr() routine for additional comments. + */ + spin_lock_irqsave(&virt_cntr_lock, flags); + + /* Need to disable and reenable the performance counters + * to get the desired behavior from the hardware. This + * is hardware specific. + */ + + cbe_disable_pm(cpu); + + interrupt_mask = cbe_clear_pm_interrupts(cpu); + + /* If the interrupt mask has been cleared, then the virt cntr + * has cleared the interrupt. When the thread that generated + * the interrupt is restored, the data count will be restored to + * 0xffffff0 to cause the interrupt to be regenerated. + */ + + if ((oprofile_running == 1) && (interrupt_mask != 0)) { + pc = regs->nip; + is_kernel = is_kernel_addr(pc); + + for (i = 0; i < num_counters; ++i) { + if ((interrupt_mask & CBE_PM_CTR_OVERFLOW_INTR(i)) + && ctr[i].enabled) { + oprofile_add_pc(pc, is_kernel, i); + cbe_write_ctr(cpu, i, reset_value[i]); + } + } + + /* The counters were frozen by the interrupt. + * Reenable the interrupt and restart the counters. + * If there was a race between the interrupt handler and + * the virtual counter routine. The virutal counter + * routine may have cleared the interrupts. Hence must + * use the virt_cntr_inter_mask to re-enable the interrupts. + */ + cbe_enable_pm_interrupts(cpu, hdw_thread, + virt_cntr_inter_mask); + + /* The writes to the various performance counters only writes + * to a latch. The new values (interrupt setting bits, reset + * counter value etc.) are not copied to the actual registers + * until the performance monitor is enabled. In order to get + * this to work as desired, the permormance monitor needs to + * be disabled while writting to the latches. This is a + * HW design issue. + */ + cbe_enable_pm(cpu); + } + spin_unlock_irqrestore(&virt_cntr_lock, flags); +} + +struct op_powerpc_model op_model_cell = { + .reg_setup = cell_reg_setup, + .cpu_setup = cell_cpu_setup, + .global_start = cell_global_start, + .global_stop = cell_global_stop, + .handle_interrupt = cell_handle_interrupt, +}; diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index 5a91b75c2f0..9a0ee62691d 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -130,6 +130,18 @@ struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu) } EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs); +/* FIXME + * This is little more than a stub at the moment. It should be + * fleshed out so that it works for both SMT and non-SMT, no + * matter if the passed cpu is odd or even. + * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1. + * For SMT disabled, returns 0 for all cpus. + */ +u32 cbe_get_hw_thread_id(int cpu) +{ + return (cpu & 1); +} +EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id); void __init cbe_regs_init(void) { diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c index f28abf2fc27..99c612025e8 100644 --- a/arch/powerpc/platforms/cell/pmu.c +++ b/arch/powerpc/platforms/cell/pmu.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -375,9 +376,9 @@ void cbe_disable_pm_interrupts(u32 cpu) } EXPORT_SYMBOL_GPL(cbe_disable_pm_interrupts); -static irqreturn_t cbe_pm_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t cbe_pm_irq(int irq, void *dev_id) { - perf_irq(regs); + perf_irq(get_irq_regs()); return IRQ_HANDLED; } @@ -408,3 +409,21 @@ int __init cbe_init_pm_irq(void) } arch_initcall(cbe_init_pm_irq); +void cbe_sync_irq(int node) +{ + unsigned int irq; + + irq = irq_find_mapping(NULL, + IIC_IRQ_IOEX_PMI + | (node << IIC_IRQ_NODE_SHIFT)); + + if (irq == NO_IRQ) { + printk(KERN_WARNING "ERROR, unable to get existing irq %d " \ + "for node %d\n", irq, node); + return; + } + + synchronize_irq(irq); +} +EXPORT_SYMBOL_GPL(cbe_sync_irq); + diff --git a/include/asm-powerpc/cell-pmu.h b/include/asm-powerpc/cell-pmu.h index 63037c352fd..e8c2ebd3ddd 100644 --- a/include/asm-powerpc/cell-pmu.h +++ b/include/asm-powerpc/cell-pmu.h @@ -91,5 +91,23 @@ extern void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask); extern void cbe_disable_pm_interrupts(u32 cpu); extern u32 cbe_query_pm_interrupts(u32 cpu); extern u32 cbe_clear_pm_interrupts(u32 cpu); +extern void cbe_sync_irq(int node); + +/* Utility functions, macros */ +extern u32 cbe_get_hw_thread_id(int cpu); + +#define cbe_cpu_to_node(cpu) ((cpu) >> 1) + +#define CBE_COUNT_SUPERVISOR_MODE 0 +#define CBE_COUNT_HYPERVISOR_MODE 1 +#define CBE_COUNT_PROBLEM_MODE 2 +#define CBE_COUNT_ALL_MODES 3 + +/* Macros for the pm07_control registers. */ +#define PM07_CTR_INPUT_MUX(x) (((x) & 0x3F) << 26) +#define PM07_CTR_INPUT_CONTROL(x) (((x) & 1) << 25) +#define PM07_CTR_POLARITY(x) (((x) & 1) << 24) +#define PM07_CTR_COUNT_CYCLES(x) (((x) & 1) << 23) +#define PM07_CTR_ENABLE(x) (((x) & 1) << 22) #endif /* __ASM_CELL_PMU_H__ */ diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index a9a40149a7c..762d15e4887 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -45,6 +45,7 @@ enum powerpc_oprofile_type { PPC_OPROFILE_POWER4 = 2, PPC_OPROFILE_G4 = 3, PPC_OPROFILE_BOOKE = 4, + PPC_OPROFILE_CELL = 5, }; struct cpu_spec { diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h index 07a10e590c1..71043bf3641 100644 --- a/include/asm-powerpc/oprofile_impl.h +++ b/include/asm-powerpc/oprofile_impl.h @@ -44,7 +44,9 @@ struct op_powerpc_model { int num_counters); void (*cpu_setup) (struct op_counter_config *); void (*start) (struct op_counter_config *); + void (*global_start) (struct op_counter_config *); void (*stop) (void); + void (*global_stop) (void); void (*handle_interrupt) (struct pt_regs *, struct op_counter_config *); int num_counters; @@ -54,6 +56,7 @@ extern struct op_powerpc_model op_model_fsl_booke; extern struct op_powerpc_model op_model_rs64; extern struct op_powerpc_model op_model_power4; extern struct op_powerpc_model op_model_7450; +extern struct op_powerpc_model op_model_cell; #ifndef CONFIG_FSL_BOOKE -- cgit v1.2.3-70-g09d2 From 974a76f51355d22f4f63d83d6bb1ccecd019ec58 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 10 Nov 2006 20:38:53 +1100 Subject: [POWERPC] Distinguish POWER6 partition modes and tell userspace This adds code to look at the properties firmware puts in the device tree to determine what compatibility mode the partition is in on POWER6 machines, and set the ELF aux vector AT_HWCAP and AT_PLATFORM entries appropriately. Specifically, we look at the cpu-version property in the cpu node(s). If that contains a "logical" PVR value (of the form 0x0f00000x), we call identify_cpu again with this PVR value. A value of 0x0f000001 indicates the partition is in POWER5+ compatibility mode, and a value of 0x0f000002 indicates "POWER6 architected" mode, with various extensions disabled. We also look for various other properties: ibm,dfp, ibm,purr and ibm,spurr. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cputable.c | 43 +++++++++++-- arch/powerpc/kernel/prom.c | 110 +++++++++++++++++++++++---------- arch/powerpc/kernel/prom_init.c | 3 +- arch/powerpc/kernel/setup_32.c | 2 +- arch/powerpc/kernel/setup_64.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 2 +- arch/ppc/kernel/setup.c | 2 +- include/asm-powerpc/cputable.h | 13 +++- 8 files changed, 130 insertions(+), 47 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 992121b2d26..911ac442f44 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -277,10 +277,45 @@ static struct cpu_spec cpu_specs[] = { .oprofile_mmcra_sipr = MMCRA_SIPR, .platform = "power5+", }, + { /* POWER6 in P5+ mode; 2.04-compliant processor */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x0f000001, + .cpu_name = "POWER5+", + .cpu_features = CPU_FTRS_POWER5, + .cpu_user_features = COMMON_USER_POWER5_PLUS, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 6, + .oprofile_cpu_type = "ppc64/power6", + .oprofile_type = PPC_OPROFILE_POWER4, + .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, + .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, + .oprofile_mmcra_clear = POWER6_MMCRA_THRM | + POWER6_MMCRA_OTHER, + .platform = "power5+", + }, { /* Power6 */ .pvr_mask = 0xffff0000, .pvr_value = 0x003e0000, - .cpu_name = "POWER6", + .cpu_name = "POWER6 (raw)", + .cpu_features = CPU_FTRS_POWER6, + .cpu_user_features = COMMON_USER_POWER6 | + PPC_FEATURE_POWER6_EXT, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 6, + .oprofile_cpu_type = "ppc64/power6", + .oprofile_type = PPC_OPROFILE_POWER4, + .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, + .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, + .oprofile_mmcra_clear = POWER6_MMCRA_THRM | + POWER6_MMCRA_OTHER, + .platform = "power6x", + }, + { /* 2.05-compliant processor, i.e. Power6 "architected" mode */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x0f000002, + .cpu_name = "POWER6 (architected)", .cpu_features = CPU_FTRS_POWER6, .cpu_user_features = COMMON_USER_POWER6, .icache_bsize = 128, @@ -1173,19 +1208,15 @@ static struct cpu_spec cpu_specs[] = { #endif /* CONFIG_PPC32 */ }; -struct cpu_spec *identify_cpu(unsigned long offset) +struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr) { struct cpu_spec *s = cpu_specs; struct cpu_spec **cur = &cur_cpu_spec; - unsigned int pvr = mfspr(SPRN_PVR); int i; s = PTRRELOC(s); cur = PTRRELOC(cur); - if (*cur != NULL) - return PTRRELOC(*cur); - for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) if ((pvr & s->pvr_mask) == s->pvr_value) { *cur = cpu_specs + i; diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 16d29d16b96..c18dbe77fdc 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -538,35 +538,31 @@ static struct ibm_pa_feature { {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, }; -static void __init check_cpu_pa_features(unsigned long node) +static void __init scan_features(unsigned long node, unsigned char *ftrs, + unsigned long tablelen, + struct ibm_pa_feature *fp, + unsigned long ft_size) { - unsigned char *pa_ftrs; - unsigned long len, tablelen, i, bit; - - pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen); - if (pa_ftrs == NULL) - return; + unsigned long i, len, bit; /* find descriptor with type == 0 */ for (;;) { if (tablelen < 3) return; - len = 2 + pa_ftrs[0]; + len = 2 + ftrs[0]; if (tablelen < len) return; /* descriptor 0 not found */ - if (pa_ftrs[1] == 0) + if (ftrs[1] == 0) break; tablelen -= len; - pa_ftrs += len; + ftrs += len; } /* loop over bits we know about */ - for (i = 0; i < ARRAY_SIZE(ibm_pa_features); ++i) { - struct ibm_pa_feature *fp = &ibm_pa_features[i]; - - if (fp->pabyte >= pa_ftrs[0]) + for (i = 0; i < ft_size; ++i, ++fp) { + if (fp->pabyte >= ftrs[0]) continue; - bit = (pa_ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1; + bit = (ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1; if (bit ^ fp->invert) { cur_cpu_spec->cpu_features |= fp->cpu_features; cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs; @@ -577,16 +573,59 @@ static void __init check_cpu_pa_features(unsigned long node) } } +static void __init check_cpu_pa_features(unsigned long node) +{ + unsigned char *pa_ftrs; + unsigned long tablelen; + + pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen); + if (pa_ftrs == NULL) + return; + + scan_features(node, pa_ftrs, tablelen, + ibm_pa_features, ARRAY_SIZE(ibm_pa_features)); +} + +static struct feature_property { + const char *name; + u32 min_value; + unsigned long cpu_feature; + unsigned long cpu_user_ftr; +} feature_properties[] __initdata = { +#ifdef CONFIG_ALTIVEC + {"altivec", 0, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC}, + {"ibm,vmx", 1, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC}, +#endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_PPC64 + {"ibm,dfp", 1, 0, PPC_FEATURE_HAS_DFP}, + {"ibm,purr", 1, CPU_FTR_PURR, 0}, + {"ibm,spurr", 1, CPU_FTR_SPURR, 0}, +#endif /* CONFIG_PPC64 */ +}; + +static void __init check_cpu_feature_properties(unsigned long node) +{ + unsigned long i; + struct feature_property *fp = feature_properties; + const u32 *prop; + + for (i = 0; i < ARRAY_SIZE(feature_properties); ++i, ++fp) { + prop = of_get_flat_dt_prop(node, fp->name, NULL); + if (prop && *prop >= fp->min_value) { + cur_cpu_spec->cpu_features |= fp->cpu_feature; + cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftr; + } + } +} + static int __init early_init_dt_scan_cpus(unsigned long node, const char *uname, int depth, void *data) { static int logical_cpuid = 0; char *type = of_get_flat_dt_prop(node, "device_type", NULL); -#ifdef CONFIG_ALTIVEC - u32 *prop; -#endif - u32 *intserv; + const u32 *prop; + const u32 *intserv; int i, nthreads; unsigned long len; int found = 0; @@ -643,24 +682,27 @@ static int __init early_init_dt_scan_cpus(unsigned long node, intserv[i]); boot_cpuid = logical_cpuid; set_hard_smp_processor_id(boot_cpuid, intserv[i]); - } -#ifdef CONFIG_ALTIVEC - /* Check if we have a VMX and eventually update CPU features */ - prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); - if (prop && (*prop) > 0) { - cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; - cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; - } - - /* Same goes for Apple's "altivec" property */ - prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); - if (prop) { - cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; - cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; + /* + * PAPR defines "logical" PVR values for cpus that + * meet various levels of the architecture: + * 0x0f000001 Architecture version 2.04 + * 0x0f000002 Architecture version 2.05 + * If the cpu-version property in the cpu node contains + * such a value, we call identify_cpu again with the + * logical PVR value in order to use the cpu feature + * bits appropriate for the architecture level. + * + * A POWER6 partition in "POWER6 architected" mode + * uses the 0x0f000002 PVR value; in POWER5+ mode + * it uses 0x0f000001. + */ + prop = of_get_flat_dt_prop(node, "cpu-version", NULL); + if (prop && (*prop & 0xff000000) == 0x0f000000) + identify_cpu(0, *prop); } -#endif /* CONFIG_ALTIVEC */ + check_cpu_feature_properties(node); check_cpu_pa_features(node); #ifdef CONFIG_PPC_PSERIES diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 8671eb634a9..396109a537c 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -627,6 +627,7 @@ static void __init early_cmdline_parse(void) /* Option vector 3: processor options supported */ #define OV3_FP 0x80 /* floating point */ #define OV3_VMX 0x40 /* VMX/Altivec */ +#define OV3_DFP 0x20 /* decimal FP */ /* Option vector 5: PAPR/OF options supported */ #define OV5_LPAR 0x80 /* logical partitioning supported */ @@ -668,7 +669,7 @@ static unsigned char ibm_architecture_vec[] = { /* option vector 3: processor options supported */ 3 - 2, /* length */ 0, /* don't ignore, don't halt */ - OV3_FP | OV3_VMX, + OV3_FP | OV3_VMX | OV3_DFP, /* option vector 4: IBM PAPR implementation */ 2 - 2, /* length */ diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 04df53a3c86..61c65d19ef0 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -97,7 +97,7 @@ unsigned long __init early_init(unsigned long dt_ptr) * Identify the CPU type and fix up code sections * that depend on which cpu we have. */ - spec = identify_cpu(offset); + spec = identify_cpu(offset, mfspr(SPRN_PVR)); do_feature_fixups(spec->cpu_features, PTRRELOC(&__start___ftr_fixup), diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index f602a53b1b7..3733de30e84 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -171,7 +171,7 @@ void __init setup_paca(int cpu) void __init early_setup(unsigned long dt_ptr) { /* Identify CPU type */ - identify_cpu(0); + identify_cpu(0, mfspr(SPRN_PVR)); /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ setup_paca(0); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 0f39bdbbf91..1796644ec7d 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -677,7 +677,7 @@ void * __init iSeries_early_setup(void) /* Identify CPU type. This is done again by the common code later * on but calling this function multiple times is fine. */ - identify_cpu(0); + identify_cpu(0, mfspr(SPRN_PVR)); powerpc_firmware_features |= FW_FEATURE_ISERIES; powerpc_firmware_features |= FW_FEATURE_LPAR; diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 27faeca2c7a..3c506af1988 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -313,7 +313,7 @@ early_init(int r3, int r4, int r5) * Identify the CPU type and fix up code sections * that depend on which cpu we have. */ - spec = identify_cpu(offset); + spec = identify_cpu(offset, mfspr(SPRN_PVR)); do_feature_fixups(spec->cpu_features, PTRRELOC(&__start___ftr_fixup), PTRRELOC(&__stop___ftr_fixup)); diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 762d15e4887..d06222a5be5 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -24,6 +24,8 @@ #define PPC_FEATURE_ICACHE_SNOOP 0x00002000 #define PPC_FEATURE_ARCH_2_05 0x00001000 #define PPC_FEATURE_PA6T 0x00000800 +#define PPC_FEATURE_HAS_DFP 0x00000400 +#define PPC_FEATURE_POWER6_EXT 0x00000200 #define PPC_FEATURE_TRUE_LE 0x00000002 #define PPC_FEATURE_PPC_LE 0x00000001 @@ -92,7 +94,7 @@ extern struct cpu_spec *cur_cpu_spec; extern unsigned int __start___ftr_fixup, __stop___ftr_fixup; -extern struct cpu_spec *identify_cpu(unsigned long offset); +extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr); extern void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end); @@ -149,6 +151,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) #define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000) #define CPU_FTR_CELL_TB_BUG LONG_ASM_CONST(0x0000800000000000) +#define CPU_FTR_SPURR LONG_ASM_CONST(0x0001000000000000) #ifndef __ASSEMBLY__ @@ -333,7 +336,13 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ - CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_REAL_LE) + CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE) +#define CPU_FTRS_POWER6X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ + CPU_FTR_MMCRA | CPU_FTR_SMT | \ + CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ + CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | \ + CPU_FTR_SPURR | CPU_FTR_REAL_LE) #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ -- cgit v1.2.3-70-g09d2 From bf1ab978be2318c5a564de9aa0f1a217b44170d4 Mon Sep 17 00:00:00 2001 From: Dwayne Grant McConnell Date: Thu, 23 Nov 2006 00:46:37 +0100 Subject: [POWERPC] coredump: Add SPU elf notes to coredump. This patch adds SPU elf notes to the coredump. It creates a separate note for each of /regs, /fpcr, /lslr, /decr, /decr_status, /mem, /signal1, /signal1_type, /signal2, /signal2_type, /event_mask, /event_status, /mbox_info, /ibox_info, /wbox_info, /dma_info, /proxydma_info, /object-id. A new macro, ARCH_HAVE_EXTRA_NOTES, was created for architectures to specify they have extra elf core notes. A new macro, ELF_CORE_EXTRA_NOTES_SIZE, was created so the size of the additional notes could be calculated and added to the notes phdr entry. A new macro, ELF_CORE_WRITE_EXTRA_NOTES, was created so the new notes would be written after the existing notes. The SPU coredump code resides in spufs. Stub functions are provided in the kernel which are hooked into the spufs code which does the actual work via register_arch_coredump_calls(). A new set of __spufs__read/get() functions was provided to allow the coredump code to read from the spufs files without having to lock the SPU context for each file read from. Cc: Signed-off-by: Dwayne Grant McConnell Signed-off-by: Arnd Bergmann --- arch/powerpc/platforms/cell/Makefile | 1 + arch/powerpc/platforms/cell/spu_coredump.c | 81 +++++++ arch/powerpc/platforms/cell/spufs/Makefile | 2 +- arch/powerpc/platforms/cell/spufs/coredump.c | 238 +++++++++++++++++++ arch/powerpc/platforms/cell/spufs/file.c | 327 ++++++++++++++++++++------- arch/powerpc/platforms/cell/spufs/inode.c | 7 + arch/powerpc/platforms/cell/spufs/spufs.h | 11 + fs/binfmt_elf.c | 8 + include/asm-powerpc/elf.h | 13 ++ include/asm-powerpc/spu.h | 10 + include/linux/elf.h | 7 + 11 files changed, 618 insertions(+), 87 deletions(-) create mode 100644 arch/powerpc/platforms/cell/spu_coredump.c create mode 100644 arch/powerpc/platforms/cell/spufs/coredump.c (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 62c011e8092..f90e8337796 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -15,5 +15,6 @@ spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ + spu_coredump.o \ $(spufs-modular-m) \ $(spu-priv1-y) spufs/ diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c new file mode 100644 index 00000000000..6915b418ee7 --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_coredump.c @@ -0,0 +1,81 @@ +/* + * SPU core dump code + * + * (C) Copyright 2006 IBM Corp. + * + * Author: Dwayne Grant McConnell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include + +static struct spu_coredump_calls spu_coredump_calls; +static DEFINE_MUTEX(spu_coredump_mutex); + +int arch_notes_size(void) +{ + long ret; + struct module *owner = spu_coredump_calls.owner; + + ret = -ENOSYS; + mutex_lock(&spu_coredump_mutex); + if (owner && try_module_get(owner)) { + ret = spu_coredump_calls.arch_notes_size(); + module_put(owner); + } + mutex_unlock(&spu_coredump_mutex); + return ret; +} + +void arch_write_notes(struct file *file) +{ + struct module *owner = spu_coredump_calls.owner; + + mutex_lock(&spu_coredump_mutex); + if (owner && try_module_get(owner)) { + spu_coredump_calls.arch_write_notes(file); + module_put(owner); + } + mutex_unlock(&spu_coredump_mutex); +} + +int register_arch_coredump_calls(struct spu_coredump_calls *calls) +{ + if (spu_coredump_calls.owner) + return -EBUSY; + + mutex_lock(&spu_coredump_mutex); + spu_coredump_calls.arch_notes_size = calls->arch_notes_size; + spu_coredump_calls.arch_write_notes = calls->arch_write_notes; + spu_coredump_calls.owner = calls->owner; + mutex_unlock(&spu_coredump_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(register_arch_coredump_calls); + +void unregister_arch_coredump_calls(struct spu_coredump_calls *calls) +{ + BUG_ON(spu_coredump_calls.owner != calls->owner); + + mutex_lock(&spu_coredump_mutex); + spu_coredump_calls.owner = NULL; + mutex_unlock(&spu_coredump_mutex); +} +EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls); diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index ecdfbb35f82..472217d19fa 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -1,7 +1,7 @@ obj-y += switch.o obj-$(CONFIG_SPU_FS) += spufs.o -spufs-y += inode.o file.o context.o syscalls.o +spufs-y += inode.o file.o context.o syscalls.o coredump.o spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o # Rules to build switch.o with the help of SPU tool chain diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c new file mode 100644 index 00000000000..26945c491f6 --- /dev/null +++ b/arch/powerpc/platforms/cell/spufs/coredump.c @@ -0,0 +1,238 @@ +/* + * SPU core dump code + * + * (C) Copyright 2006 IBM Corp. + * + * Author: Dwayne Grant McConnell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "spufs.h" + +struct spufs_ctx_info { + struct list_head list; + int dfd; + int memsize; /* in bytes */ + struct spu_context *ctx; +}; + +static LIST_HEAD(ctx_info_list); + +static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer, + size_t size, loff_t *off) +{ + u64 data; + int ret; + + if (spufs_coredump_read[num].read) + return spufs_coredump_read[num].read(ctx, buffer, size, off); + + data = spufs_coredump_read[num].get(ctx); + ret = copy_to_user(buffer, &data, 8); + return ret ? -EFAULT : 8; +} + +/* + * These are the only things you should do on a core-file: use only these + * functions to write out all the necessary info. + */ +static int spufs_dump_write(struct file *file, const void *addr, int nr) +{ + return file->f_op->write(file, addr, nr, &file->f_pos) == nr; +} + +static int spufs_dump_seek(struct file *file, loff_t off) +{ + if (file->f_op->llseek) { + if (file->f_op->llseek(file, off, 0) != off) + return 0; + } else + file->f_pos = off; + return 1; +} + +static void spufs_fill_memsize(struct spufs_ctx_info *ctx_info) +{ + struct spu_context *ctx; + unsigned long long lslr; + + ctx = ctx_info->ctx; + lslr = ctx->csa.priv2.spu_lslr_RW; + ctx_info->memsize = lslr + 1; +} + +static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info) +{ + int dfd, memsize, i, sz, total = 0; + char *name; + char fullname[80]; + + dfd = ctx_info->dfd; + memsize = ctx_info->memsize; + + for (i = 0; spufs_coredump_read[i].name; i++) { + name = spufs_coredump_read[i].name; + sz = spufs_coredump_read[i].size; + + sprintf(fullname, "SPU/%d/%s", dfd, name); + + total += sizeof(struct elf_note); + total += roundup(strlen(fullname) + 1, 4); + if (!strcmp(name, "mem")) + total += roundup(memsize, 4); + else + total += roundup(sz, 4); + } + + return total; +} + +static int spufs_add_one_context(struct file *file, int dfd) +{ + struct spu_context *ctx; + struct spufs_ctx_info *ctx_info; + int size; + + ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx; + if (ctx->flags & SPU_CREATE_NOSCHED) + return 0; + + ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL); + if (unlikely(!ctx_info)) + return -ENOMEM; + + ctx_info->dfd = dfd; + ctx_info->ctx = ctx; + + spufs_fill_memsize(ctx_info); + + size = spufs_ctx_note_size(ctx_info); + list_add(&ctx_info->list, &ctx_info_list); + return size; +} + +/* + * The additional architecture-specific notes for Cell are various + * context files in the spu context. + * + * This function iterates over all open file descriptors and sees + * if they are a directory in spufs. In that case we use spufs + * internal functionality to dump them without needing to actually + * open the files. + */ +static int spufs_arch_notes_size(void) +{ + struct fdtable *fdt = files_fdtable(current->files); + int size = 0, fd; + + for (fd = 0; fd < fdt->max_fdset && fd < fdt->max_fds; fd++) { + if (FD_ISSET(fd, fdt->open_fds)) { + struct file *file = fcheck(fd); + + if (file && file->f_op == &spufs_context_fops) { + int rval = spufs_add_one_context(file, fd); + if (rval < 0) + break; + size += rval; + } + } + } + + return size; +} + +static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, + struct file *file) +{ + struct spu_context *ctx; + loff_t pos = 0; + int sz, dfd, rc, total = 0; + const int bufsz = 4096; + char *name; + char fullname[80], *buf; + struct elf_note en; + + buf = kmalloc(bufsz, GFP_KERNEL); + if (!buf) + return; + + dfd = ctx_info->dfd; + name = spufs_coredump_read[i].name; + + if (!strcmp(name, "mem")) + sz = ctx_info->memsize; + else + sz = spufs_coredump_read[i].size; + + ctx = ctx_info->ctx; + if (!ctx) { + return; + } + + sprintf(fullname, "SPU/%d/%s", dfd, name); + en.n_namesz = strlen(fullname) + 1; + en.n_descsz = sz; + en.n_type = NT_SPU; + + if (!spufs_dump_write(file, &en, sizeof(en))) + return; + if (!spufs_dump_write(file, fullname, en.n_namesz)) + return; + if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4))) + return; + + do { + rc = do_coredump_read(i, ctx, buf, bufsz, &pos); + if (rc > 0) { + if (!spufs_dump_write(file, buf, rc)) + return; + total += rc; + } + } while (rc == bufsz && total < sz); + + spufs_dump_seek(file, roundup((unsigned long)file->f_pos + - total + sz, 4)); +} + +static void spufs_arch_write_notes(struct file *file) +{ + int j; + struct spufs_ctx_info *ctx_info, *next; + + list_for_each_entry_safe(ctx_info, next, &ctx_info_list, list) { + spu_acquire_saved(ctx_info->ctx); + for (j = 0; j < spufs_coredump_num_notes; j++) + spufs_arch_write_note(ctx_info, j, file); + spu_release(ctx_info->ctx); + list_del(&ctx_info->list); + kfree(ctx_info); + } +} + +struct spu_coredump_calls spufs_coredump_calls = { + .arch_notes_size = spufs_arch_notes_size, + .arch_write_notes = spufs_arch_write_notes, + .owner = THIS_MODULE, +}; diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 50e0afc46ad..347eff56fcb 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -39,7 +39,6 @@ #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) - static int spufs_mem_open(struct inode *inode, struct file *file) { @@ -51,19 +50,24 @@ spufs_mem_open(struct inode *inode, struct file *file) return 0; } +static ssize_t +__spufs_mem_read(struct spu_context *ctx, char __user *buffer, + size_t size, loff_t *pos) +{ + char *local_store = ctx->ops->get_ls(ctx); + return simple_read_from_buffer(buffer, size, pos, local_store, + LS_SIZE); +} + static ssize_t spufs_mem_read(struct file *file, char __user *buffer, size_t size, loff_t *pos) { - struct spu_context *ctx = file->private_data; - char *local_store; int ret; + struct spu_context *ctx = file->private_data; spu_acquire(ctx); - - local_store = ctx->ops->get_ls(ctx); - ret = simple_read_from_buffer(buffer, size, pos, local_store, LS_SIZE); - + ret = __spufs_mem_read(ctx, buffer, size, pos); spu_release(ctx); return ret; } @@ -261,19 +265,24 @@ spufs_regs_open(struct inode *inode, struct file *file) return 0; } +static ssize_t +__spufs_regs_read(struct spu_context *ctx, char __user *buffer, + size_t size, loff_t *pos) +{ + struct spu_lscsa *lscsa = ctx->csa.lscsa; + return simple_read_from_buffer(buffer, size, pos, + lscsa->gprs, sizeof lscsa->gprs); +} + static ssize_t spufs_regs_read(struct file *file, char __user *buffer, size_t size, loff_t *pos) { - struct spu_context *ctx = file->private_data; - struct spu_lscsa *lscsa = ctx->csa.lscsa; int ret; + struct spu_context *ctx = file->private_data; spu_acquire_saved(ctx); - - ret = simple_read_from_buffer(buffer, size, pos, - lscsa->gprs, sizeof lscsa->gprs); - + ret = __spufs_regs_read(ctx, buffer, size, pos); spu_release(ctx); return ret; } @@ -307,19 +316,24 @@ static struct file_operations spufs_regs_fops = { .llseek = generic_file_llseek, }; +static ssize_t +__spufs_fpcr_read(struct spu_context *ctx, char __user * buffer, + size_t size, loff_t * pos) +{ + struct spu_lscsa *lscsa = ctx->csa.lscsa; + return simple_read_from_buffer(buffer, size, pos, + &lscsa->fpcr, sizeof(lscsa->fpcr)); +} + static ssize_t spufs_fpcr_read(struct file *file, char __user * buffer, size_t size, loff_t * pos) { - struct spu_context *ctx = file->private_data; - struct spu_lscsa *lscsa = ctx->csa.lscsa; int ret; + struct spu_context *ctx = file->private_data; spu_acquire_saved(ctx); - - ret = simple_read_from_buffer(buffer, size, pos, - &lscsa->fpcr, sizeof(lscsa->fpcr)); - + ret = __spufs_fpcr_read(ctx, buffer, size, pos); spu_release(ctx); return ret; } @@ -719,22 +733,19 @@ static int spufs_signal1_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); } -static ssize_t spufs_signal1_read(struct file *file, char __user *buf, +static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf, size_t len, loff_t *pos) { - struct spu_context *ctx = file->private_data; int ret = 0; u32 data; if (len < 4) return -EINVAL; - spu_acquire_saved(ctx); if (ctx->csa.spu_chnlcnt_RW[3]) { data = ctx->csa.spu_chnldata_RW[3]; ret = 4; } - spu_release(ctx); if (!ret) goto out; @@ -746,6 +757,19 @@ out: return ret; } +static ssize_t spufs_signal1_read(struct file *file, char __user *buf, + size_t len, loff_t *pos) +{ + int ret; + struct spu_context *ctx = file->private_data; + + spu_acquire_saved(ctx); + ret = __spufs_signal1_read(ctx, buf, len, pos); + spu_release(ctx); + + return ret; +} + static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, size_t len, loff_t *pos) { @@ -816,22 +840,19 @@ static int spufs_signal2_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); } -static ssize_t spufs_signal2_read(struct file *file, char __user *buf, +static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf, size_t len, loff_t *pos) { - struct spu_context *ctx = file->private_data; int ret = 0; u32 data; if (len < 4) return -EINVAL; - spu_acquire_saved(ctx); if (ctx->csa.spu_chnlcnt_RW[4]) { data = ctx->csa.spu_chnldata_RW[4]; ret = 4; } - spu_release(ctx); if (!ret) goto out; @@ -840,7 +861,20 @@ static ssize_t spufs_signal2_read(struct file *file, char __user *buf, return -EFAULT; out: - return 4; + return ret; +} + +static ssize_t spufs_signal2_read(struct file *file, char __user *buf, + size_t len, loff_t *pos) +{ + struct spu_context *ctx = file->private_data; + int ret; + + spu_acquire_saved(ctx); + ret = __spufs_signal2_read(ctx, buf, len, pos); + spu_release(ctx); + + return ret; } static ssize_t spufs_signal2_write(struct file *file, const char __user *buf, @@ -916,13 +950,19 @@ static void spufs_signal1_type_set(void *data, u64 val) spu_release(ctx); } +static u64 __spufs_signal1_type_get(void *data) +{ + struct spu_context *ctx = data; + return ctx->ops->signal1_type_get(ctx); +} + static u64 spufs_signal1_type_get(void *data) { struct spu_context *ctx = data; u64 ret; spu_acquire(ctx); - ret = ctx->ops->signal1_type_get(ctx); + ret = __spufs_signal1_type_get(data); spu_release(ctx); return ret; @@ -939,13 +979,19 @@ static void spufs_signal2_type_set(void *data, u64 val) spu_release(ctx); } +static u64 __spufs_signal2_type_get(void *data) +{ + struct spu_context *ctx = data; + return ctx->ops->signal2_type_get(ctx); +} + static u64 spufs_signal2_type_get(void *data) { struct spu_context *ctx = data; u64 ret; spu_acquire(ctx); - ret = ctx->ops->signal2_type_get(ctx); + ret = __spufs_signal2_type_get(data); spu_release(ctx); return ret; @@ -1387,13 +1433,19 @@ static void spufs_decr_set(void *data, u64 val) spu_release(ctx); } -static u64 spufs_decr_get(void *data) +static u64 __spufs_decr_get(void *data) { struct spu_context *ctx = data; struct spu_lscsa *lscsa = ctx->csa.lscsa; + return lscsa->decr.slot[0]; +} + +static u64 spufs_decr_get(void *data) +{ + struct spu_context *ctx = data; u64 ret; spu_acquire_saved(ctx); - ret = lscsa->decr.slot[0]; + ret = __spufs_decr_get(data); spu_release(ctx); return ret; } @@ -1409,13 +1461,19 @@ static void spufs_decr_status_set(void *data, u64 val) spu_release(ctx); } -static u64 spufs_decr_status_get(void *data) +static u64 __spufs_decr_status_get(void *data) { struct spu_context *ctx = data; struct spu_lscsa *lscsa = ctx->csa.lscsa; + return lscsa->decr_status.slot[0]; +} + +static u64 spufs_decr_status_get(void *data) +{ + struct spu_context *ctx = data; u64 ret; spu_acquire_saved(ctx); - ret = lscsa->decr_status.slot[0]; + ret = __spufs_decr_status_get(data); spu_release(ctx); return ret; } @@ -1431,30 +1489,43 @@ static void spufs_event_mask_set(void *data, u64 val) spu_release(ctx); } -static u64 spufs_event_mask_get(void *data) +static u64 __spufs_event_mask_get(void *data) { struct spu_context *ctx = data; struct spu_lscsa *lscsa = ctx->csa.lscsa; + return lscsa->event_mask.slot[0]; +} + +static u64 spufs_event_mask_get(void *data) +{ + struct spu_context *ctx = data; u64 ret; spu_acquire_saved(ctx); - ret = lscsa->event_mask.slot[0]; + ret = __spufs_event_mask_get(data); spu_release(ctx); return ret; } DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, spufs_event_mask_set, "0x%llx\n") -static u64 spufs_event_status_get(void *data) +static u64 __spufs_event_status_get(void *data) { struct spu_context *ctx = data; struct spu_state *state = &ctx->csa; - u64 ret = 0; u64 stat; - - spu_acquire_saved(ctx); stat = state->spu_chnlcnt_RW[0]; if (stat) - ret = state->spu_chnldata_RW[0]; + return state->spu_chnldata_RW[0]; + return 0; +} + +static u64 spufs_event_status_get(void *data) +{ + struct spu_context *ctx = data; + u64 ret = 0; + + spu_acquire_saved(ctx); + ret = __spufs_event_status_get(data); spu_release(ctx); return ret; } @@ -1499,12 +1570,18 @@ static u64 spufs_id_get(void *data) } DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n") -static u64 spufs_object_id_get(void *data) +static u64 __spufs_object_id_get(void *data) { struct spu_context *ctx = data; return ctx->object_id; } +static u64 spufs_object_id_get(void *data) +{ + /* FIXME: Should there really be no locking here? */ + return __spufs_object_id_get(data); +} + static void spufs_object_id_set(void *data, u64 id) { struct spu_context *ctx = data; @@ -1514,13 +1591,19 @@ static void spufs_object_id_set(void *data, u64 id) DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, spufs_object_id_set, "0x%llx\n"); +static u64 __spufs_lslr_get(void *data) +{ + struct spu_context *ctx = data; + return ctx->csa.priv2.spu_lslr_RW; +} + static u64 spufs_lslr_get(void *data) { struct spu_context *ctx = data; u64 ret; spu_acquire_saved(ctx); - ret = ctx->csa.priv2.spu_lslr_RW; + ret = __spufs_lslr_get(data); spu_release(ctx); return ret; @@ -1535,26 +1618,36 @@ static int spufs_info_open(struct inode *inode, struct file *file) return 0; } +static ssize_t __spufs_mbox_info_read(struct spu_context *ctx, + char __user *buf, size_t len, loff_t *pos) +{ + u32 mbox_stat; + u32 data; + + mbox_stat = ctx->csa.prob.mb_stat_R; + if (mbox_stat & 0x0000ff) { + data = ctx->csa.prob.pu_mb_R; + } + + return simple_read_from_buffer(buf, len, pos, &data, sizeof data); +} + static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf, size_t len, loff_t *pos) { + int ret; struct spu_context *ctx = file->private_data; - u32 mbox_stat; - u32 data; if (!access_ok(VERIFY_WRITE, buf, len)) return -EFAULT; spu_acquire_saved(ctx); spin_lock(&ctx->csa.register_lock); - mbox_stat = ctx->csa.prob.mb_stat_R; - if (mbox_stat & 0x0000ff) { - data = ctx->csa.prob.pu_mb_R; - } + ret = __spufs_mbox_info_read(ctx, buf, len, pos); spin_unlock(&ctx->csa.register_lock); spu_release(ctx); - return simple_read_from_buffer(buf, len, pos, &data, sizeof data); + return ret; } static struct file_operations spufs_mbox_info_fops = { @@ -1563,26 +1656,36 @@ static struct file_operations spufs_mbox_info_fops = { .llseek = generic_file_llseek, }; +static ssize_t __spufs_ibox_info_read(struct spu_context *ctx, + char __user *buf, size_t len, loff_t *pos) +{ + u32 ibox_stat; + u32 data; + + ibox_stat = ctx->csa.prob.mb_stat_R; + if (ibox_stat & 0xff0000) { + data = ctx->csa.priv2.puint_mb_R; + } + + return simple_read_from_buffer(buf, len, pos, &data, sizeof data); +} + static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf, size_t len, loff_t *pos) { struct spu_context *ctx = file->private_data; - u32 ibox_stat; - u32 data; + int ret; if (!access_ok(VERIFY_WRITE, buf, len)) return -EFAULT; spu_acquire_saved(ctx); spin_lock(&ctx->csa.register_lock); - ibox_stat = ctx->csa.prob.mb_stat_R; - if (ibox_stat & 0xff0000) { - data = ctx->csa.priv2.puint_mb_R; - } + ret = __spufs_ibox_info_read(ctx, buf, len, pos); spin_unlock(&ctx->csa.register_lock); spu_release(ctx); - return simple_read_from_buffer(buf, len, pos, &data, sizeof data); + return ret; } static struct file_operations spufs_ibox_info_fops = { @@ -1591,29 +1694,39 @@ static struct file_operations spufs_ibox_info_fops = { .llseek = generic_file_llseek, }; -static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf, - size_t len, loff_t *pos) +static ssize_t __spufs_wbox_info_read(struct spu_context *ctx, + char __user *buf, size_t len, loff_t *pos) { - struct spu_context *ctx = file->private_data; int i, cnt; u32 data[4]; u32 wbox_stat; + wbox_stat = ctx->csa.prob.mb_stat_R; + cnt = 4 - ((wbox_stat & 0x00ff00) >> 8); + for (i = 0; i < cnt; i++) { + data[i] = ctx->csa.spu_mailbox_data[i]; + } + + return simple_read_from_buffer(buf, len, pos, &data, + cnt * sizeof(u32)); +} + +static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf, + size_t len, loff_t *pos) +{ + struct spu_context *ctx = file->private_data; + int ret; + if (!access_ok(VERIFY_WRITE, buf, len)) return -EFAULT; spu_acquire_saved(ctx); spin_lock(&ctx->csa.register_lock); - wbox_stat = ctx->csa.prob.mb_stat_R; - cnt = (wbox_stat & 0x00ff00) >> 8; - for (i = 0; i < cnt; i++) { - data[i] = ctx->csa.spu_mailbox_data[i]; - } + ret = __spufs_wbox_info_read(ctx, buf, len, pos); spin_unlock(&ctx->csa.register_lock); spu_release(ctx); - return simple_read_from_buffer(buf, len, pos, &data, - cnt * sizeof(u32)); + return ret; } static struct file_operations spufs_wbox_info_fops = { @@ -1622,19 +1735,13 @@ static struct file_operations spufs_wbox_info_fops = { .llseek = generic_file_llseek, }; -static ssize_t spufs_dma_info_read(struct file *file, char __user *buf, - size_t len, loff_t *pos) +static ssize_t __spufs_dma_info_read(struct spu_context *ctx, + char __user *buf, size_t len, loff_t *pos) { - struct spu_context *ctx = file->private_data; struct spu_dma_info info; struct mfc_cq_sr *qp, *spuqp; int i; - if (!access_ok(VERIFY_WRITE, buf, len)) - return -EFAULT; - - spu_acquire_saved(ctx); - spin_lock(&ctx->csa.register_lock); info.dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW; info.dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0]; info.dma_info_status = ctx->csa.spu_chnldata_RW[24]; @@ -1649,25 +1756,40 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf, qp->mfc_cq_data2_RW = spuqp->mfc_cq_data2_RW; qp->mfc_cq_data3_RW = spuqp->mfc_cq_data3_RW; } - spin_unlock(&ctx->csa.register_lock); - spu_release(ctx); return simple_read_from_buffer(buf, len, pos, &info, sizeof info); } +static ssize_t spufs_dma_info_read(struct file *file, char __user *buf, + size_t len, loff_t *pos) +{ + struct spu_context *ctx = file->private_data; + int ret; + + if (!access_ok(VERIFY_WRITE, buf, len)) + return -EFAULT; + + spu_acquire_saved(ctx); + spin_lock(&ctx->csa.register_lock); + ret = __spufs_dma_info_read(ctx, buf, len, pos); + spin_unlock(&ctx->csa.register_lock); + spu_release(ctx); + + return ret; +} + static struct file_operations spufs_dma_info_fops = { .open = spufs_info_open, .read = spufs_dma_info_read, }; -static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf, - size_t len, loff_t *pos) +static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx, + char __user *buf, size_t len, loff_t *pos) { - struct spu_context *ctx = file->private_data; struct spu_proxydma_info info; - int ret = sizeof info; struct mfc_cq_sr *qp, *puqp; + int ret = sizeof info; int i; if (len < ret) @@ -1676,8 +1798,6 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf, if (!access_ok(VERIFY_WRITE, buf, len)) return -EFAULT; - spu_acquire_saved(ctx); - spin_lock(&ctx->csa.register_lock); info.proxydma_info_type = ctx->csa.prob.dma_querytype_RW; info.proxydma_info_mask = ctx->csa.prob.dma_querymask_RW; info.proxydma_info_status = ctx->csa.prob.dma_tagstatus_R; @@ -1690,12 +1810,23 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf, qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW; qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW; } + + return simple_read_from_buffer(buf, len, pos, &info, + sizeof info); +} + +static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf, + size_t len, loff_t *pos) +{ + struct spu_context *ctx = file->private_data; + int ret; + + spu_acquire_saved(ctx); + spin_lock(&ctx->csa.register_lock); + ret = __spufs_proxydma_info_read(ctx, buf, len, pos); spin_unlock(&ctx->csa.register_lock); spu_release(ctx); - if (copy_to_user(buf, &info, sizeof info)) - ret = -EFAULT; - return ret; } @@ -1760,3 +1891,27 @@ struct tree_descr spufs_dir_nosched_contents[] = { { "object-id", &spufs_object_id_ops, 0666, }, {}, }; + +struct spufs_coredump_reader spufs_coredump_read[] = { + { "regs", __spufs_regs_read, NULL, 128 * 16 }, + { "fpcr", __spufs_fpcr_read, NULL, 16 }, + { "lslr", NULL, __spufs_lslr_get, 11 }, + { "decr", NULL, __spufs_decr_get, 11 }, + { "decr_status", NULL, __spufs_decr_status_get, 11 }, + { "mem", __spufs_mem_read, NULL, 256 * 1024, }, + { "signal1", __spufs_signal1_read, NULL, 4 }, + { "signal1_type", NULL, __spufs_signal1_type_get, 2 }, + { "signal2", __spufs_signal2_read, NULL, 4 }, + { "signal2_type", NULL, __spufs_signal2_type_get, 2 }, + { "event_mask", NULL, __spufs_event_mask_get, 8 }, + { "event_status", NULL, __spufs_event_status_get, 8 }, + { "mbox_info", __spufs_mbox_info_read, NULL, 4 }, + { "ibox_info", __spufs_ibox_info_read, NULL, 4 }, + { "wbox_info", __spufs_wbox_info_read, NULL, 16 }, + { "dma_info", __spufs_dma_info_read, NULL, 69 * 8 }, + { "proxydma_info", __spufs_proxydma_info_read, NULL, 35 * 8 }, + { "object-id", NULL, __spufs_object_id_get, 19 }, + { }, +}; +int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read) - 1; + diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index d5f0a21a19d..a3ca06bd0ca 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -232,6 +232,7 @@ struct file_operations spufs_context_fops = { .readdir = dcache_readdir, .fsync = simple_sync_file, }; +EXPORT_SYMBOL_GPL(spufs_context_fops); static int spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, @@ -647,6 +648,7 @@ static struct file_system_type spufs_type = { static int __init spufs_init(void) { int ret; + ret = -ENOMEM; spufs_inode_cache = kmem_cache_create("spufs_inode_cache", sizeof(struct spufs_inode_info), 0, @@ -662,10 +664,14 @@ static int __init spufs_init(void) if (ret) goto out_cache; ret = register_spu_syscalls(&spufs_calls); + if (ret) + goto out_fs; + ret = register_arch_coredump_calls(&spufs_coredump_calls); if (ret) goto out_fs; spufs_init_isolated_loader(); + return 0; out_fs: unregister_filesystem(&spufs_type); @@ -679,6 +685,7 @@ module_init(spufs_init); static void __exit spufs_exit(void) { spu_sched_exit(); + unregister_arch_coredump_calls(&spufs_coredump_calls); unregister_spu_syscalls(&spufs_calls); unregister_filesystem(&spufs_type); kmem_cache_destroy(spufs_inode_cache); diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 23d20f38056..70fb13395c0 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -223,4 +223,15 @@ void spufs_stop_callback(struct spu *spu); void spufs_mfc_callback(struct spu *spu); void spufs_dma_callback(struct spu *spu, int type); +extern struct spu_coredump_calls spufs_coredump_calls; +struct spufs_coredump_reader { + char *name; + ssize_t (*read)(struct spu_context *ctx, + char __user *buffer, size_t size, loff_t *pos); + u64 (*get)(void *data); + size_t size; +}; +extern struct spufs_coredump_reader spufs_coredump_read[]; +extern int spufs_coredump_num_notes; + #endif diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 79b05a1a436..cc72bb43061 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1582,6 +1582,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) sz += thread_status_size; +#ifdef ELF_CORE_WRITE_EXTRA_NOTES + sz += ELF_CORE_EXTRA_NOTES_SIZE; +#endif + fill_elf_note_phdr(&phdr, sz, offset); offset += sz; DUMP_WRITE(&phdr, sizeof(phdr)); @@ -1622,6 +1626,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) if (!writenote(notes + i, file, &foffset)) goto end_coredump; +#ifdef ELF_CORE_WRITE_EXTRA_NOTES + ELF_CORE_WRITE_EXTRA_NOTES; +#endif + /* write out the thread status notes section */ list_for_each(t, &thread_list) { struct elf_thread_status *tmp = diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index 9a83a987d39..4545aa68250 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -411,4 +411,17 @@ do { \ /* Keep this the last entry. */ #define R_PPC64_NUM 107 +#ifdef CONFIG_PPC_CELL +/* Notes used in ET_CORE. Note name is "SPU//". */ +#define NT_SPU 1 + +extern int arch_notes_size(void); +extern void arch_write_notes(struct file *file); + +#define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size() +#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file) + +#define ARCH_HAVE_EXTRA_ELF_NOTES +#endif /* CONFIG_PPC_CELL */ + #endif /* _ASM_POWERPC_ELF_H */ diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index ffa4df08360..f968f869753 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -172,6 +172,13 @@ extern struct spufs_calls { struct module *owner; } spufs_calls; +/* coredump calls implemented in spufs */ +struct spu_coredump_calls { + asmlinkage int (*arch_notes_size)(void); + asmlinkage void (*arch_write_notes)(struct file *file); + struct module *owner; +}; + /* return status from spu_run, same as in libspe */ #define SPE_EVENT_DMA_ALIGNMENT 0x0008 /*A DMA alignment error */ #define SPE_EVENT_SPE_ERROR 0x0010 /*An illegal instruction error*/ @@ -203,6 +210,9 @@ static inline void unregister_spu_syscalls(struct spufs_calls *calls) } #endif /* MODULE */ +int register_arch_coredump_calls(struct spu_coredump_calls *calls); +void unregister_arch_coredump_calls(struct spu_coredump_calls *calls); + int spu_add_sysdev_attr(struct sysdev_attribute *attr); void spu_remove_sysdev_attr(struct sysdev_attribute *attr); diff --git a/include/linux/elf.h b/include/linux/elf.h index b70d1d2c8d2..743d5c8e6d3 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -368,5 +368,12 @@ extern Elf64_Dyn _DYNAMIC []; #endif +#ifndef ARCH_HAVE_EXTRA_ELF_NOTES +static inline int arch_notes_size(void) { return 0; } +static inline void arch_write_notes(struct file *file) { } + +#define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size() +#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file) +#endif /* ARCH_HAVE_EXTRA_ELF_NOTES */ #endif /* _LINUX_ELF_H */ -- cgit v1.2.3-70-g09d2 From 0b8e2e131094d162a836e2afe86e52acbfa05703 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 23 Nov 2006 00:46:46 +0100 Subject: [POWERPC] Make 64-bit cpu features defined on 32-bit It saves #ifdef'ing in callers if we at least define the 64-bit cpu features for 32-bit also. Signed-off-by: Michael Ellerman Signed-off-by: Arnd Bergmann --- include/asm-powerpc/cputable.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index d06222a5be5..354f66da9dc 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -315,7 +315,8 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTRS_E500_2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN) #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) -#ifdef __powerpc64__ + +/* 64-bit CPUs */ #define CPU_FTRS_POWER3 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE) #define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ @@ -353,7 +354,6 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, CPU_FTR_PURR | CPU_FTR_REAL_LE) #define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2) -#endif #ifdef __powerpc64__ #define CPU_FTRS_POSSIBLE \ -- cgit v1.2.3-70-g09d2 From e34226d2cd443a67f46fc531e3a6bc6e03843ce2 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 23 Nov 2006 00:46:48 +0100 Subject: [POWERPC] add virq_to_hw accessor routine This adds an accessor routine virq_to_hw() to the virq routines which hides the implementation details of the virq to hwirq map. Acked-by: Benjamin Herrenschmidt Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann --- include/asm-powerpc/irq.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index f960f5346f4..46476e9a494 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h @@ -135,6 +135,10 @@ struct irq_map_entry { extern struct irq_map_entry irq_map[NR_IRQS]; +static inline irq_hw_number_t virq_to_hw(unsigned int virq) +{ + return irq_map[virq].hwirq; +} /** * irq_alloc_host - Allocate a new irq_host data structure -- cgit v1.2.3-70-g09d2 From e28b003136b5b2f10c25b49c32df9b7742550c23 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 23 Nov 2006 00:46:49 +0100 Subject: [POWERPC] cell: abstract spu management routines This adds a platform specific spu management abstraction and the coresponding routines to support the IBM Cell Blade. It also removes the hypervisor only resources that were included in struct spu. Three new platform specific routines are introduced, spu_enumerate_spus(), spu_create_spu() and spu_destroy_spu(). The underlying design uses a new type, struct spu_management_ops, to hold function pointers that the platform setup code is expected to initialize to instances appropriate to that platform. For the IBM Cell Blade support, I put the hypervisor only resources that were in struct spu into a platform specific data structure struct spu_pdata. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann --- arch/powerpc/platforms/cell/cbe_thermal.c | 5 +- arch/powerpc/platforms/cell/setup.c | 3 +- arch/powerpc/platforms/cell/spu_base.c | 334 ++------------------- arch/powerpc/platforms/cell/spu_priv1_mmio.c | 424 +++++++++++++++++++++++++-- arch/powerpc/platforms/cell/spu_priv1_mmio.h | 26 ++ include/asm-powerpc/spu.h | 5 +- include/asm-powerpc/spu_priv1.h | 40 ++- 7 files changed, 490 insertions(+), 347 deletions(-) create mode 100644 arch/powerpc/platforms/cell/spu_priv1_mmio.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c index 17831a92d91..616a0a3fd0e 100644 --- a/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/arch/powerpc/platforms/cell/cbe_thermal.c @@ -29,6 +29,7 @@ #include #include "cbe_regs.h" +#include "spu_priv1_mmio.h" static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) { @@ -36,7 +37,7 @@ static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) spu = container_of(sysdev, struct spu, sysdev); - return cbe_get_pmd_regs(spu->devnode); + return cbe_get_pmd_regs(spu_devnode(spu)); } /* returns the value for a given spu in a given register */ @@ -49,7 +50,7 @@ static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iom /* getting the id from the reg attribute will not work on future device-tree layouts * in future we should store the id to the spu struct and use it here */ spu = container_of(sysdev, struct spu, sysdev); - id = (unsigned int *)get_property(spu->devnode, "reg", NULL); + id = (unsigned int *)get_property(spu_devnode(spu), "reg", NULL); value.val = in_be64(®->val); return value.spe[*id]; diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 83d5d0c2faf..36989c2eee6 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -145,7 +145,8 @@ static void __init cell_init_irq(void) static void __init cell_setup_arch(void) { #ifdef CONFIG_SPU_BASE - spu_priv1_ops = &spu_priv1_mmio_ops; + spu_priv1_ops = &spu_priv1_mmio_ops; + spu_management_ops = &spu_management_of_ops; #endif cbe_regs_init(); diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d4f4f396288..841ed359802 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -25,23 +25,17 @@ #include #include #include -#include -#include #include #include #include - -#include -#include -#include +#include +#include #include #include #include -#include #include -#include "interrupt.h" - +const struct spu_management_ops *spu_management_ops; const struct spu_priv1_ops *spu_priv1_ops; EXPORT_SYMBOL_GPL(spu_priv1_ops); @@ -512,261 +506,6 @@ int spu_irq_class_1_bottom(struct spu *spu) return ret; } -static int __init find_spu_node_id(struct device_node *spe) -{ - const unsigned int *id; - struct device_node *cpu; - cpu = spe->parent->parent; - id = get_property(cpu, "node-id", NULL); - return id ? *id : 0; -} - -static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe, - const char *prop) -{ - static DEFINE_MUTEX(add_spumem_mutex); - - const struct address_prop { - unsigned long address; - unsigned int len; - } __attribute__((packed)) *p; - int proplen; - - unsigned long start_pfn, nr_pages; - struct pglist_data *pgdata; - struct zone *zone; - int ret; - - p = get_property(spe, prop, &proplen); - WARN_ON(proplen != sizeof (*p)); - - start_pfn = p->address >> PAGE_SHIFT; - nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT; - - pgdata = NODE_DATA(spu->nid); - zone = pgdata->node_zones; - - /* XXX rethink locking here */ - mutex_lock(&add_spumem_mutex); - ret = __add_pages(zone, start_pfn, nr_pages); - mutex_unlock(&add_spumem_mutex); - - return ret; -} - -static void __iomem * __init map_spe_prop(struct spu *spu, - struct device_node *n, const char *name) -{ - const struct address_prop { - unsigned long address; - unsigned int len; - } __attribute__((packed)) *prop; - - const void *p; - int proplen; - void __iomem *ret = NULL; - int err = 0; - - p = get_property(n, name, &proplen); - if (proplen != sizeof (struct address_prop)) - return NULL; - - prop = p; - - err = cell_spuprop_present(spu, n, name); - if (err && (err != -EEXIST)) - goto out; - - ret = ioremap(prop->address, prop->len); - - out: - return ret; -} - -static void spu_unmap(struct spu *spu) -{ - iounmap(spu->priv2); - iounmap(spu->priv1); - iounmap(spu->problem); - iounmap((__force u8 __iomem *)spu->local_store); -} - -/* This function shall be abstracted for HV platforms */ -static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np) -{ - unsigned int isrc; - const u32 *tmp; - - /* Get the interrupt source unit from the device-tree */ - tmp = get_property(np, "isrc", NULL); - if (!tmp) - return -ENODEV; - isrc = tmp[0]; - - /* Add the node number */ - isrc |= spu->node << IIC_IRQ_NODE_SHIFT; - - /* Now map interrupts of all 3 classes */ - spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc); - spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc); - spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc); - - /* Right now, we only fail if class 2 failed */ - return spu->irqs[2] == NO_IRQ ? -EINVAL : 0; -} - -static int __init spu_map_device_old(struct spu *spu, struct device_node *node) -{ - const char *prop; - int ret; - - ret = -ENODEV; - spu->name = get_property(node, "name", NULL); - if (!spu->name) - goto out; - - prop = get_property(node, "local-store", NULL); - if (!prop) - goto out; - spu->local_store_phys = *(unsigned long *)prop; - - /* we use local store as ram, not io memory */ - spu->local_store = (void __force *) - map_spe_prop(spu, node, "local-store"); - if (!spu->local_store) - goto out; - - prop = get_property(node, "problem", NULL); - if (!prop) - goto out_unmap; - spu->problem_phys = *(unsigned long *)prop; - - spu->problem= map_spe_prop(spu, node, "problem"); - if (!spu->problem) - goto out_unmap; - - spu->priv1= map_spe_prop(spu, node, "priv1"); - /* priv1 is not available on a hypervisor */ - - spu->priv2= map_spe_prop(spu, node, "priv2"); - if (!spu->priv2) - goto out_unmap; - ret = 0; - goto out; - -out_unmap: - spu_unmap(spu); -out: - return ret; -} - -static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) -{ - struct of_irq oirq; - int ret; - int i; - - for (i=0; i < 3; i++) { - ret = of_irq_map_one(np, i, &oirq); - if (ret) { - pr_debug("spu_new: failed to get irq %d\n", i); - goto err; - } - ret = -EINVAL; - pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0], - oirq.controller->full_name); - spu->irqs[i] = irq_create_of_mapping(oirq.controller, - oirq.specifier, oirq.size); - if (spu->irqs[i] == NO_IRQ) { - pr_debug("spu_new: failed to map it !\n"); - goto err; - } - } - return 0; - -err: - pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, spu->name); - for (; i >= 0; i--) { - if (spu->irqs[i] != NO_IRQ) - irq_dispose_mapping(spu->irqs[i]); - } - return ret; -} - -static int spu_map_resource(struct device_node *node, int nr, - void __iomem** virt, unsigned long *phys) -{ - struct resource resource = { }; - int ret; - - ret = of_address_to_resource(node, nr, &resource); - if (ret) - goto out; - - if (phys) - *phys = resource.start; - *virt = ioremap(resource.start, resource.end - resource.start); - if (!*virt) - ret = -EINVAL; - -out: - return ret; -} - -static int __init spu_map_device(struct spu *spu, struct device_node *node) -{ - int ret = -ENODEV; - spu->name = get_property(node, "name", NULL); - if (!spu->name) - goto out; - - ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store, - &spu->local_store_phys); - if (ret) { - pr_debug("spu_new: failed to map %s resource 0\n", - node->full_name); - goto out; - } - ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem, - &spu->problem_phys); - if (ret) { - pr_debug("spu_new: failed to map %s resource 1\n", - node->full_name); - goto out_unmap; - } - ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2, - NULL); - if (ret) { - pr_debug("spu_new: failed to map %s resource 2\n", - node->full_name); - goto out_unmap; - } - - if (!firmware_has_feature(FW_FEATURE_LPAR)) - ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1, - NULL); - if (ret) { - pr_debug("spu_new: failed to map %s resource 3\n", - node->full_name); - goto out_unmap; - } - pr_debug("spu_new: %s maps:\n", node->full_name); - pr_debug(" local store : 0x%016lx -> 0x%p\n", - spu->local_store_phys, spu->local_store); - pr_debug(" problem state : 0x%016lx -> 0x%p\n", - spu->problem_phys, spu->problem); - pr_debug(" priv2 : 0x%p\n", spu->priv2); - pr_debug(" priv1 : 0x%p\n", spu->priv1); - - return 0; - -out_unmap: - spu_unmap(spu); -out: - pr_debug("failed to map spe %s: %d\n", spu->name, ret); - return ret; -} - struct sysdev_class spu_sysdev_class = { set_kset_name("spu") }; @@ -846,7 +585,7 @@ static void spu_destroy_sysdev(struct spu *spu) sysdev_unregister(&spu->sysdev); } -static int __init create_spu(struct device_node *spe) +static int __init create_spu(void *data) { struct spu *spu; int ret; @@ -857,60 +596,37 @@ static int __init create_spu(struct device_node *spe) if (!spu) goto out; - spu->node = find_spu_node_id(spe); - if (spu->node >= MAX_NUMNODES) { - printk(KERN_WARNING "SPE %s on node %d ignored," - " node number too big\n", spe->full_name, spu->node); - printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n"); - return -ENODEV; - } - spu->nid = of_node_to_nid(spe); - if (spu->nid == -1) - spu->nid = 0; + spin_lock_init(&spu->register_lock); + mutex_lock(&spu_mutex); + spu->number = number++; + mutex_unlock(&spu_mutex); + + ret = spu_create_spu(spu, data); - ret = spu_map_device(spu, spe); - /* try old method */ - if (ret) - ret = spu_map_device_old(spu, spe); if (ret) goto out_free; - ret = spu_map_interrupts(spu, spe); - if (ret) - ret = spu_map_interrupts_old(spu, spe); - if (ret) - goto out_unmap; - spin_lock_init(&spu->register_lock); spu_mfc_sdr_setup(spu); spu_mfc_sr1_set(spu, 0x33); - mutex_lock(&spu_mutex); - - spu->number = number++; ret = spu_request_irqs(spu); if (ret) - goto out_unlock; + goto out_destroy; ret = spu_create_sysdev(spu); if (ret) goto out_free_irqs; + mutex_lock(&spu_mutex); list_add(&spu->list, &spu_list[spu->node]); list_add(&spu->full_list, &spu_full_list); - spu->devnode = of_node_get(spe); - mutex_unlock(&spu_mutex); - pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n", - spu->name, spu->local_store, - spu->problem, spu->priv1, spu->priv2, spu->number); goto out; out_free_irqs: spu_free_irqs(spu); -out_unlock: - mutex_unlock(&spu_mutex); -out_unmap: - spu_unmap(spu); +out_destroy: + spu_destroy_spu(spu); out_free: kfree(spu); out: @@ -922,11 +638,9 @@ static void destroy_spu(struct spu *spu) list_del_init(&spu->list); list_del_init(&spu->full_list); - of_node_put(spu->devnode); - spu_destroy_sysdev(spu); spu_free_irqs(spu); - spu_unmap(spu); + spu_destroy_spu(spu); kfree(spu); } @@ -947,7 +661,6 @@ module_exit(cleanup_spu_base); static int __init init_spu_base(void) { - struct device_node *node; int i, ret; /* create sysdev class for spus */ @@ -958,16 +671,13 @@ static int __init init_spu_base(void) for (i = 0; i < MAX_NUMNODES; i++) INIT_LIST_HEAD(&spu_list[i]); - ret = -ENODEV; - for (node = of_find_node_by_type(NULL, "spe"); - node; node = of_find_node_by_type(node, "spe")) { - ret = create_spu(node); - if (ret) { - printk(KERN_WARNING "%s: Error initializing %s\n", - __FUNCTION__, node->name); - cleanup_spu_base(); - break; - } + ret = spu_enumerate_spus(create_spu); + + if (ret) { + printk(KERN_WARNING "%s: Error initializing spus\n", + __FUNCTION__); + cleanup_spu_base(); + return ret; } xmon_register_spus(&spu_full_list); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index 90011f9aab3..a5de0430c56 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -18,120 +18,498 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include +#include #include +#include +#include +#include +#include +#include +#include +#include -#include #include #include +#include +#include #include "interrupt.h" +#include "spu_priv1_mmio.h" + +struct spu_pdata { + int nid; + struct device_node *devnode; + struct spu_priv1 __iomem *priv1; +}; + +static struct spu_pdata *spu_get_pdata(struct spu *spu) +{ + BUG_ON(!spu->pdata); + return spu->pdata; +} + +struct device_node *spu_devnode(struct spu *spu) +{ + return spu_get_pdata(spu)->devnode; +} + +EXPORT_SYMBOL_GPL(spu_devnode); + +static int __init find_spu_node_id(struct device_node *spe) +{ + const unsigned int *id; + struct device_node *cpu; + cpu = spe->parent->parent; + id = get_property(cpu, "node-id", NULL); + return id ? *id : 0; +} + +static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe, + const char *prop) +{ + static DEFINE_MUTEX(add_spumem_mutex); + + const struct address_prop { + unsigned long address; + unsigned int len; + } __attribute__((packed)) *p; + int proplen; + + unsigned long start_pfn, nr_pages; + struct pglist_data *pgdata; + struct zone *zone; + int ret; + + p = get_property(spe, prop, &proplen); + WARN_ON(proplen != sizeof (*p)); + + start_pfn = p->address >> PAGE_SHIFT; + nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT; + + pgdata = NODE_DATA(spu_get_pdata(spu)->nid); + zone = pgdata->node_zones; + + /* XXX rethink locking here */ + mutex_lock(&add_spumem_mutex); + ret = __add_pages(zone, start_pfn, nr_pages); + mutex_unlock(&add_spumem_mutex); + + return ret; +} + +static void __iomem * __init map_spe_prop(struct spu *spu, + struct device_node *n, const char *name) +{ + const struct address_prop { + unsigned long address; + unsigned int len; + } __attribute__((packed)) *prop; + + const void *p; + int proplen; + void __iomem *ret = NULL; + int err = 0; + + p = get_property(n, name, &proplen); + if (proplen != sizeof (struct address_prop)) + return NULL; + + prop = p; + + err = cell_spuprop_present(spu, n, name); + if (err && (err != -EEXIST)) + goto out; + + ret = ioremap(prop->address, prop->len); + + out: + return ret; +} + +static void spu_unmap(struct spu *spu) +{ + iounmap(spu->priv2); + iounmap(spu_get_pdata(spu)->priv1); + iounmap(spu->problem); + iounmap((__force u8 __iomem *)spu->local_store); +} + +static int __init spu_map_interrupts_old(struct spu *spu, + struct device_node *np) +{ + unsigned int isrc; + const u32 *tmp; + + /* Get the interrupt source unit from the device-tree */ + tmp = get_property(np, "isrc", NULL); + if (!tmp) + return -ENODEV; + isrc = tmp[0]; + + /* Add the node number */ + isrc |= spu->node << IIC_IRQ_NODE_SHIFT; + + /* Now map interrupts of all 3 classes */ + spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc); + spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc); + spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc); + + /* Right now, we only fail if class 2 failed */ + return spu->irqs[2] == NO_IRQ ? -EINVAL : 0; +} + +static int __init spu_map_device_old(struct spu *spu, struct device_node *node) +{ + const char *prop; + int ret; + + ret = -ENODEV; + spu->name = get_property(node, "name", NULL); + if (!spu->name) + goto out; + + prop = get_property(node, "local-store", NULL); + if (!prop) + goto out; + spu->local_store_phys = *(unsigned long *)prop; + + /* we use local store as ram, not io memory */ + spu->local_store = (void __force *) + map_spe_prop(spu, node, "local-store"); + if (!spu->local_store) + goto out; + + prop = get_property(node, "problem", NULL); + if (!prop) + goto out_unmap; + spu->problem_phys = *(unsigned long *)prop; + + spu->problem= map_spe_prop(spu, node, "problem"); + if (!spu->problem) + goto out_unmap; + + spu_get_pdata(spu)->priv1= map_spe_prop(spu, node, "priv1"); + + spu->priv2= map_spe_prop(spu, node, "priv2"); + if (!spu->priv2) + goto out_unmap; + ret = 0; + goto out; + +out_unmap: + spu_unmap(spu); +out: + return ret; +} + +static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) +{ + struct of_irq oirq; + int ret; + int i; + + for (i=0; i < 3; i++) { + ret = of_irq_map_one(np, i, &oirq); + if (ret) { + pr_debug("spu_new: failed to get irq %d\n", i); + goto err; + } + ret = -EINVAL; + pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0], + oirq.controller->full_name); + spu->irqs[i] = irq_create_of_mapping(oirq.controller, + oirq.specifier, oirq.size); + if (spu->irqs[i] == NO_IRQ) { + pr_debug("spu_new: failed to map it !\n"); + goto err; + } + } + return 0; + +err: + pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, + spu->name); + for (; i >= 0; i--) { + if (spu->irqs[i] != NO_IRQ) + irq_dispose_mapping(spu->irqs[i]); + } + return ret; +} + +static int spu_map_resource(struct device_node *node, int nr, + void __iomem** virt, unsigned long *phys) +{ + struct resource resource = { }; + int ret; + + ret = of_address_to_resource(node, nr, &resource); + if (ret) + goto out; + + if (phys) + *phys = resource.start; + *virt = ioremap(resource.start, resource.end - resource.start); + if (!*virt) + ret = -EINVAL; + +out: + return ret; +} + +static int __init spu_map_device(struct spu *spu, struct device_node *node) +{ + int ret = -ENODEV; + spu->name = get_property(node, "name", NULL); + if (!spu->name) + goto out; + + ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store, + &spu->local_store_phys); + if (ret) { + pr_debug("spu_new: failed to map %s resource 0\n", + node->full_name); + goto out; + } + ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem, + &spu->problem_phys); + if (ret) { + pr_debug("spu_new: failed to map %s resource 1\n", + node->full_name); + goto out_unmap; + } + ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2, + NULL); + if (ret) { + pr_debug("spu_new: failed to map %s resource 2\n", + node->full_name); + goto out_unmap; + } + if (!firmware_has_feature(FW_FEATURE_LPAR)) + ret = spu_map_resource(node, 3, + (void __iomem**)&spu_get_pdata(spu)->priv1, NULL); + if (ret) { + pr_debug("spu_new: failed to map %s resource 3\n", + node->full_name); + goto out_unmap; + } + pr_debug("spu_new: %s maps:\n", node->full_name); + pr_debug(" local store : 0x%016lx -> 0x%p\n", + spu->local_store_phys, spu->local_store); + pr_debug(" problem state : 0x%016lx -> 0x%p\n", + spu->problem_phys, spu->problem); + pr_debug(" priv2 : 0x%p\n", spu->priv2); + pr_debug(" priv1 : 0x%p\n", + spu_get_pdata(spu)->priv1); + + return 0; + +out_unmap: + spu_unmap(spu); +out: + pr_debug("failed to map spe %s: %d\n", spu->name, ret); + return ret; +} + +static int __init of_enumerate_spus(int (*fn)(void *data)) +{ + int ret; + struct device_node *node; + + ret = -ENODEV; + for (node = of_find_node_by_type(NULL, "spe"); + node; node = of_find_node_by_type(node, "spe")) { + ret = fn(node); + if (ret) { + printk(KERN_WARNING "%s: Error initializing %s\n", + __FUNCTION__, node->name); + break; + } + } + return ret; +} + +static int __init of_create_spu(struct spu *spu, void *data) +{ + int ret; + struct device_node *spe = (struct device_node *)data; + + spu->pdata = kzalloc(sizeof(struct spu_pdata), + GFP_KERNEL); + if (!spu->pdata) { + ret = -ENOMEM; + goto out; + } + + spu->node = find_spu_node_id(spe); + if (spu->node >= MAX_NUMNODES) { + printk(KERN_WARNING "SPE %s on node %d ignored," + " node number too big\n", spe->full_name, spu->node); + printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n"); + ret = -ENODEV; + goto out_free; + } + + spu_get_pdata(spu)->nid = of_node_to_nid(spe); + if (spu_get_pdata(spu)->nid == -1) + spu_get_pdata(spu)->nid = 0; + + ret = spu_map_device(spu, spe); + /* try old method */ + if (ret) + ret = spu_map_device_old(spu, spe); + if (ret) + goto out_free; + + ret = spu_map_interrupts(spu, spe); + if (ret) + ret = spu_map_interrupts_old(spu, spe); + if (ret) + goto out_unmap; + + spu_get_pdata(spu)->devnode = of_node_get(spe); + + pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n", spu->name, + spu->local_store, spu->problem, spu_get_pdata(spu)->priv1, + spu->priv2, spu->number); + goto out; + +out_unmap: + spu_unmap(spu); +out_free: + kfree(spu->pdata); + spu->pdata = NULL; +out: + return ret; +} + +static int of_destroy_spu(struct spu *spu) +{ + spu_unmap(spu); + of_node_put(spu_get_pdata(spu)->devnode); + kfree(spu->pdata); + spu->pdata = NULL; + return 0; +} + +const struct spu_management_ops spu_management_of_ops = { + .enumerate_spus = of_enumerate_spus, + .create_spu = of_create_spu, + .destroy_spu = of_destroy_spu, +}; static void int_mask_and(struct spu *spu, int class, u64 mask) { u64 old_mask; - old_mask = in_be64(&spu->priv1->int_mask_RW[class]); - out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); + old_mask = in_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class]); + out_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class], + old_mask & mask); } static void int_mask_or(struct spu *spu, int class, u64 mask) { u64 old_mask; - old_mask = in_be64(&spu->priv1->int_mask_RW[class]); - out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); + old_mask = in_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class]); + out_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class], + old_mask | mask); } static void int_mask_set(struct spu *spu, int class, u64 mask) { - out_be64(&spu->priv1->int_mask_RW[class], mask); + out_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class], mask); } static u64 int_mask_get(struct spu *spu, int class) { - return in_be64(&spu->priv1->int_mask_RW[class]); + return in_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class]); } static void int_stat_clear(struct spu *spu, int class, u64 stat) { - out_be64(&spu->priv1->int_stat_RW[class], stat); + out_be64(&spu_get_pdata(spu)->priv1->int_stat_RW[class], stat); } static u64 int_stat_get(struct spu *spu, int class) { - return in_be64(&spu->priv1->int_stat_RW[class]); + return in_be64(&spu_get_pdata(spu)->priv1->int_stat_RW[class]); } static void cpu_affinity_set(struct spu *spu, int cpu) { u64 target = iic_get_target_id(cpu); u64 route = target << 48 | target << 32 | target << 16; - out_be64(&spu->priv1->int_route_RW, route); + out_be64(&spu_get_pdata(spu)->priv1->int_route_RW, route); } static u64 mfc_dar_get(struct spu *spu) { - return in_be64(&spu->priv1->mfc_dar_RW); + return in_be64(&spu_get_pdata(spu)->priv1->mfc_dar_RW); } static u64 mfc_dsisr_get(struct spu *spu) { - return in_be64(&spu->priv1->mfc_dsisr_RW); + return in_be64(&spu_get_pdata(spu)->priv1->mfc_dsisr_RW); } static void mfc_dsisr_set(struct spu *spu, u64 dsisr) { - out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); + out_be64(&spu_get_pdata(spu)->priv1->mfc_dsisr_RW, dsisr); } static void mfc_sdr_setup(struct spu *spu) { - out_be64(&spu->priv1->mfc_sdr_RW, mfspr(SPRN_SDR1)); + out_be64(&spu_get_pdata(spu)->priv1->mfc_sdr_RW, mfspr(SPRN_SDR1)); } static void mfc_sr1_set(struct spu *spu, u64 sr1) { - out_be64(&spu->priv1->mfc_sr1_RW, sr1); + out_be64(&spu_get_pdata(spu)->priv1->mfc_sr1_RW, sr1); } static u64 mfc_sr1_get(struct spu *spu) { - return in_be64(&spu->priv1->mfc_sr1_RW); + return in_be64(&spu_get_pdata(spu)->priv1->mfc_sr1_RW); } static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) { - out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); + out_be64(&spu_get_pdata(spu)->priv1->mfc_tclass_id_RW, tclass_id); } static u64 mfc_tclass_id_get(struct spu *spu) { - return in_be64(&spu->priv1->mfc_tclass_id_RW); + return in_be64(&spu_get_pdata(spu)->priv1->mfc_tclass_id_RW); } static void tlb_invalidate(struct spu *spu) { - out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); + out_be64(&spu_get_pdata(spu)->priv1->tlb_invalidate_entry_W, 0ul); } static void resource_allocation_groupID_set(struct spu *spu, u64 id) { - out_be64(&spu->priv1->resource_allocation_groupID_RW, id); + out_be64(&spu_get_pdata(spu)->priv1->resource_allocation_groupID_RW, + id); } static u64 resource_allocation_groupID_get(struct spu *spu) { - return in_be64(&spu->priv1->resource_allocation_groupID_RW); + return in_be64( + &spu_get_pdata(spu)->priv1->resource_allocation_groupID_RW); } static void resource_allocation_enable_set(struct spu *spu, u64 enable) { - out_be64(&spu->priv1->resource_allocation_enable_RW, enable); + out_be64(&spu_get_pdata(spu)->priv1->resource_allocation_enable_RW, + enable); } static u64 resource_allocation_enable_get(struct spu *spu) { - return in_be64(&spu->priv1->resource_allocation_enable_RW); + return in_be64( + &spu_get_pdata(spu)->priv1->resource_allocation_enable_RW); } const struct spu_priv1_ops spu_priv1_mmio_ops = diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.h b/arch/powerpc/platforms/cell/spu_priv1_mmio.h new file mode 100644 index 00000000000..7b62bd1cc25 --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.h @@ -0,0 +1,26 @@ +/* + * spu hypervisor abstraction for direct hardware access. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SPU_PRIV1_MMIO_H +#define SPU_PRIV1_MMIO_H + +struct device_node *spu_devnode(struct spu *spu); + +#endif /* SPU_PRIV1_MMIO_H */ diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index f968f869753..fdad4267b44 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -111,13 +111,11 @@ struct spu { u8 *local_store; unsigned long problem_phys; struct spu_problem __iomem *problem; - struct spu_priv1 __iomem *priv1; struct spu_priv2 __iomem *priv2; struct list_head list; struct list_head sched_list; struct list_head full_list; int number; - int nid; unsigned int irqs[3]; u32 node; u64 flags; @@ -144,8 +142,7 @@ struct spu { char irq_c1[8]; char irq_c2[8]; - struct device_node *devnode; - + void* pdata; /* platform private data */ struct sys_device sysdev; }; diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h index 4f9a04db99f..69dcb0c5388 100644 --- a/include/asm-powerpc/spu_priv1.h +++ b/include/asm-powerpc/spu_priv1.h @@ -21,12 +21,13 @@ #define _SPU_PRIV1_H #if defined(__KERNEL__) +#include + struct spu; /* access to priv1 registers */ -struct spu_priv1_ops -{ +struct spu_priv1_ops { void (*int_mask_and) (struct spu *spu, int class, u64 mask); void (*int_mask_or) (struct spu *spu, int class, u64 mask); void (*int_mask_set) (struct spu *spu, int class, u64 mask); @@ -171,12 +172,41 @@ spu_resource_allocation_enable_get (struct spu *spu) return spu_priv1_ops->resource_allocation_enable_get(spu); } -/* The declarations folowing are put here for convenience - * and only intended to be used by the platform setup code - * for initializing spu_priv1_ops. +/* spu management abstraction */ + +struct spu_management_ops { + int (*enumerate_spus)(int (*fn)(void *data)); + int (*create_spu)(struct spu *spu, void *data); + int (*destroy_spu)(struct spu *spu); +}; + +extern const struct spu_management_ops* spu_management_ops; + +static inline int +spu_enumerate_spus (int (*fn)(void *data)) +{ + return spu_management_ops->enumerate_spus(fn); +} + +static inline int +spu_create_spu (struct spu *spu, void *data) +{ + return spu_management_ops->create_spu(spu, data); +} + +static inline int +spu_destroy_spu (struct spu *spu) +{ + return spu_management_ops->destroy_spu(spu); +} + +/* + * The declarations folowing are put here for convenience + * and only intended to be used by the platform setup code. */ extern const struct spu_priv1_ops spu_priv1_mmio_ops; +extern const struct spu_management_ops spu_management_of_ops; #endif /* __KERNEL__ */ #endif -- cgit v1.2.3-70-g09d2 From f58a9d171a346afb1b09190427e6c28c6118703e Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 23 Nov 2006 00:46:51 +0100 Subject: [POWERPC] ps3: add support for ps3 platform Adds the core platform support for the PS3 game console and other devices using the PS3 hypervisor. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann --- MAINTAINERS | 7 + arch/powerpc/Kconfig | 11 +- arch/powerpc/platforms/Makefile | 1 + arch/powerpc/platforms/ps3/Kconfig | 32 ++ arch/powerpc/platforms/ps3/Makefile | 2 + arch/powerpc/platforms/ps3/mm.c | 827 ++++++++++++++++++++++++++++++++++ arch/powerpc/platforms/ps3/platform.h | 60 +++ arch/powerpc/platforms/ps3/setup.c | 173 +++++++ arch/powerpc/platforms/ps3/smp.c | 158 +++++++ arch/powerpc/platforms/ps3/time.c | 104 +++++ include/asm-powerpc/ps3.h | 250 ++++++++++ 11 files changed, 1624 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/platforms/ps3/Kconfig create mode 100644 arch/powerpc/platforms/ps3/Makefile create mode 100644 arch/powerpc/platforms/ps3/mm.c create mode 100644 arch/powerpc/platforms/ps3/platform.h create mode 100644 arch/powerpc/platforms/ps3/setup.c create mode 100644 arch/powerpc/platforms/ps3/smp.c create mode 100644 arch/powerpc/platforms/ps3/time.c create mode 100644 include/asm-powerpc/ps3.h (limited to 'include/asm-powerpc') diff --git a/MAINTAINERS b/MAINTAINERS index 45df5d4e2ab..fd3b2ca0c03 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2443,6 +2443,13 @@ M: promise@pnd-pc.demon.co.uk W: http://www.pnd-pc.demon.co.uk/promise/ S: Maintained +PS3 PLATFORM SUPPORT +P: Geoff Levand +M: geoffrey.levand@am.sony.com +L: linuxppc-dev@ozlabs.org +L: cbe-oss-dev@ozlabs.org +S: Supported + PVRUSB2 VIDEO4LINUX DRIVER P: Mike Isely M: isely@pobox.com diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index b4a3b699433..c0146a40c6f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -495,6 +495,14 @@ config UDBG_RTAS_CONSOLE depends on PPC_RTAS default n +config PPC_PS3 + bool "Sony PS3" + depends on PPC_MULTIPLATFORM && PPC64 + select PPC_CELL + help + This option enables support for the Sony PS3 game console + and other platforms using the PS3 hypervisor. + config XICS depends on PPC_PSERIES bool @@ -647,6 +655,7 @@ source arch/powerpc/platforms/85xx/Kconfig source arch/powerpc/platforms/86xx/Kconfig source arch/powerpc/platforms/8xx/Kconfig source arch/powerpc/platforms/cell/Kconfig +source arch/powerpc/platforms/ps3/Kconfig menu "Kernel options" @@ -917,7 +926,7 @@ config MCA config PCI bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ - || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 + || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 || PPC_PS3 default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ && !PPC_85xx && !PPC_86xx default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index 7ad2673d0aa..56caf4fbd73 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -16,4 +16,5 @@ obj-$(CONFIG_PPC_ISERIES) += iseries/ obj-$(CONFIG_PPC_MAPLE) += maple/ obj-$(CONFIG_PPC_PASEMI) += pasemi/ obj-$(CONFIG_PPC_CELL) += cell/ +obj-$(CONFIG_PS3) += ps3/ obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/ diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig new file mode 100644 index 00000000000..f023719f645 --- /dev/null +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -0,0 +1,32 @@ +menu "PS3 Platform Options" + depends on PPC_PS3 + +config PS3_HTAB_SIZE + depends on PPC_PS3 + int "PS3 Platform pagetable size" + range 18 20 + default 20 + help + This option is only for experts who may have the desire to fine + tune the pagetable size on their system. The value here is + expressed as the log2 of the page table size. Valid values are + 18, 19, and 20, corresponding to 256KB, 512KB and 1MB respectively. + + If unsure, choose the default (20) with the confidence that your + system will have optimal runtime performance. + +config PS3_DYNAMIC_DMA + depends on PPC_PS3 && EXPERIMENTAL + bool "PS3 Platform dynamic DMA page table management" + default n + help + This option will enable kernel support to take advantage of the + per device dynamic DMA page table management provided by the Cell + processor's IO Controller. This support incurs some runtime + overhead and also slightly increases kernel memory usage. The + current implementation should be considered experimental. + + This support is mainly for Linux kernel development. If unsure, + say N. + +endmenu diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile new file mode 100644 index 00000000000..8d6c72c6ea7 --- /dev/null +++ b/arch/powerpc/platforms/ps3/Makefile @@ -0,0 +1,2 @@ +obj-y += setup.o mm.o smp.o time.o hvcall.o htab.o repository.o +obj-y += interrupt.o exports.o diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c new file mode 100644 index 00000000000..a57f7036dd1 --- /dev/null +++ b/arch/powerpc/platforms/ps3/mm.c @@ -0,0 +1,827 @@ +/* + * PS3 address space management. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "platform.h" + +#if defined(DEBUG) +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) do{if(0)printk(fmt);}while(0) +#endif + +enum { +#if defined(CONFIG_PS3_USE_LPAR_ADDR) + USE_LPAR_ADDR = 1, +#else + USE_LPAR_ADDR = 0, +#endif +#if defined(CONFIG_PS3_DYNAMIC_DMA) + USE_DYNAMIC_DMA = 1, +#else + USE_DYNAMIC_DMA = 0, +#endif +}; + +enum { + PAGE_SHIFT_4K = 12U, + PAGE_SHIFT_64K = 16U, + PAGE_SHIFT_16M = 24U, +}; + +static unsigned long make_page_sizes(unsigned long a, unsigned long b) +{ + return (a << 56) | (b << 48); +} + +enum { + ALLOCATE_MEMORY_TRY_ALT_UNIT = 0X04, + ALLOCATE_MEMORY_ADDR_ZERO = 0X08, +}; + +/* valid htab sizes are {18,19,20} = 256K, 512K, 1M */ + +enum { + HTAB_SIZE_MAX = 20U, /* HV limit of 1MB */ + HTAB_SIZE_MIN = 18U, /* CPU limit of 256KB */ +}; + +/*============================================================================*/ +/* virtual address space routines */ +/*============================================================================*/ + +/** + * struct mem_region - memory region structure + * @base: base address + * @size: size in bytes + * @offset: difference between base and rm.size + */ + +struct mem_region { + unsigned long base; + unsigned long size; + unsigned long offset; +}; + +/** + * struct map - address space state variables holder + * @total: total memory available as reported by HV + * @vas_id - HV virtual address space id + * @htab_size: htab size in bytes + * + * The HV virtual address space (vas) allows for hotplug memory regions. + * Memory regions can be created and destroyed in the vas at runtime. + * @rm: real mode (bootmem) region + * @r1: hotplug memory region(s) + * + * ps3 addresses + * virt_addr: a cpu 'translated' effective address + * phys_addr: an address in what Linux thinks is the physical address space + * lpar_addr: an address in the HV virtual address space + * bus_addr: an io controller 'translated' address on a device bus + */ + +struct map { + unsigned long total; + unsigned long vas_id; + unsigned long htab_size; + struct mem_region rm; + struct mem_region r1; +}; + +#define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__) +static void _debug_dump_map(const struct map* m, const char* func, int line) +{ + DBG("%s:%d: map.total = %lxh\n", func, line, m->total); + DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size); + DBG("%s:%d: map.vas_id = %lu\n", func, line, m->vas_id); + DBG("%s:%d: map.htab_size = %lxh\n", func, line, m->htab_size); + DBG("%s:%d: map.r1.base = %lxh\n", func, line, m->r1.base); + DBG("%s:%d: map.r1.offset = %lxh\n", func, line, m->r1.offset); + DBG("%s:%d: map.r1.size = %lxh\n", func, line, m->r1.size); +} + +static struct map map; + +/** + * ps3_mm_phys_to_lpar - translate a linux physical address to lpar address + * @phys_addr: linux physical address + */ + +unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr) +{ + BUG_ON(is_kernel_addr(phys_addr)); + if (USE_LPAR_ADDR) + return phys_addr; + else + return (phys_addr < map.rm.size || phys_addr >= map.total) + ? phys_addr : phys_addr + map.r1.offset; +} + +EXPORT_SYMBOL(ps3_mm_phys_to_lpar); + +/** + * ps3_mm_vas_create - create the virtual address space + */ + +void __init ps3_mm_vas_create(unsigned long* htab_size) +{ + int result; + unsigned long start_address; + unsigned long size; + unsigned long access_right; + unsigned long max_page_size; + unsigned long flags; + + result = lv1_query_logical_partition_address_region_info(0, + &start_address, &size, &access_right, &max_page_size, + &flags); + + if (result) { + DBG("%s:%d: lv1_query_logical_partition_address_region_info " + "failed: %s\n", __func__, __LINE__, + ps3_result(result)); + goto fail; + } + + if (max_page_size < PAGE_SHIFT_16M) { + DBG("%s:%d: bad max_page_size %lxh\n", __func__, __LINE__, + max_page_size); + goto fail; + } + + BUILD_BUG_ON(CONFIG_PS3_HTAB_SIZE > HTAB_SIZE_MAX); + BUILD_BUG_ON(CONFIG_PS3_HTAB_SIZE < HTAB_SIZE_MIN); + + result = lv1_construct_virtual_address_space(CONFIG_PS3_HTAB_SIZE, + 2, make_page_sizes(PAGE_SHIFT_16M, PAGE_SHIFT_64K), + &map.vas_id, &map.htab_size); + + if (result) { + DBG("%s:%d: lv1_construct_virtual_address_space failed: %s\n", + __func__, __LINE__, ps3_result(result)); + goto fail; + } + + result = lv1_select_virtual_address_space(map.vas_id); + + if (result) { + DBG("%s:%d: lv1_select_virtual_address_space failed: %s\n", + __func__, __LINE__, ps3_result(result)); + goto fail; + } + + *htab_size = map.htab_size; + + debug_dump_map(&map); + + return; + +fail: + panic("ps3_mm_vas_create failed"); +} + +/** + * ps3_mm_vas_destroy - + */ + +void ps3_mm_vas_destroy(void) +{ + if (map.vas_id) { + lv1_select_virtual_address_space(0); + lv1_destruct_virtual_address_space(map.vas_id); + map.vas_id = 0; + } +} + +/*============================================================================*/ +/* memory hotplug routines */ +/*============================================================================*/ + +/** + * ps3_mm_region_create - create a memory region in the vas + * @r: pointer to a struct mem_region to accept initialized values + * @size: requested region size + * + * This implementation creates the region with the vas large page size. + * @size is rounded down to a multiple of the vas large page size. + */ + +int ps3_mm_region_create(struct mem_region *r, unsigned long size) +{ + int result; + unsigned long muid; + + r->size = _ALIGN_DOWN(size, 1 << PAGE_SHIFT_16M); + + DBG("%s:%d requested %lxh\n", __func__, __LINE__, size); + DBG("%s:%d actual %lxh\n", __func__, __LINE__, r->size); + DBG("%s:%d difference %lxh (%luMB)\n", __func__, __LINE__, + (unsigned long)(size - r->size), + (size - r->size) / 1024 / 1024); + + if (r->size == 0) { + DBG("%s:%d: size == 0\n", __func__, __LINE__); + result = -1; + goto zero_region; + } + + result = lv1_allocate_memory(r->size, PAGE_SHIFT_16M, 0, + ALLOCATE_MEMORY_TRY_ALT_UNIT, &r->base, &muid); + + if (result || r->base < map.rm.size) { + DBG("%s:%d: lv1_allocate_memory failed: %s\n", + __func__, __LINE__, ps3_result(result)); + goto zero_region; + } + + r->offset = r->base - map.rm.size; + return result; + +zero_region: + r->size = r->base = r->offset = 0; + return result; +} + +/** + * ps3_mm_region_destroy - destroy a memory region + * @r: pointer to struct mem_region + */ + +void ps3_mm_region_destroy(struct mem_region *r) +{ + if (r->base) { + lv1_release_memory(r->base); + r->size = r->base = r->offset = 0; + map.total = map.rm.size; + } +} + +/** + * ps3_mm_add_memory - hot add memory + */ + +static int __init ps3_mm_add_memory(void) +{ + int result; + unsigned long start_addr; + unsigned long start_pfn; + unsigned long nr_pages; + + BUG_ON(!mem_init_done); + + start_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size; + start_pfn = start_addr >> PAGE_SHIFT; + nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT; + + DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n", + __func__, __LINE__, start_addr, start_pfn, nr_pages); + + result = add_memory(0, start_addr, map.r1.size); + + if (result) { + DBG("%s:%d: add_memory failed: (%d)\n", + __func__, __LINE__, result); + return result; + } + + result = online_pages(start_pfn, nr_pages); + + if (result) + DBG("%s:%d: online_pages failed: (%d)\n", + __func__, __LINE__, result); + + return result; +} + +core_initcall(ps3_mm_add_memory); + +/*============================================================================*/ +/* dma routines */ +/*============================================================================*/ + +/** + * dma_lpar_to_bus - Translate an lpar address to ioc mapped bus address. + * @r: pointer to dma region structure + * @lpar_addr: HV lpar address + */ + +static unsigned long dma_lpar_to_bus(struct ps3_dma_region *r, + unsigned long lpar_addr) +{ + BUG_ON(lpar_addr >= map.r1.base + map.r1.size); + return r->bus_addr + (lpar_addr <= map.rm.size ? lpar_addr + : lpar_addr - map.r1.offset); +} + +#define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__) +static void _dma_dump_region(const struct ps3_dma_region *r, const char* func, + int line) +{ + DBG("%s:%d: dev %u:%u\n", func, line, r->did.bus_id, + r->did.dev_id); + DBG("%s:%d: page_size %u\n", func, line, r->page_size); + DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); + DBG("%s:%d: len %lxh\n", func, line, r->len); +} + +/** + * dma_chunk - A chunk of dma pages mapped by the io controller. + * @region - The dma region that owns this chunk. + * @lpar_addr: Starting lpar address of the area to map. + * @bus_addr: Starting ioc bus address of the area to map. + * @len: Length in bytes of the area to map. + * @link: A struct list_head used with struct ps3_dma_region.chunk_list, the + * list of all chuncks owned by the region. + * + * This implementation uses a very simple dma page manager + * based on the dma_chunk structure. This scheme assumes + * that all drivers use very well behaved dma ops. + */ + +struct dma_chunk { + struct ps3_dma_region *region; + unsigned long lpar_addr; + unsigned long bus_addr; + unsigned long len; + struct list_head link; + unsigned int usage_count; +}; + +#define dma_dump_chunk(_a) _dma_dump_chunk(_a, __func__, __LINE__) +static void _dma_dump_chunk (const struct dma_chunk* c, const char* func, + int line) +{ + DBG("%s:%d: r.dev %u:%u\n", func, line, + c->region->did.bus_id, c->region->did.dev_id); + DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr); + DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size); + DBG("%s:%d: r.len %lxh\n", func, line, c->region->len); + DBG("%s:%d: c.lpar_addr %lxh\n", func, line, c->lpar_addr); + DBG("%s:%d: c.bus_addr %lxh\n", func, line, c->bus_addr); + DBG("%s:%d: c.len %lxh\n", func, line, c->len); +} + +static struct dma_chunk * dma_find_chunk(struct ps3_dma_region *r, + unsigned long bus_addr, unsigned long len) +{ + struct dma_chunk *c; + unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size); + unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size); + + list_for_each_entry(c, &r->chunk_list.head, link) { + /* intersection */ + if (aligned_bus >= c->bus_addr + && aligned_bus < c->bus_addr + c->len + && aligned_bus + aligned_len <= c->bus_addr + c->len) { + return c; + } + /* below */ + if (aligned_bus + aligned_len <= c->bus_addr) { + continue; + } + /* above */ + if (aligned_bus >= c->bus_addr + c->len) { + continue; + } + + /* we don't handle the multi-chunk case for now */ + + dma_dump_chunk(c); + BUG(); + } + return NULL; +} + +static int dma_free_chunk(struct dma_chunk *c) +{ + int result = 0; + + if (c->bus_addr) { + result = lv1_unmap_device_dma_region(c->region->did.bus_id, + c->region->did.dev_id, c->bus_addr, c->len); + BUG_ON(result); + } + + kfree(c); + return result; +} + +/** + * dma_map_pages - Maps dma pages into the io controller bus address space. + * @r: Pointer to a struct ps3_dma_region. + * @phys_addr: Starting physical address of the area to map. + * @len: Length in bytes of the area to map. + * c_out: A pointer to receive an allocated struct dma_chunk for this area. + * + * This is the lowest level dma mapping routine, and is the one that will + * make the HV call to add the pages into the io controller address space. + */ + +static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, + unsigned long len, struct dma_chunk **c_out) +{ + int result; + struct dma_chunk *c; + + c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC); + + if (!c) { + result = -ENOMEM; + goto fail_alloc; + } + + c->region = r; + c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr); + c->bus_addr = dma_lpar_to_bus(r, c->lpar_addr); + c->len = len; + + result = lv1_map_device_dma_region(c->region->did.bus_id, + c->region->did.dev_id, c->lpar_addr, c->bus_addr, c->len, + 0xf800000000000000UL); + + if (result) { + DBG("%s:%d: lv1_map_device_dma_region failed: %s\n", + __func__, __LINE__, ps3_result(result)); + goto fail_map; + } + + list_add(&c->link, &r->chunk_list.head); + + *c_out = c; + return 0; + +fail_map: + kfree(c); +fail_alloc: + *c_out = NULL; + DBG(" <- %s:%d\n", __func__, __LINE__); + return result; +} + +/** + * dma_region_create - Create a device dma region. + * @r: Pointer to a struct ps3_dma_region. + * + * This is the lowest level dma region create routine, and is the one that + * will make the HV call to create the region. + */ + +static int dma_region_create(struct ps3_dma_region* r) +{ + int result; + + r->len = _ALIGN_UP(map.total, 1 << r->page_size); + INIT_LIST_HEAD(&r->chunk_list.head); + spin_lock_init(&r->chunk_list.lock); + + result = lv1_allocate_device_dma_region(r->did.bus_id, r->did.dev_id, + r->len, r->page_size, r->region_type, &r->bus_addr); + + dma_dump_region(r); + + if (result) { + DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n", + __func__, __LINE__, ps3_result(result)); + r->len = r->bus_addr = 0; + } + + return result; +} + +/** + * dma_region_free - Free a device dma region. + * @r: Pointer to a struct ps3_dma_region. + * + * This is the lowest level dma region free routine, and is the one that + * will make the HV call to free the region. + */ + +static int dma_region_free(struct ps3_dma_region* r) +{ + int result; + struct dma_chunk *c; + struct dma_chunk *tmp; + + list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) { + list_del(&c->link); + dma_free_chunk(c); + } + + result = lv1_free_device_dma_region(r->did.bus_id, r->did.dev_id, + r->bus_addr); + + if (result) + DBG("%s:%d: lv1_free_device_dma_region failed: %s\n", + __func__, __LINE__, ps3_result(result)); + + r->len = r->bus_addr = 0; + + return result; +} + +/** + * dma_map_area - Map an area of memory into a device dma region. + * @r: Pointer to a struct ps3_dma_region. + * @virt_addr: Starting virtual address of the area to map. + * @len: Length in bytes of the area to map. + * @bus_addr: A pointer to return the starting ioc bus address of the area to + * map. + * + * This is the common dma mapping routine. + */ + +static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, + unsigned long len, unsigned long *bus_addr) +{ + int result; + unsigned long flags; + struct dma_chunk *c; + unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) + : virt_addr; + + *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); + + if (!USE_DYNAMIC_DMA) { + unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr); + DBG(" -> %s:%d\n", __func__, __LINE__); + DBG("%s:%d virt_addr %lxh\n", __func__, __LINE__, + virt_addr); + DBG("%s:%d phys_addr %lxh\n", __func__, __LINE__, + phys_addr); + DBG("%s:%d lpar_addr %lxh\n", __func__, __LINE__, + lpar_addr); + DBG("%s:%d len %lxh\n", __func__, __LINE__, len); + DBG("%s:%d bus_addr %lxh (%lxh)\n", __func__, __LINE__, + *bus_addr, len); + } + + spin_lock_irqsave(&r->chunk_list.lock, flags); + c = dma_find_chunk(r, *bus_addr, len); + + if (c) { + c->usage_count++; + spin_unlock_irqrestore(&r->chunk_list.lock, flags); + return 0; + } + + result = dma_map_pages(r, _ALIGN_DOWN(phys_addr, 1 << r->page_size), + _ALIGN_UP(len, 1 << r->page_size), &c); + + if (result) { + *bus_addr = 0; + DBG("%s:%d: dma_map_pages failed (%d)\n", + __func__, __LINE__, result); + spin_unlock_irqrestore(&r->chunk_list.lock, flags); + return result; + } + + c->usage_count = 1; + + spin_unlock_irqrestore(&r->chunk_list.lock, flags); + return result; +} + +/** + * dma_unmap_area - Unmap an area of memory from a device dma region. + * @r: Pointer to a struct ps3_dma_region. + * @bus_addr: The starting ioc bus address of the area to unmap. + * @len: Length in bytes of the area to unmap. + * + * This is the common dma unmap routine. + */ + +int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, + unsigned long len) +{ + unsigned long flags; + struct dma_chunk *c; + + spin_lock_irqsave(&r->chunk_list.lock, flags); + c = dma_find_chunk(r, bus_addr, len); + + if (!c) { + unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, + 1 << r->page_size); + unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size); + DBG("%s:%d: not found: bus_addr %lxh\n", + __func__, __LINE__, bus_addr); + DBG("%s:%d: not found: len %lxh\n", + __func__, __LINE__, len); + DBG("%s:%d: not found: aligned_bus %lxh\n", + __func__, __LINE__, aligned_bus); + DBG("%s:%d: not found: aligned_len %lxh\n", + __func__, __LINE__, aligned_len); + BUG(); + } + + c->usage_count--; + + if (!c->usage_count) { + list_del(&c->link); + dma_free_chunk(c); + } + + spin_unlock_irqrestore(&r->chunk_list.lock, flags); + return 0; +} + +/** + * dma_region_create_linear - Setup a linear dma maping for a device. + * @r: Pointer to a struct ps3_dma_region. + * + * This routine creates an HV dma region for the device and maps all available + * ram into the io controller bus address space. + */ + +static int dma_region_create_linear(struct ps3_dma_region *r) +{ + int result; + unsigned long tmp; + + /* force 16M dma pages for linear mapping */ + + if (r->page_size != PS3_DMA_16M) { + pr_info("%s:%d: forcing 16M pages for linear map\n", + __func__, __LINE__); + r->page_size = PS3_DMA_16M; + } + + result = dma_region_create(r); + BUG_ON(result); + + result = dma_map_area(r, map.rm.base, map.rm.size, &tmp); + BUG_ON(result); + + if (USE_LPAR_ADDR) + result = dma_map_area(r, map.r1.base, map.r1.size, + &tmp); + else + result = dma_map_area(r, map.rm.size, map.r1.size, + &tmp); + + BUG_ON(result); + + return result; +} + +/** + * dma_region_free_linear - Free a linear dma mapping for a device. + * @r: Pointer to a struct ps3_dma_region. + * + * This routine will unmap all mapped areas and free the HV dma region. + */ + +static int dma_region_free_linear(struct ps3_dma_region *r) +{ + int result; + + result = dma_unmap_area(r, dma_lpar_to_bus(r, 0), map.rm.size); + BUG_ON(result); + + result = dma_unmap_area(r, dma_lpar_to_bus(r, map.r1.base), + map.r1.size); + BUG_ON(result); + + result = dma_region_free(r); + BUG_ON(result); + + return result; +} + +/** + * dma_map_area_linear - Map an area of memory into a device dma region. + * @r: Pointer to a struct ps3_dma_region. + * @virt_addr: Starting virtual address of the area to map. + * @len: Length in bytes of the area to map. + * @bus_addr: A pointer to return the starting ioc bus address of the area to + * map. + * + * This routine just returns the coresponding bus address. Actual mapping + * occurs in dma_region_create_linear(). + */ + +static int dma_map_area_linear(struct ps3_dma_region *r, + unsigned long virt_addr, unsigned long len, unsigned long *bus_addr) +{ + unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) + : virt_addr; + *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); + return 0; +} + +/** + * dma_unmap_area_linear - Unmap an area of memory from a device dma region. + * @r: Pointer to a struct ps3_dma_region. + * @bus_addr: The starting ioc bus address of the area to unmap. + * @len: Length in bytes of the area to unmap. + * + * This routine does nothing. Unmapping occurs in dma_region_free_linear(). + */ + +static int dma_unmap_area_linear(struct ps3_dma_region *r, + unsigned long bus_addr, unsigned long len) +{ + return 0; +} + +int ps3_dma_region_create(struct ps3_dma_region *r) +{ + return (USE_DYNAMIC_DMA) + ? dma_region_create(r) + : dma_region_create_linear(r); +} + +int ps3_dma_region_free(struct ps3_dma_region *r) +{ + return (USE_DYNAMIC_DMA) + ? dma_region_free(r) + : dma_region_free_linear(r); +} + +int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, + unsigned long len, unsigned long *bus_addr) +{ + return (USE_DYNAMIC_DMA) + ? dma_map_area(r, virt_addr, len, bus_addr) + : dma_map_area_linear(r, virt_addr, len, bus_addr); +} + +int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, + unsigned long len) +{ + return (USE_DYNAMIC_DMA) ? dma_unmap_area(r, bus_addr, len) + : dma_unmap_area_linear(r, bus_addr, len); +} + +/*============================================================================*/ +/* system startup routines */ +/*============================================================================*/ + +/** + * ps3_mm_init - initialize the address space state variables + */ + +void __init ps3_mm_init(void) +{ + int result; + + DBG(" -> %s:%d\n", __func__, __LINE__); + + result = ps3_repository_read_mm_info(&map.rm.base, &map.rm.size, + &map.total); + + if (result) + panic("ps3_repository_read_mm_info() failed"); + + map.rm.offset = map.rm.base; + map.vas_id = map.htab_size = 0; + + /* this implementation assumes map.rm.base is zero */ + + BUG_ON(map.rm.base); + BUG_ON(!map.rm.size); + + lmb_add(map.rm.base, map.rm.size); + lmb_analyze(); + + /* arrange to do this in ps3_mm_add_memory */ + ps3_mm_region_create(&map.r1, map.total - map.rm.size); + + DBG(" <- %s:%d\n", __func__, __LINE__); +} + +/** + * ps3_mm_shutdown - final cleanup of address space + */ + +void ps3_mm_shutdown(void) +{ + ps3_mm_region_destroy(&map.r1); + map.total = map.rm.size; +} diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h new file mode 100644 index 00000000000..d9948df6ccd --- /dev/null +++ b/arch/powerpc/platforms/ps3/platform.h @@ -0,0 +1,60 @@ +/* + * PS3 platform declarations. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(_PS3_PLATFORM_H) +#define _PS3_PLATFORM_H + +#include + +/* htab */ + +void __init ps3_hpte_init(unsigned long htab_size); +void __init ps3_map_htab(void); + +/* mm */ + +void __init ps3_mm_init(void); +void __init ps3_mm_vas_create(unsigned long* htab_size); +void ps3_mm_vas_destroy(void); +void ps3_mm_shutdown(void); + +/* irq */ + +void ps3_init_IRQ(void); +void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq); + +/* smp */ + +void smp_init_ps3(void); +void ps3_smp_cleanup_cpu(int cpu); + +/* time */ + +void __init ps3_calibrate_decr(void); +unsigned long __init ps3_get_boot_time(void); +void ps3_get_rtc_time(struct rtc_time *time); +int ps3_set_rtc_time(struct rtc_time *time); + +/* os area */ + +int __init ps3_os_area_init(void); +u64 ps3_os_area_rtc_diff(void); + +#endif diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c new file mode 100644 index 00000000000..c1f6de50654 --- /dev/null +++ b/arch/powerpc/platforms/ps3/setup.c @@ -0,0 +1,173 @@ +/* + * PS3 platform setup routines. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "platform.h" + +#if defined(DEBUG) +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) do{if(0)printk(fmt);}while(0) +#endif + +static void ps3_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "machine\t\t: %s\n", ppc_md.name); +} + +static void ps3_power_save(void) +{ + /* + * lv1_pause() puts the PPE thread into inactive state until an + * irq on an unmasked plug exists. MSR[EE] has no effect. + * flags: 0 = wake on DEC interrupt, 1 = ignore DEC interrupt. + */ + + lv1_pause(0); +} + +static void ps3_panic(char *str) +{ + DBG("%s:%d %s\n", __func__, __LINE__, str); + +#ifdef CONFIG_SMP + smp_send_stop(); +#endif + printk("\n"); + printk(" System does not reboot automatically.\n"); + printk(" Please press POWER button.\n"); + printk("\n"); + + for (;;) ; +} + +static void __init ps3_setup_arch(void) +{ + DBG(" -> %s:%d\n", __func__, __LINE__); + + ps3_spu_set_platform(); + ps3_map_htab(); + +#ifdef CONFIG_SMP + smp_init_ps3(); +#endif + +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + + ppc_md.power_save = ps3_power_save; + + DBG(" <- %s:%d\n", __func__, __LINE__); +} + +static void __init ps3_progress(char *s, unsigned short hex) +{ + printk("*** %04x : %s\n", hex, s ? s : ""); +} + +static int __init ps3_probe(void) +{ + unsigned long htab_size; + unsigned long dt_root; + + DBG(" -> %s:%d\n", __func__, __LINE__); + + dt_root = of_get_flat_dt_root(); + if (!of_flat_dt_is_compatible(dt_root, "PS3")) + return 0; + + powerpc_firmware_features |= FW_FEATURE_LPAR; + + ps3_os_area_init(); + ps3_mm_init(); + ps3_mm_vas_create(&htab_size); + ps3_hpte_init(htab_size); + + DBG(" <- %s:%d\n", __func__, __LINE__); + return 1; +} + +#if defined(CONFIG_KEXEC) +static void ps3_kexec_cpu_down(int crash_shutdown, int secondary) +{ + DBG(" -> %s:%d\n", __func__, __LINE__); + + if (secondary) { + int cpu; + for_each_online_cpu(cpu) + if (cpu) + ps3_smp_cleanup_cpu(cpu); + } else + ps3_smp_cleanup_cpu(0); + + DBG(" <- %s:%d\n", __func__, __LINE__); +} + +static void ps3_machine_kexec(struct kimage *image) +{ + unsigned long ppe_id; + + DBG(" -> %s:%d\n", __func__, __LINE__); + + lv1_get_logical_ppe_id(&ppe_id); + lv1_configure_irq_state_bitmap(ppe_id, 0, 0); + ps3_mm_shutdown(); + ps3_mm_vas_destroy(); + + default_machine_kexec(image); + + DBG(" <- %s:%d\n", __func__, __LINE__); +} +#endif + +define_machine(ps3) { + .name = "PS3", + .probe = ps3_probe, + .setup_arch = ps3_setup_arch, + .show_cpuinfo = ps3_show_cpuinfo, + .init_IRQ = ps3_init_IRQ, + .panic = ps3_panic, + .get_boot_time = ps3_get_boot_time, + .set_rtc_time = ps3_set_rtc_time, + .get_rtc_time = ps3_get_rtc_time, + .calibrate_decr = ps3_calibrate_decr, + .progress = ps3_progress, +#if defined(CONFIG_KEXEC) + .kexec_cpu_down = ps3_kexec_cpu_down, + .machine_kexec = ps3_machine_kexec, + .machine_kexec_prepare = default_machine_kexec_prepare, + .machine_crash_shutdown = default_machine_crash_shutdown, +#endif +}; diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c new file mode 100644 index 00000000000..11d2080607e --- /dev/null +++ b/arch/powerpc/platforms/ps3/smp.c @@ -0,0 +1,158 @@ +/* + * PS3 SMP routines. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include +#include +#include + +#include "platform.h" + +#if defined(DEBUG) +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) do{if(0)printk(fmt);}while(0) +#endif + +static irqreturn_t ipi_function_handler(int irq, void *msg) +{ + smp_message_recv((int)(long)msg); + return IRQ_HANDLED; +} + +/** + * virqs - a per cpu array of virqs for ipi use + */ + +#define MSG_COUNT 4 +static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]); + +static const char *names[MSG_COUNT] = { + "ipi call", + "ipi reschedule", + "ipi migrate", + "ipi debug brk" +}; + +static void do_message_pass(int target, int msg) +{ + int result; + unsigned int virq; + + if (msg >= MSG_COUNT) { + DBG("%s:%d: bad msg: %d\n", __func__, __LINE__, msg); + return; + } + + virq = per_cpu(virqs, target)[msg]; + result = ps3_send_event_locally(virq); + + if (result) + DBG("%s:%d: ps3_send_event_locally(%d, %d) failed" + " (%d)\n", __func__, __LINE__, target, msg, result); +} + +static void ps3_smp_message_pass(int target, int msg) +{ + int cpu; + + if (target < NR_CPUS) + do_message_pass(target, msg); + else if (target == MSG_ALL_BUT_SELF) { + for_each_online_cpu(cpu) + if (cpu != smp_processor_id()) + do_message_pass(cpu, msg); + } else { + for_each_online_cpu(cpu) + do_message_pass(cpu, msg); + } +} + +static int ps3_smp_probe(void) +{ + return 2; +} + +static void __init ps3_smp_setup_cpu(int cpu) +{ + int result; + unsigned int *virqs = per_cpu(virqs, cpu); + int i; + + DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); + + /* + * Check assumptions on virqs[] indexing. If this + * check fails, then a different mapping of PPC_MSG_ + * to index needs to be setup. + */ + + BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0); + BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1); + BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); + + for (i = 0; i < MSG_COUNT; i++) { + result = ps3_alloc_event_irq(&virqs[i]); + + if (result) + continue; + + DBG("%s:%d: (%d, %d) => virq %u\n", + __func__, __LINE__, cpu, i, virqs[i]); + + + request_irq(virqs[i], ipi_function_handler, IRQF_DISABLED, + names[i], (void*)(long)i); + } + + ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]); + + DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); +} + +void ps3_smp_cleanup_cpu(int cpu) +{ + unsigned int *virqs = per_cpu(virqs, cpu); + int i; + + DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); + for (i = 0; i < MSG_COUNT; i++) { + ps3_free_event_irq(virqs[i]); + free_irq(virqs[i], (void*)(long)i); + virqs[i] = NO_IRQ; + } + DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); +} + +static struct smp_ops_t ps3_smp_ops = { + .probe = ps3_smp_probe, + .message_pass = ps3_smp_message_pass, + .kick_cpu = smp_generic_kick_cpu, + .setup_cpu = ps3_smp_setup_cpu, +}; + +void smp_init_ps3(void) +{ + DBG(" -> %s\n", __func__); + smp_ops = &ps3_smp_ops; + DBG(" <- %s\n", __func__); +} diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c new file mode 100644 index 00000000000..1bae8b19b36 --- /dev/null +++ b/arch/powerpc/platforms/ps3/time.c @@ -0,0 +1,104 @@ +/* + * PS3 time and rtc routines. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include +#include +#include + +#include "platform.h" + +#define dump_tm(_a) _dump_tm(_a, __func__, __LINE__) +static void _dump_tm(const struct rtc_time *tm, const char* func, int line) +{ + pr_debug("%s:%d tm_sec %d\n", func, line, tm->tm_sec); + pr_debug("%s:%d tm_min %d\n", func, line, tm->tm_min); + pr_debug("%s:%d tm_hour %d\n", func, line, tm->tm_hour); + pr_debug("%s:%d tm_mday %d\n", func, line, tm->tm_mday); + pr_debug("%s:%d tm_mon %d\n", func, line, tm->tm_mon); + pr_debug("%s:%d tm_year %d\n", func, line, tm->tm_year); + pr_debug("%s:%d tm_wday %d\n", func, line, tm->tm_wday); +} + +#define dump_time(_a) _dump_time(_a, __func__, __LINE__) +static void __attribute__ ((unused)) _dump_time(int time, const char* func, + int line) +{ + struct rtc_time tm; + + to_tm(time, &tm); + + pr_debug("%s:%d time %d\n", func, line, time); + _dump_tm(&tm, func, line); +} + +/** + * rtc_shift - Difference in seconds between 1970 and the ps3 rtc value. + */ + +static s64 rtc_shift; + +void __init ps3_calibrate_decr(void) +{ + int result; + u64 tmp; + + result = ps3_repository_read_be_tb_freq(0, &tmp); + BUG_ON(result); + + ppc_tb_freq = tmp; + ppc_proc_freq = ppc_tb_freq * 40; + + rtc_shift = ps3_os_area_rtc_diff(); +} + +static u64 read_rtc(void) +{ + int result; + u64 rtc_val; + u64 tb_val; + + result = lv1_get_rtc(&rtc_val, &tb_val); + BUG_ON(result); + + return rtc_val; +} + +int ps3_set_rtc_time(struct rtc_time *tm) +{ + u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + rtc_shift = now - read_rtc(); + return 0; +} + +void ps3_get_rtc_time(struct rtc_time *tm) +{ + to_tm(read_rtc() + rtc_shift, tm); + tm->tm_year -= 1900; + tm->tm_mon -= 1; +} + +unsigned long __init ps3_get_boot_time(void) +{ + return read_rtc() + rtc_shift; +} diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h new file mode 100644 index 00000000000..d0109ffac50 --- /dev/null +++ b/include/asm-powerpc/ps3.h @@ -0,0 +1,250 @@ +/* + * PS3 platform declarations. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(_ASM_POWERPC_PS3_H) +#define _ASM_POWERPC_PS3_H + +#include /* for __deprecated */ +#include +#include +#include + +/** + * struct ps3_device_id - HV bus device identifier from the system repository + * @bus_id: HV bus id, {1..} (zero invalid) + * @dev_id: HV device id, {0..} + */ + +struct ps3_device_id { + unsigned int bus_id; + unsigned int dev_id; +}; + + +/* dma routines */ + +enum ps3_dma_page_size { + PS3_DMA_4K = 12U, + PS3_DMA_64K = 16U, + PS3_DMA_1M = 20U, + PS3_DMA_16M = 24U, +}; + +enum ps3_dma_region_type { + PS3_DMA_OTHER = 0, + PS3_DMA_INTERNAL = 2, +}; + +/** + * struct ps3_dma_region - A per device dma state variables structure + * @did: The HV device id. + * @page_size: The ioc pagesize. + * @region_type: The HV region type. + * @bus_addr: The 'translated' bus address of the region. + * @len: The length in bytes of the region. + * @chunk_list: Opaque variable used by the ioc page manager. + */ + +struct ps3_dma_region { + struct ps3_device_id did; + enum ps3_dma_page_size page_size; + enum ps3_dma_region_type region_type; + unsigned long bus_addr; + unsigned long len; + struct { + spinlock_t lock; + struct list_head head; + } chunk_list; +}; + +/** + * struct ps3_dma_region_init - Helper to initialize structure variables + * + * Helper to properly initialize variables prior to calling + * ps3_system_bus_device_register. + */ + +static inline void ps3_dma_region_init(struct ps3_dma_region *r, + const struct ps3_device_id* did, enum ps3_dma_page_size page_size, + enum ps3_dma_region_type region_type) +{ + r->did = *did; + r->page_size = page_size; + r->region_type = region_type; +} +int ps3_dma_region_create(struct ps3_dma_region *r); +int ps3_dma_region_free(struct ps3_dma_region *r); +int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, + unsigned long len, unsigned long *bus_addr); +int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, + unsigned long len); + +/* mmio routines */ + +enum ps3_mmio_page_size { + PS3_MMIO_4K = 12U, + PS3_MMIO_64K = 16U +}; + +/** + * struct ps3_mmio_region - a per device mmio state variables structure + * + * Current systems can be supported with a single region per device. + */ + +struct ps3_mmio_region { + struct ps3_device_id did; + unsigned long bus_addr; + unsigned long len; + enum ps3_mmio_page_size page_size; + unsigned long lpar_addr; +}; + +/** + * struct ps3_mmio_region_init - Helper to initialize structure variables + * + * Helper to properly initialize variables prior to calling + * ps3_system_bus_device_register. + */ + +static inline void ps3_mmio_region_init(struct ps3_mmio_region *r, + const struct ps3_device_id* did, unsigned long bus_addr, + unsigned long len, enum ps3_mmio_page_size page_size) +{ + r->did = *did; + r->bus_addr = bus_addr; + r->len = len; + r->page_size = page_size; +} +int ps3_mmio_region_create(struct ps3_mmio_region *r); +int ps3_free_mmio_region(struct ps3_mmio_region *r); +unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr); + +/* inrerrupt routines */ + +int ps3_alloc_io_irq(unsigned int interrupt_id, unsigned int *virq); +int ps3_free_io_irq(unsigned int virq); +int ps3_alloc_event_irq(unsigned int *virq); +int ps3_free_event_irq(unsigned int virq); +int ps3_send_event_locally(unsigned int virq); +int ps3_connect_event_irq(const struct ps3_device_id *did, + unsigned int interrupt_id, unsigned int *virq); +int ps3_disconnect_event_irq(const struct ps3_device_id *did, + unsigned int interrupt_id, unsigned int virq); +int ps3_alloc_vuart_irq(void* virt_addr_bmp, unsigned int *virq); +int ps3_free_vuart_irq(unsigned int virq); +int ps3_alloc_spe_irq(unsigned long spe_id, unsigned int class, + unsigned int *virq); +int ps3_free_spe_irq(unsigned int virq); + +/* lv1 result codes */ + +enum lv1_result { + LV1_SUCCESS = 0, + /* not used -1 */ + LV1_RESOURCE_SHORTAGE = -2, + LV1_NO_PRIVILEGE = -3, + LV1_DENIED_BY_POLICY = -4, + LV1_ACCESS_VIOLATION = -5, + LV1_NO_ENTRY = -6, + LV1_DUPLICATE_ENTRY = -7, + LV1_TYPE_MISMATCH = -8, + LV1_BUSY = -9, + LV1_EMPTY = -10, + LV1_WRONG_STATE = -11, + /* not used -12 */ + LV1_NO_MATCH = -13, + LV1_ALREADY_CONNECTED = -14, + LV1_UNSUPPORTED_PARAMETER_VALUE = -15, + LV1_CONDITION_NOT_SATISFIED = -16, + LV1_ILLEGAL_PARAMETER_VALUE = -17, + LV1_BAD_OPTION = -18, + LV1_IMPLEMENTATION_LIMITATION = -19, + LV1_NOT_IMPLEMENTED = -20, + LV1_INVALID_CLASS_ID = -21, + LV1_CONSTRAINT_NOT_SATISFIED = -22, + LV1_ALIGNMENT_ERROR = -23, + LV1_INTERNAL_ERROR = -32768, +}; + +static inline const char* ps3_result(int result) +{ +#if defined(DEBUG) + switch (result) { + case LV1_SUCCESS: + return "LV1_SUCCESS (0)"; + case -1: + return "** unknown result ** (-1)"; + case LV1_RESOURCE_SHORTAGE: + return "LV1_RESOURCE_SHORTAGE (-2)"; + case LV1_NO_PRIVILEGE: + return "LV1_NO_PRIVILEGE (-3)"; + case LV1_DENIED_BY_POLICY: + return "LV1_DENIED_BY_POLICY (-4)"; + case LV1_ACCESS_VIOLATION: + return "LV1_ACCESS_VIOLATION (-5)"; + case LV1_NO_ENTRY: + return "LV1_NO_ENTRY (-6)"; + case LV1_DUPLICATE_ENTRY: + return "LV1_DUPLICATE_ENTRY (-7)"; + case LV1_TYPE_MISMATCH: + return "LV1_TYPE_MISMATCH (-8)"; + case LV1_BUSY: + return "LV1_BUSY (-9)"; + case LV1_EMPTY: + return "LV1_EMPTY (-10)"; + case LV1_WRONG_STATE: + return "LV1_WRONG_STATE (-11)"; + case -12: + return "** unknown result ** (-12)"; + case LV1_NO_MATCH: + return "LV1_NO_MATCH (-13)"; + case LV1_ALREADY_CONNECTED: + return "LV1_ALREADY_CONNECTED (-14)"; + case LV1_UNSUPPORTED_PARAMETER_VALUE: + return "LV1_UNSUPPORTED_PARAMETER_VALUE (-15)"; + case LV1_CONDITION_NOT_SATISFIED: + return "LV1_CONDITION_NOT_SATISFIED (-16)"; + case LV1_ILLEGAL_PARAMETER_VALUE: + return "LV1_ILLEGAL_PARAMETER_VALUE (-17)"; + case LV1_BAD_OPTION: + return "LV1_BAD_OPTION (-18)"; + case LV1_IMPLEMENTATION_LIMITATION: + return "LV1_IMPLEMENTATION_LIMITATION (-19)"; + case LV1_NOT_IMPLEMENTED: + return "LV1_NOT_IMPLEMENTED (-20)"; + case LV1_INVALID_CLASS_ID: + return "LV1_INVALID_CLASS_ID (-21)"; + case LV1_CONSTRAINT_NOT_SATISFIED: + return "LV1_CONSTRAINT_NOT_SATISFIED (-22)"; + case LV1_ALIGNMENT_ERROR: + return "LV1_ALIGNMENT_ERROR (-23)"; + case LV1_INTERNAL_ERROR: + return "LV1_INTERNAL_ERROR (-32768)"; + default: + BUG(); + return "** unknown result **"; + }; +#else + return ""; +#endif +} + +#endif -- cgit v1.2.3-70-g09d2 From 1e4ed915d133aaa2802d11914a7e80b3e31304e6 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 23 Nov 2006 00:46:52 +0100 Subject: [POWERPC] ps3: add lv1 hvcalls Adds the PS3 hvcalls. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann --- arch/powerpc/platforms/ps3/exports.c | 27 ++ arch/powerpc/platforms/ps3/hvcall.S | 804 +++++++++++++++++++++++++++++++++++ include/asm-powerpc/lv1call.h | 345 +++++++++++++++ 3 files changed, 1176 insertions(+) create mode 100644 arch/powerpc/platforms/ps3/exports.c create mode 100644 arch/powerpc/platforms/ps3/hvcall.S create mode 100644 include/asm-powerpc/lv1call.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/ps3/exports.c b/arch/powerpc/platforms/ps3/exports.c new file mode 100644 index 00000000000..a7e8ffd24a6 --- /dev/null +++ b/arch/powerpc/platforms/ps3/exports.c @@ -0,0 +1,27 @@ +/* + * PS3 hvcall exports for modules. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#define LV1_CALL(name, in, out, num) \ + extern s64 _lv1_##name(LV1_##in##_IN_##out##_OUT_ARG_DECL); \ + EXPORT_SYMBOL(_lv1_##name); + +#include diff --git a/arch/powerpc/platforms/ps3/hvcall.S b/arch/powerpc/platforms/ps3/hvcall.S new file mode 100644 index 00000000000..54be6523a0e --- /dev/null +++ b/arch/powerpc/platforms/ps3/hvcall.S @@ -0,0 +1,804 @@ +/* + * PS3 hvcall interface. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * Copyright 2003, 2004 (c) MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#define lv1call .long 0x44000022; extsw r3, r3 + +#define LV1_N_IN_0_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_0_IN_0_OUT LV1_N_IN_0_OUT +#define LV1_1_IN_0_OUT LV1_N_IN_0_OUT +#define LV1_2_IN_0_OUT LV1_N_IN_0_OUT +#define LV1_3_IN_0_OUT LV1_N_IN_0_OUT +#define LV1_4_IN_0_OUT LV1_N_IN_0_OUT +#define LV1_5_IN_0_OUT LV1_N_IN_0_OUT +#define LV1_6_IN_0_OUT LV1_N_IN_0_OUT +#define LV1_7_IN_0_OUT LV1_N_IN_0_OUT + +#define LV1_0_IN_1_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + stdu r3, -8(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 8; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_0_IN_2_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r3, -8(r1); \ + stdu r4, -16(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 16; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_0_IN_3_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r3, -8(r1); \ + std r4, -16(r1); \ + stdu r5, -24(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 24; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_0_IN_7_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r3, -8(r1); \ + std r4, -16(r1); \ + std r5, -24(r1); \ + std r6, -32(r1); \ + std r7, -40(r1); \ + std r8, -48(r1); \ + stdu r9, -56(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 56; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + ld r11, -32(r1); \ + std r7, 0(r11); \ + ld r11, -40(r1); \ + std r8, 0(r11); \ + ld r11, -48(r1); \ + std r9, 0(r11); \ + ld r11, -56(r1); \ + std r10, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_1_IN_1_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + stdu r4, -8(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 8; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_1_IN_2_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r4, -8(r1); \ + stdu r5, -16(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 16; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_1_IN_3_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r4, -8(r1); \ + std r5, -16(r1); \ + stdu r6, -24(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 24; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_1_IN_4_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r4, -8(r1); \ + std r5, -16(r1); \ + std r6, -24(r1); \ + stdu r7, -32(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 32; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + ld r11, -32(r1); \ + std r7, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_1_IN_5_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r4, -8(r1); \ + std r5, -16(r1); \ + std r6, -24(r1); \ + std r7, -32(r1); \ + stdu r8, -40(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 40; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + ld r11, -32(r1); \ + std r7, 0(r11); \ + ld r11, -40(r1); \ + std r8, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_1_IN_6_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r4, -8(r1); \ + std r5, -16(r1); \ + std r6, -24(r1); \ + std r7, -32(r1); \ + std r8, -40(r1); \ + stdu r9, -48(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 48; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + ld r11, -32(r1); \ + std r7, 0(r11); \ + ld r11, -40(r1); \ + std r8, 0(r11); \ + ld r11, -48(r1); \ + std r9, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_1_IN_7_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r4, -8(r1); \ + std r5, -16(r1); \ + std r6, -24(r1); \ + std r7, -32(r1); \ + std r8, -40(r1); \ + std r9, -48(r1); \ + stdu r10, -56(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 56; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + ld r11, -32(r1); \ + std r7, 0(r11); \ + ld r11, -40(r1); \ + std r8, 0(r11); \ + ld r11, -48(r1); \ + std r9, 0(r11); \ + ld r11, -56(r1); \ + std r10, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_2_IN_1_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + stdu r5, -8(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 8; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_2_IN_2_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r5, -8(r1); \ + stdu r6, -16(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 16; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_2_IN_3_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r5, -8(r1); \ + std r6, -16(r1); \ + stdu r7, -24(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 24; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_2_IN_4_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r5, -8(r1); \ + std r6, -16(r1); \ + std r7, -24(r1); \ + stdu r8, -32(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 32; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + ld r11, -32(r1); \ + std r7, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_2_IN_5_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r5, -8(r1); \ + std r6, -16(r1); \ + std r7, -24(r1); \ + std r8, -32(r1); \ + stdu r9, -40(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 40; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + ld r11, -32(r1); \ + std r7, 0(r11); \ + ld r11, -40(r1); \ + std r8, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_3_IN_1_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + stdu r6, -8(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 8; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_3_IN_2_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r6, -8(r1); \ + stdu r7, -16(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 16; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_3_IN_3_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r6, -8(r1); \ + std r7, -16(r1); \ + stdu r8, -24(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 24; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_4_IN_1_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + stdu r7, -8(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 8; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_4_IN_2_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r7, -8(r1); \ + stdu r8, -16(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 16; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_4_IN_3_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r7, -8(r1); \ + std r8, -16(r1); \ + stdu r9, -24(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 24; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_5_IN_1_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + stdu r8, -8(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 8; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_5_IN_2_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r8, -8(r1); \ + stdu r9, -16(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 16; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_5_IN_3_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r8, -8(r1); \ + std r9, -16(r1); \ + stdu r10, -24(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 24; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, -24(r1); \ + std r6, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_6_IN_1_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + stdu r9, -8(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 8; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_6_IN_2_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r9, -8(r1); \ + stdu r10, -16(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 16; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_6_IN_3_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r9, -8(r1); \ + stdu r10, -16(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 16; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + ld r11, -16(r1); \ + std r5, 0(r11); \ + ld r11, 48+8*8(r1); \ + std r6, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_7_IN_1_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + stdu r10, -8(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + addi r1, r1, 8; \ + ld r11, -8(r1); \ + std r4, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_7_IN_6_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + std r10, 48+8*7(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + ld r11, 48+8*7(r1); \ + std r4, 0(r11); \ + ld r11, 48+8*8(r1); \ + std r5, 0(r11); \ + ld r11, 48+8*9(r1); \ + std r6, 0(r11); \ + ld r11, 48+8*10(r1); \ + std r7, 0(r11); \ + ld r11, 48+8*11(r1); \ + std r8, 0(r11); \ + ld r11, 48+8*12(r1); \ + std r9, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + +#define LV1_8_IN_1_OUT(API_NAME, API_NUMBER) \ +_GLOBAL(_##API_NAME) \ + \ + mflr r0; \ + std r0, 16(r1); \ + \ + li r11, API_NUMBER; \ + lv1call; \ + \ + ld r11, 48+8*8(r1); \ + std r4, 0(r11); \ + \ + ld r0, 16(r1); \ + mtlr r0; \ + blr + + .text + +/* the lv1 underscored call definitions expand here */ + +#define LV1_CALL(name, in, out, num) LV1_##in##_IN_##out##_OUT(lv1_##name, num) +#include diff --git a/include/asm-powerpc/lv1call.h b/include/asm-powerpc/lv1call.h new file mode 100644 index 00000000000..f733beeea63 --- /dev/null +++ b/include/asm-powerpc/lv1call.h @@ -0,0 +1,345 @@ +/* + * PS3 hvcall interface. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * Copyright 2003, 2004 (c) MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(_ASM_POWERPC_LV1CALL_H) +#define _ASM_POWERPC_LV1CALL_H + +#if !defined(__ASSEMBLY__) + +#include + +/* lv1 call declaration macros */ + +#define LV1_1_IN_ARG_DECL u64 in_1 +#define LV1_2_IN_ARG_DECL LV1_1_IN_ARG_DECL, u64 in_2 +#define LV1_3_IN_ARG_DECL LV1_2_IN_ARG_DECL, u64 in_3 +#define LV1_4_IN_ARG_DECL LV1_3_IN_ARG_DECL, u64 in_4 +#define LV1_5_IN_ARG_DECL LV1_4_IN_ARG_DECL, u64 in_5 +#define LV1_6_IN_ARG_DECL LV1_5_IN_ARG_DECL, u64 in_6 +#define LV1_7_IN_ARG_DECL LV1_6_IN_ARG_DECL, u64 in_7 +#define LV1_8_IN_ARG_DECL LV1_7_IN_ARG_DECL, u64 in_8 +#define LV1_1_OUT_ARG_DECL u64 *out_1 +#define LV1_2_OUT_ARG_DECL LV1_1_OUT_ARG_DECL, u64 *out_2 +#define LV1_3_OUT_ARG_DECL LV1_2_OUT_ARG_DECL, u64 *out_3 +#define LV1_4_OUT_ARG_DECL LV1_3_OUT_ARG_DECL, u64 *out_4 +#define LV1_5_OUT_ARG_DECL LV1_4_OUT_ARG_DECL, u64 *out_5 +#define LV1_6_OUT_ARG_DECL LV1_5_OUT_ARG_DECL, u64 *out_6 +#define LV1_7_OUT_ARG_DECL LV1_6_OUT_ARG_DECL, u64 *out_7 + +#define LV1_0_IN_0_OUT_ARG_DECL void +#define LV1_1_IN_0_OUT_ARG_DECL LV1_1_IN_ARG_DECL +#define LV1_2_IN_0_OUT_ARG_DECL LV1_2_IN_ARG_DECL +#define LV1_3_IN_0_OUT_ARG_DECL LV1_3_IN_ARG_DECL +#define LV1_4_IN_0_OUT_ARG_DECL LV1_4_IN_ARG_DECL +#define LV1_5_IN_0_OUT_ARG_DECL LV1_5_IN_ARG_DECL +#define LV1_6_IN_0_OUT_ARG_DECL LV1_6_IN_ARG_DECL +#define LV1_7_IN_0_OUT_ARG_DECL LV1_7_IN_ARG_DECL + +#define LV1_0_IN_1_OUT_ARG_DECL LV1_1_OUT_ARG_DECL +#define LV1_1_IN_1_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_1_OUT_ARG_DECL +#define LV1_2_IN_1_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_1_OUT_ARG_DECL +#define LV1_3_IN_1_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_1_OUT_ARG_DECL +#define LV1_4_IN_1_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_1_OUT_ARG_DECL +#define LV1_5_IN_1_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_1_OUT_ARG_DECL +#define LV1_6_IN_1_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_1_OUT_ARG_DECL +#define LV1_7_IN_1_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_1_OUT_ARG_DECL +#define LV1_8_IN_1_OUT_ARG_DECL LV1_8_IN_ARG_DECL, LV1_1_OUT_ARG_DECL + +#define LV1_0_IN_2_OUT_ARG_DECL LV1_2_OUT_ARG_DECL +#define LV1_1_IN_2_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_2_OUT_ARG_DECL +#define LV1_2_IN_2_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_2_OUT_ARG_DECL +#define LV1_3_IN_2_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_2_OUT_ARG_DECL +#define LV1_4_IN_2_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_2_OUT_ARG_DECL +#define LV1_5_IN_2_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_2_OUT_ARG_DECL +#define LV1_6_IN_2_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_2_OUT_ARG_DECL +#define LV1_7_IN_2_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_2_OUT_ARG_DECL + +#define LV1_0_IN_3_OUT_ARG_DECL LV1_3_OUT_ARG_DECL +#define LV1_1_IN_3_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_3_OUT_ARG_DECL +#define LV1_2_IN_3_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_3_OUT_ARG_DECL +#define LV1_3_IN_3_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_3_OUT_ARG_DECL +#define LV1_4_IN_3_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_3_OUT_ARG_DECL +#define LV1_5_IN_3_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_3_OUT_ARG_DECL +#define LV1_6_IN_3_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_3_OUT_ARG_DECL +#define LV1_7_IN_3_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_3_OUT_ARG_DECL + +#define LV1_0_IN_4_OUT_ARG_DECL LV1_4_OUT_ARG_DECL +#define LV1_1_IN_4_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_4_OUT_ARG_DECL +#define LV1_2_IN_4_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_4_OUT_ARG_DECL +#define LV1_3_IN_4_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_4_OUT_ARG_DECL +#define LV1_4_IN_4_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_4_OUT_ARG_DECL +#define LV1_5_IN_4_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_4_OUT_ARG_DECL +#define LV1_6_IN_4_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_4_OUT_ARG_DECL +#define LV1_7_IN_4_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_4_OUT_ARG_DECL + +#define LV1_0_IN_5_OUT_ARG_DECL LV1_5_OUT_ARG_DECL +#define LV1_1_IN_5_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_5_OUT_ARG_DECL +#define LV1_2_IN_5_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_5_OUT_ARG_DECL +#define LV1_3_IN_5_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_5_OUT_ARG_DECL +#define LV1_4_IN_5_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_5_OUT_ARG_DECL +#define LV1_5_IN_5_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_5_OUT_ARG_DECL +#define LV1_6_IN_5_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_5_OUT_ARG_DECL +#define LV1_7_IN_5_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_5_OUT_ARG_DECL + +#define LV1_0_IN_6_OUT_ARG_DECL LV1_6_OUT_ARG_DECL +#define LV1_1_IN_6_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_6_OUT_ARG_DECL +#define LV1_2_IN_6_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_6_OUT_ARG_DECL +#define LV1_3_IN_6_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_6_OUT_ARG_DECL +#define LV1_4_IN_6_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_6_OUT_ARG_DECL +#define LV1_5_IN_6_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_6_OUT_ARG_DECL +#define LV1_6_IN_6_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_6_OUT_ARG_DECL +#define LV1_7_IN_6_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_6_OUT_ARG_DECL + +#define LV1_0_IN_7_OUT_ARG_DECL LV1_7_OUT_ARG_DECL +#define LV1_1_IN_7_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_7_OUT_ARG_DECL +#define LV1_2_IN_7_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_7_OUT_ARG_DECL +#define LV1_3_IN_7_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_7_OUT_ARG_DECL +#define LV1_4_IN_7_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_7_OUT_ARG_DECL +#define LV1_5_IN_7_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_7_OUT_ARG_DECL +#define LV1_6_IN_7_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_7_OUT_ARG_DECL +#define LV1_7_IN_7_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_7_OUT_ARG_DECL + +#define LV1_1_IN_ARGS in_1 +#define LV1_2_IN_ARGS LV1_1_IN_ARGS, in_2 +#define LV1_3_IN_ARGS LV1_2_IN_ARGS, in_3 +#define LV1_4_IN_ARGS LV1_3_IN_ARGS, in_4 +#define LV1_5_IN_ARGS LV1_4_IN_ARGS, in_5 +#define LV1_6_IN_ARGS LV1_5_IN_ARGS, in_6 +#define LV1_7_IN_ARGS LV1_6_IN_ARGS, in_7 +#define LV1_8_IN_ARGS LV1_7_IN_ARGS, in_8 + +#define LV1_1_OUT_ARGS out_1 +#define LV1_2_OUT_ARGS LV1_1_OUT_ARGS, out_2 +#define LV1_3_OUT_ARGS LV1_2_OUT_ARGS, out_3 +#define LV1_4_OUT_ARGS LV1_3_OUT_ARGS, out_4 +#define LV1_5_OUT_ARGS LV1_4_OUT_ARGS, out_5 +#define LV1_6_OUT_ARGS LV1_5_OUT_ARGS, out_6 +#define LV1_7_OUT_ARGS LV1_6_OUT_ARGS, out_7 + +#define LV1_0_IN_0_OUT_ARGS +#define LV1_1_IN_0_OUT_ARGS LV1_1_IN_ARGS +#define LV1_2_IN_0_OUT_ARGS LV1_2_IN_ARGS +#define LV1_3_IN_0_OUT_ARGS LV1_3_IN_ARGS +#define LV1_4_IN_0_OUT_ARGS LV1_4_IN_ARGS +#define LV1_5_IN_0_OUT_ARGS LV1_5_IN_ARGS +#define LV1_6_IN_0_OUT_ARGS LV1_6_IN_ARGS +#define LV1_7_IN_0_OUT_ARGS LV1_7_IN_ARGS + +#define LV1_0_IN_1_OUT_ARGS LV1_1_OUT_ARGS +#define LV1_1_IN_1_OUT_ARGS LV1_1_IN_ARGS, LV1_1_OUT_ARGS +#define LV1_2_IN_1_OUT_ARGS LV1_2_IN_ARGS, LV1_1_OUT_ARGS +#define LV1_3_IN_1_OUT_ARGS LV1_3_IN_ARGS, LV1_1_OUT_ARGS +#define LV1_4_IN_1_OUT_ARGS LV1_4_IN_ARGS, LV1_1_OUT_ARGS +#define LV1_5_IN_1_OUT_ARGS LV1_5_IN_ARGS, LV1_1_OUT_ARGS +#define LV1_6_IN_1_OUT_ARGS LV1_6_IN_ARGS, LV1_1_OUT_ARGS +#define LV1_7_IN_1_OUT_ARGS LV1_7_IN_ARGS, LV1_1_OUT_ARGS +#define LV1_8_IN_1_OUT_ARGS LV1_8_IN_ARGS, LV1_1_OUT_ARGS + +#define LV1_0_IN_2_OUT_ARGS LV1_2_OUT_ARGS +#define LV1_1_IN_2_OUT_ARGS LV1_1_IN_ARGS, LV1_2_OUT_ARGS +#define LV1_2_IN_2_OUT_ARGS LV1_2_IN_ARGS, LV1_2_OUT_ARGS +#define LV1_3_IN_2_OUT_ARGS LV1_3_IN_ARGS, LV1_2_OUT_ARGS +#define LV1_4_IN_2_OUT_ARGS LV1_4_IN_ARGS, LV1_2_OUT_ARGS +#define LV1_5_IN_2_OUT_ARGS LV1_5_IN_ARGS, LV1_2_OUT_ARGS +#define LV1_6_IN_2_OUT_ARGS LV1_6_IN_ARGS, LV1_2_OUT_ARGS +#define LV1_7_IN_2_OUT_ARGS LV1_7_IN_ARGS, LV1_2_OUT_ARGS + +#define LV1_0_IN_3_OUT_ARGS LV1_3_OUT_ARGS +#define LV1_1_IN_3_OUT_ARGS LV1_1_IN_ARGS, LV1_3_OUT_ARGS +#define LV1_2_IN_3_OUT_ARGS LV1_2_IN_ARGS, LV1_3_OUT_ARGS +#define LV1_3_IN_3_OUT_ARGS LV1_3_IN_ARGS, LV1_3_OUT_ARGS +#define LV1_4_IN_3_OUT_ARGS LV1_4_IN_ARGS, LV1_3_OUT_ARGS +#define LV1_5_IN_3_OUT_ARGS LV1_5_IN_ARGS, LV1_3_OUT_ARGS +#define LV1_6_IN_3_OUT_ARGS LV1_6_IN_ARGS, LV1_3_OUT_ARGS +#define LV1_7_IN_3_OUT_ARGS LV1_7_IN_ARGS, LV1_3_OUT_ARGS + +#define LV1_0_IN_4_OUT_ARGS LV1_4_OUT_ARGS +#define LV1_1_IN_4_OUT_ARGS LV1_1_IN_ARGS, LV1_4_OUT_ARGS +#define LV1_2_IN_4_OUT_ARGS LV1_2_IN_ARGS, LV1_4_OUT_ARGS +#define LV1_3_IN_4_OUT_ARGS LV1_3_IN_ARGS, LV1_4_OUT_ARGS +#define LV1_4_IN_4_OUT_ARGS LV1_4_IN_ARGS, LV1_4_OUT_ARGS +#define LV1_5_IN_4_OUT_ARGS LV1_5_IN_ARGS, LV1_4_OUT_ARGS +#define LV1_6_IN_4_OUT_ARGS LV1_6_IN_ARGS, LV1_4_OUT_ARGS +#define LV1_7_IN_4_OUT_ARGS LV1_7_IN_ARGS, LV1_4_OUT_ARGS + +#define LV1_0_IN_5_OUT_ARGS LV1_5_OUT_ARGS +#define LV1_1_IN_5_OUT_ARGS LV1_1_IN_ARGS, LV1_5_OUT_ARGS +#define LV1_2_IN_5_OUT_ARGS LV1_2_IN_ARGS, LV1_5_OUT_ARGS +#define LV1_3_IN_5_OUT_ARGS LV1_3_IN_ARGS, LV1_5_OUT_ARGS +#define LV1_4_IN_5_OUT_ARGS LV1_4_IN_ARGS, LV1_5_OUT_ARGS +#define LV1_5_IN_5_OUT_ARGS LV1_5_IN_ARGS, LV1_5_OUT_ARGS +#define LV1_6_IN_5_OUT_ARGS LV1_6_IN_ARGS, LV1_5_OUT_ARGS +#define LV1_7_IN_5_OUT_ARGS LV1_7_IN_ARGS, LV1_5_OUT_ARGS + +#define LV1_0_IN_6_OUT_ARGS LV1_6_OUT_ARGS +#define LV1_1_IN_6_OUT_ARGS LV1_1_IN_ARGS, LV1_6_OUT_ARGS +#define LV1_2_IN_6_OUT_ARGS LV1_2_IN_ARGS, LV1_6_OUT_ARGS +#define LV1_3_IN_6_OUT_ARGS LV1_3_IN_ARGS, LV1_6_OUT_ARGS +#define LV1_4_IN_6_OUT_ARGS LV1_4_IN_ARGS, LV1_6_OUT_ARGS +#define LV1_5_IN_6_OUT_ARGS LV1_5_IN_ARGS, LV1_6_OUT_ARGS +#define LV1_6_IN_6_OUT_ARGS LV1_6_IN_ARGS, LV1_6_OUT_ARGS +#define LV1_7_IN_6_OUT_ARGS LV1_7_IN_ARGS, LV1_6_OUT_ARGS + +#define LV1_0_IN_7_OUT_ARGS LV1_7_OUT_ARGS +#define LV1_1_IN_7_OUT_ARGS LV1_1_IN_ARGS, LV1_7_OUT_ARGS +#define LV1_2_IN_7_OUT_ARGS LV1_2_IN_ARGS, LV1_7_OUT_ARGS +#define LV1_3_IN_7_OUT_ARGS LV1_3_IN_ARGS, LV1_7_OUT_ARGS +#define LV1_4_IN_7_OUT_ARGS LV1_4_IN_ARGS, LV1_7_OUT_ARGS +#define LV1_5_IN_7_OUT_ARGS LV1_5_IN_ARGS, LV1_7_OUT_ARGS +#define LV1_6_IN_7_OUT_ARGS LV1_6_IN_ARGS, LV1_7_OUT_ARGS +#define LV1_7_IN_7_OUT_ARGS LV1_7_IN_ARGS, LV1_7_OUT_ARGS + +/* + * This LV1_CALL() macro is for use by callers. It expands into an + * inline call wrapper and an underscored HV call declaration. The + * wrapper can be used to instrument the lv1 call interface. The + * file lv1call.S defines its own LV1_CALL() macro to expand into + * the actual underscored call definition. + */ + +#if !defined(LV1_CALL) +#define LV1_CALL(name, in, out, num) \ + extern s64 _lv1_##name(LV1_##in##_IN_##out##_OUT_ARG_DECL); \ + static inline int lv1_##name(LV1_##in##_IN_##out##_OUT_ARG_DECL) \ + {return _lv1_##name(LV1_##in##_IN_##out##_OUT_ARGS);} +#endif + +#endif /* !defined(__ASSEMBLY__) */ + +/* lv1 call table */ + +LV1_CALL(allocate_memory, 4, 2, 0 ) +LV1_CALL(write_htab_entry, 4, 0, 1 ) +LV1_CALL(construct_virtual_address_space, 3, 2, 2 ) +LV1_CALL(invalidate_htab_entries, 5, 0, 3 ) +LV1_CALL(get_virtual_address_space_id_of_ppe, 1, 1, 4 ) +LV1_CALL(query_logical_partition_address_region_info, 1, 5, 6 ) +LV1_CALL(select_virtual_address_space, 1, 0, 7 ) +LV1_CALL(pause, 1, 0, 9 ) +LV1_CALL(destruct_virtual_address_space, 1, 0, 10 ) +LV1_CALL(configure_irq_state_bitmap, 3, 0, 11 ) +LV1_CALL(connect_irq_plug_ext, 5, 0, 12 ) +LV1_CALL(release_memory, 1, 0, 13 ) +LV1_CALL(disconnect_irq_plug_ext, 3, 0, 17 ) +LV1_CALL(construct_event_receive_port, 0, 1, 18 ) +LV1_CALL(destruct_event_receive_port, 1, 0, 19 ) +LV1_CALL(send_event_locally, 1, 0, 24 ) +LV1_CALL(end_of_interrupt, 1, 0, 27 ) +LV1_CALL(connect_irq_plug, 2, 0, 28 ) +LV1_CALL(disconnect_irq_plug, 1, 0, 29 ) +LV1_CALL(end_of_interrupt_ext, 3, 0, 30 ) +LV1_CALL(did_update_interrupt_mask, 2, 0, 31 ) +LV1_CALL(shutdown_logical_partition, 1, 0, 44 ) +LV1_CALL(destruct_logical_spe, 1, 0, 54 ) +LV1_CALL(construct_logical_spe, 7, 6, 57 ) +LV1_CALL(set_spe_interrupt_mask, 3, 0, 61 ) +LV1_CALL(set_spe_transition_notifier, 3, 0, 64 ) +LV1_CALL(disable_logical_spe, 2, 0, 65 ) +LV1_CALL(clear_spe_interrupt_status, 4, 0, 66 ) +LV1_CALL(get_spe_interrupt_status, 2, 1, 67 ) +LV1_CALL(get_logical_ppe_id, 0, 1, 69 ) +LV1_CALL(set_interrupt_mask, 5, 0, 73 ) +LV1_CALL(get_logical_partition_id, 0, 1, 74 ) +LV1_CALL(configure_execution_time_variable, 1, 0, 77 ) +LV1_CALL(get_spe_irq_outlet, 2, 1, 78 ) +LV1_CALL(set_spe_privilege_state_area_1_register, 3, 0, 79 ) +LV1_CALL(create_repository_node, 6, 0, 90 ) +LV1_CALL(get_repository_node_value, 5, 2, 91 ) +LV1_CALL(modify_repository_node_value, 6, 0, 92 ) +LV1_CALL(remove_repository_node, 4, 0, 93 ) +LV1_CALL(read_htab_entries, 2, 5, 95 ) +LV1_CALL(set_dabr, 2, 0, 96 ) +LV1_CALL(get_total_execution_time, 2, 1, 103 ) +LV1_CALL(construct_io_irq_outlet, 1, 1, 120 ) +LV1_CALL(destruct_io_irq_outlet, 1, 0, 121 ) +LV1_CALL(map_htab, 1, 1, 122 ) +LV1_CALL(unmap_htab, 1, 0, 123 ) +LV1_CALL(get_version_info, 0, 1, 127 ) +LV1_CALL(insert_htab_entry, 6, 3, 158 ) +LV1_CALL(read_virtual_uart, 3, 1, 162 ) +LV1_CALL(write_virtual_uart, 3, 1, 163 ) +LV1_CALL(set_virtual_uart_param, 3, 0, 164 ) +LV1_CALL(get_virtual_uart_param, 2, 1, 165 ) +LV1_CALL(configure_virtual_uart_irq, 1, 1, 166 ) +LV1_CALL(open_device, 3, 0, 170 ) +LV1_CALL(close_device, 2, 0, 171 ) +LV1_CALL(map_device_mmio_region, 5, 1, 172 ) +LV1_CALL(unmap_device_mmio_region, 3, 0, 173 ) +LV1_CALL(allocate_device_dma_region, 5, 1, 174 ) +LV1_CALL(free_device_dma_region, 3, 0, 175 ) +LV1_CALL(map_device_dma_region, 6, 0, 176 ) +LV1_CALL(unmap_device_dma_region, 4, 0, 177 ) +LV1_CALL(net_add_multicast_address, 4, 0, 185 ) +LV1_CALL(net_remove_multicast_address, 4, 0, 186 ) +LV1_CALL(net_start_tx_dma, 4, 0, 187 ) +LV1_CALL(net_stop_tx_dma, 3, 0, 188 ) +LV1_CALL(net_start_rx_dma, 4, 0, 189 ) +LV1_CALL(net_stop_rx_dma, 3, 0, 190 ) +LV1_CALL(net_set_interrupt_status_indicator, 4, 0, 191 ) +LV1_CALL(net_set_interrupt_mask, 4, 0, 193 ) +LV1_CALL(net_control, 6, 2, 194 ) +LV1_CALL(connect_interrupt_event_receive_port, 4, 0, 197 ) +LV1_CALL(disconnect_interrupt_event_receive_port, 4, 0, 198 ) +LV1_CALL(get_spe_all_interrupt_statuses, 1, 1, 199 ) +LV1_CALL(deconfigure_virtual_uart_irq, 0, 0, 202 ) +LV1_CALL(enable_logical_spe, 2, 0, 207 ) +LV1_CALL(gpu_open, 1, 0, 210 ) +LV1_CALL(gpu_close, 0, 0, 211 ) +LV1_CALL(gpu_device_map, 1, 2, 212 ) +LV1_CALL(gpu_device_unmap, 1, 0, 213 ) +LV1_CALL(gpu_memory_allocate, 5, 2, 214 ) +LV1_CALL(gpu_memory_free, 1, 0, 216 ) +LV1_CALL(gpu_context_allocate, 2, 5, 217 ) +LV1_CALL(gpu_context_free, 1, 0, 218 ) +LV1_CALL(gpu_context_iomap, 5, 0, 221 ) +LV1_CALL(gpu_context_attribute, 6, 0, 225 ) +LV1_CALL(gpu_context_intr, 1, 1, 227 ) +LV1_CALL(gpu_attribute, 5, 0, 228 ) +LV1_CALL(get_rtc, 0, 2, 232 ) +LV1_CALL(set_ppe_periodic_tracer_frequency, 1, 0, 240 ) +LV1_CALL(start_ppe_periodic_tracer, 5, 0, 241 ) +LV1_CALL(stop_ppe_periodic_tracer, 1, 1, 242 ) +LV1_CALL(storage_read, 6, 1, 245 ) +LV1_CALL(storage_write, 6, 1, 246 ) +LV1_CALL(storage_send_device_command, 6, 1, 248 ) +LV1_CALL(storage_get_async_status, 1, 2, 249 ) +LV1_CALL(storage_check_async_status, 2, 1, 254 ) +LV1_CALL(panic, 1, 0, 255 ) +LV1_CALL(construct_lpm, 6, 3, 140 ) +LV1_CALL(destruct_lpm, 1, 0, 141 ) +LV1_CALL(start_lpm, 1, 0, 142 ) +LV1_CALL(stop_lpm, 1, 1, 143 ) +LV1_CALL(copy_lpm_trace_buffer, 3, 1, 144 ) +LV1_CALL(add_lpm_event_bookmark, 5, 0, 145 ) +LV1_CALL(delete_lpm_event_bookmark, 3, 0, 146 ) +LV1_CALL(set_lpm_interrupt_mask, 3, 1, 147 ) +LV1_CALL(get_lpm_interrupt_status, 1, 1, 148 ) +LV1_CALL(set_lpm_general_control, 5, 2, 149 ) +LV1_CALL(set_lpm_interval, 3, 1, 150 ) +LV1_CALL(set_lpm_trigger_control, 3, 1, 151 ) +LV1_CALL(set_lpm_counter_control, 4, 1, 152 ) +LV1_CALL(set_lpm_group_control, 3, 1, 153 ) +LV1_CALL(set_lpm_debug_bus_control, 3, 1, 154 ) +LV1_CALL(set_lpm_counter, 5, 2, 155 ) +LV1_CALL(set_lpm_signal, 7, 0, 156 ) +LV1_CALL(set_lpm_spr_trigger, 2, 0, 157 ) + +#endif -- cgit v1.2.3-70-g09d2 From 82a527f0bd84977d7e85f15fb1f987c42cc0a68d Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 23 Nov 2006 00:46:53 +0100 Subject: [POWERPC] ps3: add feature bits Adds the needed firmware feature bits for the PS3. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann --- include/asm-powerpc/firmware.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h index fdf9aff7115..d1011b892d5 100644 --- a/include/asm-powerpc/firmware.h +++ b/include/asm-powerpc/firmware.h @@ -58,12 +58,17 @@ enum { FW_FEATURE_PSERIES_ALWAYS = 0, FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, + FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR, + FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR, FW_FEATURE_POSSIBLE = #ifdef CONFIG_PPC_PSERIES FW_FEATURE_PSERIES_POSSIBLE | #endif #ifdef CONFIG_PPC_ISERIES FW_FEATURE_ISERIES_POSSIBLE | +#endif +#ifdef CONFIG_PS3 + FW_FEATURE_PS3_POSSIBLE | #endif 0, FW_FEATURE_ALWAYS = @@ -72,6 +77,9 @@ enum { #endif #ifdef CONFIG_PPC_ISERIES FW_FEATURE_ISERIES_ALWAYS & +#endif +#ifdef CONFIG_PS3 + FW_FEATURE_PS3_ALWAYS & #endif FW_FEATURE_POSSIBLE, -- cgit v1.2.3-70-g09d2 From 6e74b38a7ffa6b69f287ae629aae91e725916e6f Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 23 Nov 2006 00:46:55 +0100 Subject: [POWERPC] ps3: add repository support Adds support for the PS3 repository. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann --- arch/powerpc/platforms/ps3/repository.c | 840 ++++++++++++++++++++++++++++++++ include/asm-powerpc/ps3.h | 139 ++++++ 2 files changed, 979 insertions(+) create mode 100644 arch/powerpc/platforms/ps3/repository.c (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c new file mode 100644 index 00000000000..273a0d621bd --- /dev/null +++ b/arch/powerpc/platforms/ps3/repository.c @@ -0,0 +1,840 @@ +/* + * PS3 repository routines. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +enum ps3_vendor_id { + PS3_VENDOR_ID_NONE = 0, + PS3_VENDOR_ID_SONY = 0x8000000000000000UL, +}; + +enum ps3_lpar_id { + PS3_LPAR_ID_CURRENT = 0, + PS3_LPAR_ID_PME = 1, +}; + +#define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__) +static void _dump_field(const char *hdr, u64 n, const char* func, int line) +{ +#if defined(DEBUG) + char s[16]; + const char *const in = (const char *)&n; + unsigned int i; + + for (i = 0; i < 8; i++) + s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.'; + s[i] = 0; + + pr_debug("%s:%d: %s%016lx : %s\n", func, line, hdr, n, s); +#endif +} + +#define dump_node_name(_a, _b, _c, _d, _e) \ + _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__) +static void _dump_node_name (unsigned int lpar_id, u64 n1, u64 n2, u64 n3, + u64 n4, const char* func, int line) +{ + pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); + _dump_field("n1: ", n1, func, line); + _dump_field("n2: ", n2, func, line); + _dump_field("n3: ", n3, func, line); + _dump_field("n4: ", n4, func, line); +} + +#define dump_node(_a, _b, _c, _d, _e, _f, _g) \ + _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) +static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, + u64 v1, u64 v2, const char* func, int line) +{ + pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); + _dump_field("n1: ", n1, func, line); + _dump_field("n2: ", n2, func, line); + _dump_field("n3: ", n3, func, line); + _dump_field("n4: ", n4, func, line); + pr_debug("%s:%d: v1: %016lx\n", func, line, v1); + pr_debug("%s:%d: v2: %016lx\n", func, line, v2); +} + +/** + * make_first_field - Make the first field of a repository node name. + * @text: Text portion of the field. + * @index: Numeric index portion of the field. Use zero for 'don't care'. + * + * This routine sets the vendor id to zero (non-vendor specific). + * Returns field value. + */ + +static u64 make_first_field(const char *text, u64 index) +{ + u64 n; + + strncpy((char *)&n, text, 8); + return PS3_VENDOR_ID_NONE + (n >> 32) + index; +} + +/** + * make_field - Make subsequent fields of a repository node name. + * @text: Text portion of the field. Use "" for 'don't care'. + * @index: Numeric index portion of the field. Use zero for 'don't care'. + * + * Returns field value. + */ + +static u64 make_field(const char *text, u64 index) +{ + u64 n; + + strncpy((char *)&n, text, 8); + return n + index; +} + +/** + * read_node - Read a repository node from raw fields. + * @n1: First field of node name. + * @n2: Second field of node name. Use zero for 'don't care'. + * @n3: Third field of node name. Use zero for 'don't care'. + * @n4: Fourth field of node name. Use zero for 'don't care'. + * @v1: First repository value (high word). + * @v2: Second repository value (low word). Optional parameter, use zero + * for 'don't care'. + */ + +static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, + u64 *_v1, u64 *_v2) +{ + int result; + u64 v1; + u64 v2; + + if (lpar_id == PS3_LPAR_ID_CURRENT) { + u64 id; + lv1_get_logical_partition_id(&id); + lpar_id = id; + } + + result = lv1_get_repository_node_value(lpar_id, n1, n2, n3, n4, &v1, + &v2); + + if (result) { + pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n", + __func__, __LINE__, ps3_result(result)); + dump_node_name(lpar_id, n1, n2, n3, n4); + return result; + } + + dump_node(lpar_id, n1, n2, n3, n4, v1, v2); + + if (_v1) + *_v1 = v1; + if (_v2) + *_v2 = v2; + + if (v1 && !_v1) + pr_debug("%s:%d: warning: discarding non-zero v1: %016lx\n", + __func__, __LINE__, v1); + if (v2 && !_v2) + pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n", + __func__, __LINE__, v2); + + return result; +} + +int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, + u64 *value) +{ + return read_node(PS3_LPAR_ID_PME, + make_first_field("bus", bus_index), + make_field(bus_str, 0), + 0, 0, + value, 0); +} + +int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id) +{ + int result; + u64 v1; + u64 v2; /* unused */ + + result = read_node(PS3_LPAR_ID_PME, + make_first_field("bus", bus_index), + make_field("id", 0), + 0, 0, + &v1, &v2); + *bus_id = v1; + return result; +} + +int ps3_repository_read_bus_type(unsigned int bus_index, + enum ps3_bus_type *bus_type) +{ + int result; + u64 v1; + + result = read_node(PS3_LPAR_ID_PME, + make_first_field("bus", bus_index), + make_field("type", 0), + 0, 0, + &v1, 0); + *bus_type = v1; + return result; +} + +int ps3_repository_read_bus_num_dev(unsigned int bus_index, + unsigned int *num_dev) +{ + int result; + u64 v1; + + result = read_node(PS3_LPAR_ID_PME, + make_first_field("bus", bus_index), + make_field("num_dev", 0), + 0, 0, + &v1, 0); + *num_dev = v1; + return result; +} + +int ps3_repository_read_dev_str(unsigned int bus_index, + unsigned int dev_index, const char *dev_str, u64 *value) +{ + return read_node(PS3_LPAR_ID_PME, + make_first_field("bus", bus_index), + make_field("dev", dev_index), + make_field(dev_str, 0), + 0, + value, 0); +} + +int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, + unsigned int *dev_id) +{ + int result; + u64 v1; + + result = read_node(PS3_LPAR_ID_PME, + make_first_field("bus", bus_index), + make_field("dev", dev_index), + make_field("id", 0), + 0, + &v1, 0); + *dev_id = v1; + return result; +} + +int ps3_repository_read_dev_type(unsigned int bus_index, + unsigned int dev_index, enum ps3_dev_type *dev_type) +{ + int result; + u64 v1; + + result = read_node(PS3_LPAR_ID_PME, + make_first_field("bus", bus_index), + make_field("dev", dev_index), + make_field("type", 0), + 0, + &v1, 0); + *dev_type = v1; + return result; +} + +int ps3_repository_read_dev_intr(unsigned int bus_index, + unsigned int dev_index, unsigned int intr_index, + unsigned int *intr_type, unsigned int* interrupt_id) +{ + int result; + u64 v1; + u64 v2; + + result = read_node(PS3_LPAR_ID_PME, + make_first_field("bus", bus_index), + make_field("dev", dev_index), + make_field("intr", intr_index), + 0, + &v1, &v2); + *intr_type = v1; + *interrupt_id = v2; + return result; +} + +int ps3_repository_read_dev_reg_type(unsigned int bus_index, + unsigned int dev_index, unsigned int reg_index, unsigned int *reg_type) +{ + int result; + u64 v1; + + result = read_node(PS3_LPAR_ID_PME, + make_first_field("bus", bus_index), + make_field("dev", dev_index), + make_field("reg", reg_index), + make_field("type", 0), + &v1, 0); + *reg_type = v1; + return result; +} + +int ps3_repository_read_dev_reg_addr(unsigned int bus_index, + unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len) +{ + return read_node(PS3_LPAR_ID_PME, + make_first_field("bus", bus_index), + make_field("dev", dev_index), + make_field("reg", reg_index), + make_field("data", 0), + bus_addr, len); +} + +int ps3_repository_read_dev_reg(unsigned int bus_index, + unsigned int dev_index, unsigned int reg_index, unsigned int *reg_type, + u64 *bus_addr, u64 *len) +{ + int result = ps3_repository_read_dev_reg_type(bus_index, dev_index, + reg_index, reg_type); + return result ? result + : ps3_repository_read_dev_reg_addr(bus_index, dev_index, + reg_index, bus_addr, len); +} + +#if defined(DEBUG) +int ps3_repository_dump_resource_info(unsigned int bus_index, + unsigned int dev_index) +{ + int result = 0; + unsigned int res_index; + + pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, + bus_index, dev_index); + + for (res_index = 0; res_index < 10; res_index++) { + enum ps3_interrupt_type intr_type; + unsigned int interrupt_id; + + result = ps3_repository_read_dev_intr(bus_index, dev_index, + res_index, &intr_type, &interrupt_id); + + if (result) { + if (result != LV1_NO_ENTRY) + pr_debug("%s:%d ps3_repository_read_dev_intr" + " (%u:%u) failed\n", __func__, __LINE__, + bus_index, dev_index); + break; + } + + pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", + __func__, __LINE__, bus_index, dev_index, intr_type, + interrupt_id); + } + + for (res_index = 0; res_index < 10; res_index++) { + enum ps3_region_type reg_type; + u64 bus_addr; + u64 len; + + result = ps3_repository_read_dev_reg(bus_index, dev_index, + res_index, ®_type, &bus_addr, &len); + + if (result) { + if (result != LV1_NO_ENTRY) + pr_debug("%s:%d ps3_repository_read_dev_reg" + " (%u:%u) failed\n", __func__, __LINE__, + bus_index, dev_index); + break; + } + + pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", + __func__, __LINE__, bus_index, dev_index, reg_type, + bus_addr, len); + } + + pr_debug(" <- %s:%d\n", __func__, __LINE__); + return result; +} + +static int dump_device_info(unsigned int bus_index, unsigned int num_dev) +{ + int result = 0; + unsigned int dev_index; + + pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index); + + for (dev_index = 0; dev_index < num_dev; dev_index++) { + enum ps3_dev_type dev_type; + unsigned int dev_id; + + result = ps3_repository_read_dev_type(bus_index, dev_index, + &dev_type); + + if (result) { + pr_debug("%s:%d ps3_repository_read_dev_type" + " (%u:%u) failed\n", __func__, __LINE__, + bus_index, dev_index); + break; + } + + result = ps3_repository_read_dev_id(bus_index, dev_index, + &dev_id); + + if (result) { + pr_debug("%s:%d ps3_repository_read_dev_id" + " (%u:%u) failed\n", __func__, __LINE__, + bus_index, dev_index); + continue; + } + + pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, + __LINE__, bus_index, dev_index, dev_type, dev_id); + + ps3_repository_dump_resource_info(bus_index, dev_index); + } + + pr_debug(" <- %s:%d\n", __func__, __LINE__); + return result; +} + +int ps3_repository_dump_bus_info(void) +{ + int result = 0; + unsigned int bus_index; + + pr_debug(" -> %s:%d\n", __func__, __LINE__); + + for (bus_index = 0; bus_index < 10; bus_index++) { + enum ps3_bus_type bus_type; + unsigned int bus_id; + unsigned int num_dev; + + result = ps3_repository_read_bus_type(bus_index, &bus_type); + + if (result) { + pr_debug("%s:%d read_bus_type(%u) failed\n", + __func__, __LINE__, bus_index); + break; + } + + result = ps3_repository_read_bus_id(bus_index, &bus_id); + + if (result) { + pr_debug("%s:%d read_bus_id(%u) failed\n", + __func__, __LINE__, bus_index); + continue; + } + + if (bus_index != bus_id) + pr_debug("%s:%d bus_index != bus_id\n", + __func__, __LINE__); + + result = ps3_repository_read_bus_num_dev(bus_index, &num_dev); + + if (result) { + pr_debug("%s:%d read_bus_num_dev(%u) failed\n", + __func__, __LINE__, bus_index); + continue; + } + + pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", + __func__, __LINE__, bus_index, bus_type, bus_id, + num_dev); + + dump_device_info(bus_index, num_dev); + } + + pr_debug(" <- %s:%d\n", __func__, __LINE__); + return result; +} +#endif /* defined(DEBUG) */ + +static int find_device(unsigned int bus_index, unsigned int num_dev, + unsigned int start_dev_index, enum ps3_dev_type dev_type, + struct ps3_repository_device *dev) +{ + int result = 0; + unsigned int dev_index; + + pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type); + + dev->dev_index = UINT_MAX; + + for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) { + enum ps3_dev_type x; + + result = ps3_repository_read_dev_type(bus_index, dev_index, + &x); + + if (result) { + pr_debug("%s:%d read_dev_type failed\n", + __func__, __LINE__); + return result; + } + + if (x == dev_type) + break; + } + + BUG_ON(dev_index == num_dev); + + pr_debug("%s:%d: found dev_type %u at dev_index %u\n", + __func__, __LINE__, dev_type, dev_index); + + result = ps3_repository_read_dev_id(bus_index, dev_index, + &dev->did.dev_id); + + if (result) { + pr_debug("%s:%d read_dev_id failed\n", + __func__, __LINE__); + return result; + } + + dev->dev_index = dev_index; + + pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__, + dev->did.dev_id); + + return result; +} + +int ps3_repository_find_device (enum ps3_bus_type bus_type, + enum ps3_dev_type dev_type, + const struct ps3_repository_device *start_dev, + struct ps3_repository_device *dev) +{ + int result = 0; + unsigned int bus_index; + unsigned int num_dev; + + pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__, + bus_type, dev_type); + + dev->bus_index = UINT_MAX; + + for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10; + bus_index++) { + enum ps3_bus_type x; + + result = ps3_repository_read_bus_type(bus_index, &x); + + if (result) { + pr_debug("%s:%d read_bus_type failed\n", + __func__, __LINE__); + return result; + } + if (x == bus_type) + break; + } + + BUG_ON(bus_index == 10); + + pr_debug("%s:%d: found bus_type %u at bus_index %u\n", + __func__, __LINE__, bus_type, bus_index); + + result = ps3_repository_read_bus_num_dev(bus_index, &num_dev); + + if (result) { + pr_debug("%s:%d read_bus_num_dev failed\n", + __func__, __LINE__); + return result; + } + + result = find_device(bus_index, num_dev, start_dev + ? start_dev->dev_index + 1 : 0, dev_type, dev); + + if (result) { + pr_debug("%s:%d get_did failed\n", __func__, __LINE__); + return result; + } + + result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id); + + if (result) { + pr_debug("%s:%d read_bus_id failed\n", + __func__, __LINE__); + return result; + } + + dev->bus_index = bus_index; + + pr_debug("%s:%d found: bus_id %u, dev_id %u\n", + __func__, __LINE__, dev->did.bus_id, dev->did.dev_id); + + return result; +} + +int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, + enum ps3_interrupt_type intr_type, unsigned int *interrupt_id) +{ + int result = 0; + unsigned int res_index; + + pr_debug("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type); + + *interrupt_id = UINT_MAX; + + for (res_index = 0; res_index < 10; res_index++) { + enum ps3_interrupt_type t; + unsigned int id; + + result = ps3_repository_read_dev_intr(dev->bus_index, + dev->dev_index, res_index, &t, &id); + + if (result) { + pr_debug("%s:%d read_dev_intr failed\n", + __func__, __LINE__); + return result; + } + + if (t == intr_type) { + *interrupt_id = id; + break; + } + } + + BUG_ON(res_index == 10); + + pr_debug("%s:%d: found intr_type %u at res_index %u\n", + __func__, __LINE__, intr_type, res_index); + + return result; +} + +int ps3_repository_find_region(const struct ps3_repository_device *dev, + enum ps3_region_type reg_type, u64 *bus_addr, u64 *len) +{ + int result = 0; + unsigned int res_index; + + pr_debug("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type); + + *bus_addr = *len = 0; + + for (res_index = 0; res_index < 10; res_index++) { + enum ps3_region_type t; + u64 a; + u64 l; + + result = ps3_repository_read_dev_reg(dev->bus_index, + dev->dev_index, res_index, &t, &a, &l); + + if (result) { + pr_debug("%s:%d read_dev_reg failed\n", + __func__, __LINE__); + return result; + } + + if (t == reg_type) { + *bus_addr = a; + *len = l; + break; + } + } + + BUG_ON(res_index == 10); + + pr_debug("%s:%d: found reg_type %u at res_index %u\n", + __func__, __LINE__, reg_type, res_index); + + return result; +} + +int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size) +{ + return read_node(PS3_LPAR_ID_CURRENT, + make_first_field("bi", 0), + make_field("pu", 0), + ppe_id, + make_field("rm_size", 0), + rm_size, 0); +} + +int ps3_repository_read_region_total(u64 *region_total) +{ + return read_node(PS3_LPAR_ID_CURRENT, + make_first_field("bi", 0), + make_field("rgntotal", 0), + 0, 0, + region_total, 0); +} + +/** + * ps3_repository_read_mm_info - Read mm info for single pu system. + * @rm_base: Real mode memory base address. + * @rm_size: Real mode memory size. + * @region_total: Maximum memory region size. + */ + +int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total) +{ + int result; + u64 ppe_id; + + lv1_get_logical_ppe_id(&ppe_id); + *rm_base = 0; + result = ps3_repository_read_rm_size(ppe_id, rm_size); + return result ? result + : ps3_repository_read_region_total(region_total); +} + +/** + * ps3_repository_read_num_spu_reserved - Number of physical spus reserved. + * @num_spu: Number of physical spus. + */ + +int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved) +{ + int result; + u64 v1; + + result = read_node(PS3_LPAR_ID_CURRENT, + make_first_field("bi", 0), + make_field("spun", 0), + 0, 0, + &v1, 0); + *num_spu_reserved = v1; + return result; +} + +/** + * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations. + * @num_resource_id: Number of spu resource ids. + */ + +int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id) +{ + int result; + u64 v1; + + result = read_node(PS3_LPAR_ID_CURRENT, + make_first_field("bi", 0), + make_field("spursvn", 0), + 0, 0, + &v1, 0); + *num_resource_id = v1; + return result; +} + +/** + * ps3_repository_read_spu_resource_id - spu resource reservation id value. + * @res_index: Resource reservation index. + * @resource_type: Resource reservation type. + * @resource_id: Resource reservation id. + */ + +int ps3_repository_read_spu_resource_id(unsigned int res_index, + enum ps3_spu_resource_type* resource_type, unsigned int *resource_id) +{ + int result; + u64 v1; + u64 v2; + + result = read_node(PS3_LPAR_ID_CURRENT, + make_first_field("bi", 0), + make_field("spursv", 0), + res_index, + 0, + &v1, &v2); + *resource_type = v1; + *resource_id = v2; + return result; +} + +int ps3_repository_read_boot_dat_address(u64 *address) +{ + return read_node(PS3_LPAR_ID_CURRENT, + make_first_field("bi", 0), + make_field("boot_dat", 0), + make_field("address", 0), + 0, + address, 0); +} + +int ps3_repository_read_boot_dat_size(unsigned int *size) +{ + int result; + u64 v1; + + result = read_node(PS3_LPAR_ID_CURRENT, + make_first_field("bi", 0), + make_field("boot_dat", 0), + make_field("size", 0), + 0, + &v1, 0); + *size = v1; + return result; +} + +/** + * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area. + * address: lpar address of cell_ext_os_area + * @size: size of cell_ext_os_area + */ + +int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size) +{ + int result; + + *size = 0; + result = ps3_repository_read_boot_dat_address(lpar_addr); + return result ? result + : ps3_repository_read_boot_dat_size(size); +} + +int ps3_repository_read_num_be(unsigned int *num_be) +{ + int result; + u64 v1; + + result = read_node(PS3_LPAR_ID_PME, + make_first_field("ben", 0), + 0, + 0, + 0, + &v1, 0); + *num_be = v1; + return result; +} + +int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id) +{ + return read_node(PS3_LPAR_ID_PME, + make_first_field("be", be_index), + 0, + 0, + 0, + node_id, 0); +} + +int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq) +{ + return read_node(PS3_LPAR_ID_PME, + make_first_field("be", 0), + node_id, + make_field("clock", 0), + 0, + tb_freq, 0); +} + +int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) +{ + int result; + u64 node_id; + + *tb_freq = 0; + result = ps3_repository_read_be_node_id(0, &node_id); + return result ? result + : ps3_repository_read_tb_freq(node_id, tb_freq); +} diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h index d0109ffac50..eb4bbb6cff5 100644 --- a/include/asm-powerpc/ps3.h +++ b/include/asm-powerpc/ps3.h @@ -247,4 +247,143 @@ static inline const char* ps3_result(int result) #endif } +/* repository bus info */ + +enum ps3_bus_type { + PS3_BUS_TYPE_SB = 4, + PS3_BUS_TYPE_STORAGE = 5, +}; + +enum ps3_dev_type { + PS3_DEV_TYPE_SB_GELIC = 3, + PS3_DEV_TYPE_SB_USB = 4, + PS3_DEV_TYPE_SB_GPIO = 6, +}; + +int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, + u64 *value); +int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id); +int ps3_repository_read_bus_type(unsigned int bus_index, + enum ps3_bus_type *bus_type); +int ps3_repository_read_bus_num_dev(unsigned int bus_index, + unsigned int *num_dev); + +/* repository bus device info */ + +enum ps3_interrupt_type { + PS3_INTERRUPT_TYPE_EVENT_PORT = 2, + PS3_INTERRUPT_TYPE_SB_OHCI = 3, + PS3_INTERRUPT_TYPE_SB_EHCI = 4, + PS3_INTERRUPT_TYPE_OTHER = 5, +}; + +enum ps3_region_type { + PS3_REGION_TYPE_SB_OHCI = 3, + PS3_REGION_TYPE_SB_EHCI = 4, + PS3_REGION_TYPE_SB_GPIO = 5, +}; + +int ps3_repository_read_dev_str(unsigned int bus_index, + unsigned int dev_index, const char *dev_str, u64 *value); +int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, + unsigned int *dev_id); +int ps3_repository_read_dev_type(unsigned int bus_index, + unsigned int dev_index, enum ps3_dev_type *dev_type); +int ps3_repository_read_dev_intr(unsigned int bus_index, + unsigned int dev_index, unsigned int intr_index, + enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id); +int ps3_repository_read_dev_reg_type(unsigned int bus_index, + unsigned int dev_index, unsigned int reg_index, + enum ps3_region_type *reg_type); +int ps3_repository_read_dev_reg_addr(unsigned int bus_index, + unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, + u64 *len); +int ps3_repository_read_dev_reg(unsigned int bus_index, + unsigned int dev_index, unsigned int reg_index, + enum ps3_region_type *reg_type, u64 *bus_addr, u64 *len); + +/* repository bus enumerators */ + +struct ps3_repository_device { + unsigned int bus_index; + unsigned int dev_index; + struct ps3_device_id did; +}; + +int ps3_repository_find_device(enum ps3_bus_type bus_type, + enum ps3_dev_type dev_type, + const struct ps3_repository_device *start_dev, + struct ps3_repository_device *dev); +static inline int ps3_repository_find_first_device( + enum ps3_bus_type bus_type, enum ps3_dev_type dev_type, + struct ps3_repository_device *dev) +{ + return ps3_repository_find_device(bus_type, dev_type, NULL, dev); +} +int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, + enum ps3_interrupt_type intr_type, unsigned int *interrupt_id); +int ps3_repository_find_region(const struct ps3_repository_device *dev, + enum ps3_region_type reg_type, u64 *bus_addr, u64 *len); + +/* repository block device info */ + +int ps3_repository_read_dev_port(unsigned int bus_index, + unsigned int dev_index, u64 *port); +int ps3_repository_read_dev_blk_size(unsigned int bus_index, + unsigned int dev_index, u64 *blk_size); +int ps3_repository_read_dev_num_blocks(unsigned int bus_index, + unsigned int dev_index, u64 *num_blocks); +int ps3_repository_read_dev_num_regions(unsigned int bus_index, + unsigned int dev_index, unsigned int *num_regions); +int ps3_repository_read_dev_region_id(unsigned int bus_index, + unsigned int dev_index, unsigned int region_index, + unsigned int *region_id); +int ps3_repository_read_dev_region_size(unsigned int bus_index, + unsigned int dev_index, unsigned int region_index, u64 *region_size); +int ps3_repository_read_dev_region_start(unsigned int bus_index, + unsigned int dev_index, unsigned int region_index, u64 *region_start); + +/* repository pu and memory info */ + +int ps3_repository_read_num_pu(unsigned int *num_pu); +int ps3_repository_read_ppe_id(unsigned int *pu_index, unsigned int *ppe_id); +int ps3_repository_read_rm_base(unsigned int ppe_id, u64 *rm_base); +int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size); +int ps3_repository_read_region_total(u64 *region_total); +int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, + u64 *region_total); + +/* repository pme info */ + +int ps3_repository_read_num_be(unsigned int *num_be); +int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id); +int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq); +int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq); + +/* repository 'Other OS' area */ + +int ps3_repository_read_boot_dat_addr(u64 *lpar_addr); +int ps3_repository_read_boot_dat_size(unsigned int *size); +int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size); + +/* repository spu info */ + +/** + * enum spu_resource_type - Type of spu resource. + * @spu_resource_type_shared: Logical spu is shared with other partions. + * @spu_resource_type_exclusive: Logical spu is not shared with other partions. + * + * Returned by ps3_repository_read_spu_resource_id(). + */ + +enum ps3_spu_resource_type { + PS3_SPU_RESOURCE_TYPE_SHARED = 0, + PS3_SPU_RESOURCE_TYPE_EXCLUSIVE = 0x8000000000000000UL, +}; + +int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved); +int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id); +int ps3_repository_read_spu_resource_id(unsigned int res_index, + enum ps3_spu_resource_type* resource_type, unsigned int *resource_id); + #endif -- cgit v1.2.3-70-g09d2 From 261efc3f178c8c5b55d76208aee1f39ce247f723 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 23 Nov 2006 00:46:57 +0100 Subject: [POWERPC] ps3: add lpar addressing Adds some needed bits for a config option PS3_USE_LPAR_ADDR that disables the PS3 lpar address translation mechanism. This is a currently needed workaround for limitations in the design of the generic cell spu support. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann --- arch/powerpc/platforms/ps3/Kconfig | 11 +++++++++++ include/asm-powerpc/sparsemem.h | 6 ++++++ 2 files changed, 17 insertions(+) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index f023719f645..451bfcd5502 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -29,4 +29,15 @@ config PS3_DYNAMIC_DMA This support is mainly for Linux kernel development. If unsure, say N. +config PS3_USE_LPAR_ADDR + depends on PPC_PS3 && EXPERIMENTAL + bool "PS3 use lpar address space" + default y + help + This option is solely for experimentation by experts. Disables + translation of lpar addresses. SPE support currently won't work + without this set to y. + + If you have any doubt, choose the default y. + endmenu diff --git a/include/asm-powerpc/sparsemem.h b/include/asm-powerpc/sparsemem.h index 38b1ea3b58f..48ad807a0b8 100644 --- a/include/asm-powerpc/sparsemem.h +++ b/include/asm-powerpc/sparsemem.h @@ -9,8 +9,14 @@ * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space */ #define SECTION_SIZE_BITS 24 + +#if defined(CONFIG_PS3_USE_LPAR_ADDR) +#define MAX_PHYSADDR_BITS 47 +#define MAX_PHYSMEM_BITS 47 +#else #define MAX_PHYSADDR_BITS 44 #define MAX_PHYSMEM_BITS 44 +#endif #ifdef CONFIG_MEMORY_HOTPLUG extern void create_section_mapping(unsigned long start, unsigned long end); -- cgit v1.2.3-70-g09d2 From a3d4d6435b56eb0b6ff4f88e5a513cfccfb3e770 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 23 Nov 2006 00:47:00 +0100 Subject: [POWERPC] ps3: add ps3 platform system bus support Adds a PS3 system bus driver. This system bus is a virtual bus used to present the PS3 system devices in the LDM. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann --- drivers/Makefile | 1 + drivers/ps3/Makefile | 1 + drivers/ps3/system-bus.c | 358 ++++++++++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/ps3.h | 73 ++++++++++ 4 files changed, 433 insertions(+) create mode 100644 drivers/ps3/Makefile create mode 100644 drivers/ps3/system-bus.c (limited to 'include/asm-powerpc') diff --git a/drivers/Makefile b/drivers/Makefile index 4ac14dab307..a47d2483b7a 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -77,3 +77,4 @@ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ obj-$(CONFIG_GENERIC_TIME) += clocksource/ obj-$(CONFIG_DMA_ENGINE) += dma/ +obj-$(CONFIG_PS3) += ps3/ diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile new file mode 100644 index 00000000000..b52d547b7a7 --- /dev/null +++ b/drivers/ps3/Makefile @@ -0,0 +1 @@ +obj-y += system-bus.o diff --git a/drivers/ps3/system-bus.c b/drivers/ps3/system-bus.c new file mode 100644 index 00000000000..e19992c4db4 --- /dev/null +++ b/drivers/ps3/system-bus.c @@ -0,0 +1,358 @@ +/* + * PS3 system bus driver. + * + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__) +static void _dump_mmio_region(const struct ps3_mmio_region* r, + const char* func, int line) +{ + pr_debug("%s:%d: dev %u:%u\n", func, line, r->did.bus_id, + r->did.dev_id); + pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); + pr_debug("%s:%d: len %lxh\n", func, line, r->len); + pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr); +} + +int ps3_mmio_region_create(struct ps3_mmio_region *r) +{ + int result; + + result = lv1_map_device_mmio_region(r->did.bus_id, r->did.dev_id, + r->bus_addr, r->len, r->page_size, &r->lpar_addr); + + if (result) { + pr_debug("%s:%d: lv1_map_device_mmio_region failed: %s\n", + __func__, __LINE__, ps3_result(result)); + r->lpar_addr = r->len = r->bus_addr = 0; + } + + dump_mmio_region(r); + return result; +} + +int ps3_free_mmio_region(struct ps3_mmio_region *r) +{ + int result; + + result = lv1_unmap_device_mmio_region(r->did.bus_id, r->did.dev_id, + r->bus_addr); + + if (result) + pr_debug("%s:%d: lv1_unmap_device_mmio_region failed: %s\n", + __func__, __LINE__, ps3_result(result)); + + r->lpar_addr = r->len = r->bus_addr = 0; + return result; +} + +static int ps3_system_bus_match(struct device *_dev, + struct device_driver *_drv) +{ + int result; + struct ps3_system_bus_driver *drv = to_ps3_system_bus_driver(_drv); + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + + result = dev->match_id == drv->match_id; + + pr_info("%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, __LINE__, + dev->match_id, dev->core.bus_id, drv->match_id, drv->core.name, + (result ? "match" : "miss")); + return result; +} + +static int ps3_system_bus_probe(struct device *_dev) +{ + int result; + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + struct ps3_system_bus_driver *drv = + to_ps3_system_bus_driver(_dev->driver); + + result = lv1_open_device(dev->did.bus_id, dev->did.dev_id, 0); + + if (result) { + pr_debug("%s:%d: lv1_open_device failed (%d)\n", + __func__, __LINE__, result); + result = -EACCES; + goto clean_none; + } + + if (dev->d_region->did.bus_id) { + result = ps3_dma_region_create(dev->d_region); + + if (result) { + pr_debug("%s:%d: ps3_dma_region_create failed (%d)\n", + __func__, __LINE__, result); + BUG_ON("check region type"); + result = -EINVAL; + goto clean_device; + } + } + + BUG_ON(!drv); + + if (drv->probe) + result = drv->probe(dev); + else + pr_info("%s:%d: %s no probe method\n", __func__, __LINE__, + dev->core.bus_id); + + if (result) { + pr_debug("%s:%d: drv->probe failed\n", __func__, __LINE__); + goto clean_dma; + } + + return result; + +clean_dma: + ps3_dma_region_free(dev->d_region); +clean_device: + lv1_close_device(dev->did.bus_id, dev->did.dev_id); +clean_none: + return result; +} + +static int ps3_system_bus_remove(struct device *_dev) +{ + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + struct ps3_system_bus_driver *drv = + to_ps3_system_bus_driver(_dev->driver); + + if (drv->remove) + drv->remove(dev); + else + pr_info("%s:%d: %s no remove method\n", __func__, __LINE__, + dev->core.bus_id); + + ps3_dma_region_free(dev->d_region); + ps3_free_mmio_region(dev->m_region); + lv1_close_device(dev->did.bus_id, dev->did.dev_id); + + return 0; +} + +struct bus_type ps3_system_bus_type = { + .name = "ps3_system_bus", + .match = ps3_system_bus_match, + .probe = ps3_system_bus_probe, + .remove = ps3_system_bus_remove, +}; + +int __init ps3_system_bus_init(void) +{ + int result; + + result = bus_register(&ps3_system_bus_type); + BUG_ON(result); + return result; +} + +core_initcall(ps3_system_bus_init); + +/* Allocates a contiguous real buffer and creates mappings over it. + * Returns the virtual address of the buffer and sets dma_handle + * to the dma address (mapping) of the first page. + */ + +static void * ps3_alloc_coherent(struct device *_dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ + int result; + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + unsigned long virt_addr; + + BUG_ON(!dev->d_region->bus_addr); + + flag &= ~(__GFP_DMA | __GFP_HIGHMEM); + flag |= __GFP_ZERO; + + virt_addr = __get_free_pages(flag, get_order(size)); + + if (!virt_addr) { + pr_debug("%s:%d: get_free_pages failed\n", __func__, __LINE__); + goto clean_none; + } + + result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle); + + if (result) { + pr_debug("%s:%d: ps3_dma_map failed (%d)\n", + __func__, __LINE__, result); + BUG_ON("check region type"); + goto clean_alloc; + } + + return (void*)virt_addr; + +clean_alloc: + free_pages(virt_addr, get_order(size)); +clean_none: + dma_handle = NULL; + return NULL; +} + +static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, + dma_addr_t dma_handle) +{ + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + + ps3_dma_unmap(dev->d_region, dma_handle, size); + free_pages((unsigned long)vaddr, get_order(size)); +} + +/* Creates TCEs for a user provided buffer. The user buffer must be + * contiguous real kernel storage (not vmalloc). The address of the buffer + * passed here is the kernel (virtual) address of the buffer. The buffer + * need not be page aligned, the dma_addr_t returned will point to the same + * byte within the page as vaddr. + */ + +static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size, + enum dma_data_direction direction) +{ + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + int result; + unsigned long bus_addr; + + result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, + &bus_addr); + + if (result) { + pr_debug("%s:%d: ps3_dma_map failed (%d)\n", + __func__, __LINE__, result); + } + + return bus_addr; +} + +static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction direction) +{ + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + int result; + + result = ps3_dma_unmap(dev->d_region, dma_addr, size); + + if (result) { + pr_debug("%s:%d: ps3_dma_unmap failed (%d)\n", + __func__, __LINE__, result); + } +} + +static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) +{ +#if defined(CONFIG_PS3_DYNAMIC_DMA) + BUG_ON("do"); +#endif + return 0; +} + +static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) +{ +#if defined(CONFIG_PS3_DYNAMIC_DMA) + BUG_ON("do"); +#endif +} + +static int ps3_dma_supported(struct device *_dev, u64 mask) +{ + return 1; +} + +static struct dma_mapping_ops ps3_dma_ops = { + .alloc_coherent = ps3_alloc_coherent, + .free_coherent = ps3_free_coherent, + .map_single = ps3_map_single, + .unmap_single = ps3_unmap_single, + .map_sg = ps3_map_sg, + .unmap_sg = ps3_unmap_sg, + .dma_supported = ps3_dma_supported +}; + +/** + * ps3_system_bus_release_device - remove a device from the system bus + */ + +static void ps3_system_bus_release_device(struct device *_dev) +{ + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + kfree(dev); +} + +/** + * ps3_system_bus_device_register - add a device to the system bus + * + * ps3_system_bus_device_register() expects the dev object to be allocated + * dynamically by the caller. The system bus takes ownership of the dev + * object and frees the object in ps3_system_bus_release_device(). + */ + +int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) +{ + int result; + static unsigned int dev_count = 1; + + dev->core.parent = NULL; + dev->core.bus = &ps3_system_bus_type; + dev->core.release = ps3_system_bus_release_device; + + dev->core.archdata.of_node = NULL; + dev->core.archdata.dma_ops = &ps3_dma_ops; + dev->core.archdata.numa_node = 0; + + snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "sb_%02x", + dev_count++); + + pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id); + + result = device_register(&dev->core); + return result; +} + +EXPORT_SYMBOL_GPL(ps3_system_bus_device_register); + +int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv) +{ + int result; + + drv->core.bus = &ps3_system_bus_type; + + result = driver_register(&drv->core); + return result; +} + +EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register); + +void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv) +{ + driver_unregister(&drv->core); +} + +EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister); diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h index eb4bbb6cff5..52a69ed0d90 100644 --- a/include/asm-powerpc/ps3.h +++ b/include/asm-powerpc/ps3.h @@ -386,4 +386,77 @@ int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id); int ps3_repository_read_spu_resource_id(unsigned int res_index, enum ps3_spu_resource_type* resource_type, unsigned int *resource_id); + +/* system bus routines */ + +enum ps3_match_id { + PS3_MATCH_ID_EHCI = 1, + PS3_MATCH_ID_OHCI, + PS3_MATCH_ID_GELIC, + PS3_MATCH_ID_AV_SETTINGS, + PS3_MATCH_ID_SYSTEM_MANAGER, +}; + +/** + * struct ps3_system_bus_device - a device on the system bus + */ + +struct ps3_system_bus_device { + enum ps3_match_id match_id; + struct ps3_device_id did; + unsigned int interrupt_id; +/* struct iommu_table *iommu_table; -- waiting for Ben's cleanups */ + struct ps3_dma_region *d_region; + struct ps3_mmio_region *m_region; + struct device core; +}; + +/** + * struct ps3_system_bus_driver - a driver for a device on the system bus + */ + +struct ps3_system_bus_driver { + enum ps3_match_id match_id; + struct device_driver core; + int (*probe)(struct ps3_system_bus_device *); + int (*remove)(struct ps3_system_bus_device *); +/* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ +/* int (*resume)(struct ps3_system_bus_device *); */ +}; + +int ps3_system_bus_device_register(struct ps3_system_bus_device *dev); +int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv); +void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv); +static inline struct ps3_system_bus_driver *to_ps3_system_bus_driver( + struct device_driver *_drv) +{ + return container_of(_drv, struct ps3_system_bus_driver, core); +} +static inline struct ps3_system_bus_device *to_ps3_system_bus_device( + struct device *_dev) +{ + return container_of(_dev, struct ps3_system_bus_device, core); +} + +/** + * ps3_system_bus_set_drvdata - + * @dev: device structure + * @data: Data to set + */ + +static inline void ps3_system_bus_set_driver_data( + struct ps3_system_bus_device *dev, void *data) +{ + dev->core.driver_data = data; +} +static inline void *ps3_system_bus_get_driver_data( + struct ps3_system_bus_device *dev) +{ + return dev->core.driver_data; +} + +/* These two need global scope for get_dma_ops(). */ + +extern struct bus_type ps3_system_bus_type; + #endif -- cgit v1.2.3-70-g09d2 From e055595d3e5f5233374211bc6893e5d16976df99 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Nov 2006 19:18:55 +0100 Subject: [POWERPC] cell: fix building without spufs It may be desireable to build a kernel for cell without spufs, e.g. as the initial kboot kernel. This requires that the SPU specific parts of the core dump and the xmon code depend on CONFIG_SPU_BASE instead of CONFIG_PPC_CELL. Signed-off-by: Arnd Bergmann --- arch/powerpc/xmon/Makefile | 2 +- arch/powerpc/xmon/xmon.c | 6 +++--- include/asm-powerpc/elf.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile index 69303575d3d..51d97588e76 100644 --- a/arch/powerpc/xmon/Makefile +++ b/arch/powerpc/xmon/Makefile @@ -8,5 +8,5 @@ obj-y += xmon.o setjmp.o start.o nonstdio.o ifdef CONFIG_XMON_DISASSEMBLY obj-y += ppc-dis.o ppc-opc.o -obj-$(CONFIG_PPC_CELL) += spu-dis.o spu-opc.o +obj-$(CONFIG_SPU_BASE) += spu-dis.o spu-opc.o endif diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 1cf90c8ac34..dc8a3760a98 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -213,7 +213,7 @@ Commands:\n\ p call a procedure\n\ r print registers\n\ s single step\n" -#ifdef CONFIG_PPC_CELL +#ifdef CONFIG_SPU_BASE " ss stop execution on all spus\n\ sr restore execution on stopped spus\n\ sf # dump spu fields for spu # (in hex)\n\ @@ -2654,7 +2654,7 @@ void __init xmon_setup(void) debugger(NULL); } -#ifdef CONFIG_PPC_CELL +#ifdef CONFIG_SPU_BASE struct spu_info { struct spu *spu; @@ -2907,7 +2907,7 @@ static int do_spu_cmd(void) return 0; } -#else /* ! CONFIG_PPC_CELL */ +#else /* ! CONFIG_SPU_BASE */ static int do_spu_cmd(void) { return -1; diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index 4545aa68250..b5436642a10 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -411,7 +411,7 @@ do { \ /* Keep this the last entry. */ #define R_PPC64_NUM 107 -#ifdef CONFIG_PPC_CELL +#ifdef CONFIG_SPU_BASE /* Notes used in ET_CORE. Note name is "SPU//". */ #define NT_SPU 1 -- cgit v1.2.3-70-g09d2 From eb30c72026500f9efa9bb23ab2393d6a9e36c5e1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 27 Nov 2006 19:18:56 +0100 Subject: [POWERPC] ps3: Missed renames of CONFIG_PS3 to CONFIG_PPC_PS3 When renaming CONFIG_PS3 to CONFIG_PPC_PS3, a few occurrences have been missed. I also fixed up the alignment in arch/powerpc/platforms/Makefile. Signed-off-by: Geert Uytterhoeven Signed-off-by: Arnd Bergmann --- arch/powerpc/platforms/Makefile | 6 +++--- drivers/Makefile | 2 +- include/asm-powerpc/firmware.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index 56caf4fbd73..52984a803e7 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -5,7 +5,7 @@ ifeq ($(CONFIG_PPC64),y) obj-$(CONFIG_PPC_PMAC) += powermac/ endif endif -obj-$(CONFIG_PPC_EFIKA) += efika/ +obj-$(CONFIG_PPC_EFIKA) += efika/ obj-$(CONFIG_PPC_CHRP) += chrp/ obj-$(CONFIG_4xx) += 4xx/ obj-$(CONFIG_PPC_83xx) += 83xx/ @@ -14,7 +14,7 @@ obj-$(CONFIG_PPC_86xx) += 86xx/ obj-$(CONFIG_PPC_PSERIES) += pseries/ obj-$(CONFIG_PPC_ISERIES) += iseries/ obj-$(CONFIG_PPC_MAPLE) += maple/ -obj-$(CONFIG_PPC_PASEMI) += pasemi/ +obj-$(CONFIG_PPC_PASEMI) += pasemi/ obj-$(CONFIG_PPC_CELL) += cell/ -obj-$(CONFIG_PS3) += ps3/ +obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/ diff --git a/drivers/Makefile b/drivers/Makefile index a47d2483b7a..67711770b1d 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -77,4 +77,4 @@ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ obj-$(CONFIG_GENERIC_TIME) += clocksource/ obj-$(CONFIG_DMA_ENGINE) += dma/ -obj-$(CONFIG_PS3) += ps3/ +obj-$(CONFIG_PPC_PS3) += ps3/ diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h index d1011b892d5..84d43d6e13e 100644 --- a/include/asm-powerpc/firmware.h +++ b/include/asm-powerpc/firmware.h @@ -67,7 +67,7 @@ enum { #ifdef CONFIG_PPC_ISERIES FW_FEATURE_ISERIES_POSSIBLE | #endif -#ifdef CONFIG_PS3 +#ifdef CONFIG_PPC_PS3 FW_FEATURE_PS3_POSSIBLE | #endif 0, @@ -78,7 +78,7 @@ enum { #ifdef CONFIG_PPC_ISERIES FW_FEATURE_ISERIES_ALWAYS & #endif -#ifdef CONFIG_PS3 +#ifdef CONFIG_PPC_PS3 FW_FEATURE_PS3_ALWAYS & #endif FW_FEATURE_POSSIBLE, -- cgit v1.2.3-70-g09d2 From e22ba7e38144c1cccac5024cfd6ec88bb64d3e1f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Nov 2006 19:18:57 +0100 Subject: [POWERPC] ps3: multiplatform build fixes A few code paths need to check whether or not they are running on the PS3's LV1 hypervisor before making hcalls. This introduces a new firmware feature bit for this, FW_FEATURE_PS3_LV1. Now when both PS3 and IBM_CELL_BLADE are enabled, but not PSERIES, FW_FEATURE_PS3_LV1 and FW_FEATURE_LPAR get enabled at compile time, which is a bug. The same problem can also happen for (PPC_ISERIES && !PPC_PSERIES && PPC_SOMETHING_ELSE). In order to solve this, I introduce a new CONFIG_PPC_NATIVE option that is set when at least one platform is selected that can run without a hypervisor and then turns the firmware feature check into a run-time option. The new cell oprofile support that was recently merged does not work on hypervisor based platforms like the PS3, therefore make it depend on PPC_CELL_NATIVE instead of PPC_CELL. This may change if we get oprofile support for PS3. Signed-off-by: Arnd Bergmann --- arch/powerpc/Kconfig | 26 +++++++++++++++++++++----- arch/powerpc/mm/Makefile | 2 +- arch/powerpc/oprofile/Makefile | 2 +- arch/powerpc/oprofile/common.c | 2 +- arch/powerpc/platforms/ps3/mm.c | 4 ++++ arch/powerpc/platforms/ps3/setup.c | 2 +- drivers/ps3/system-bus.c | 4 ++++ include/asm-powerpc/firmware.h | 13 +++++++++++-- 8 files changed, 44 insertions(+), 11 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c0146a40c6f..c04b7138e1a 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -390,6 +390,7 @@ config PPC_PSERIES select PPC_RTAS select RTAS_ERROR_LOGGING select PPC_UDBG_16550 + select PPC_NATIVE default y config PPC_ISERIES @@ -406,6 +407,7 @@ config PPC_CHRP select PPC_RTAS select PPC_MPC106 select PPC_UDBG_16550 + select PPC_NATIVE default y config PPC_EFIKA @@ -414,6 +416,7 @@ config PPC_EFIKA select PPC_RTAS select RTAS_PROC select PPC_MPC52xx + select PPC_NATIVE default y config PPC_PMAC @@ -422,6 +425,7 @@ config PPC_PMAC select MPIC select PPC_INDIRECT_PCI if PPC32 select PPC_MPC106 if PPC32 + select PPC_NATIVE default y config PPC_PMAC64 @@ -441,6 +445,7 @@ config PPC_PREP select PPC_I8259 select PPC_INDIRECT_PCI select PPC_UDBG_16550 + select PPC_NATIVE default y config PPC_MAPLE @@ -452,6 +457,7 @@ config PPC_MAPLE select GENERIC_TBSYNC select PPC_UDBG_16550 select PPC_970_NAP + select PPC_NATIVE default n help This option enables support for the Maple 970FX Evaluation Board. @@ -464,6 +470,7 @@ config PPC_PASEMI select MPIC select PPC_UDBG_16550 select GENERIC_TBSYNC + select PPC_NATIVE help This option enables support for PA Semi's PWRficient line of SoC processors, including PA6T-1682M @@ -478,6 +485,7 @@ config PPC_CELL_NATIVE select PPC_DCR_MMIO select PPC_OF_PLATFORM_PCI select PPC_INDIRECT_IO + select PPC_NATIVE select MPIC default n @@ -490,11 +498,6 @@ config PPC_IBM_CELL_BLADE select PPC_UDBG_16550 select UDBG_RTAS_CONSOLE -config UDBG_RTAS_CONSOLE - bool "RTAS based debug console" - depends on PPC_RTAS - default n - config PPC_PS3 bool "Sony PS3" depends on PPC_MULTIPLATFORM && PPC64 @@ -503,6 +506,19 @@ config PPC_PS3 This option enables support for the Sony PS3 game console and other platforms using the PS3 hypervisor. +config PPC_NATIVE + bool + depends on PPC_MULTIPLATFORM + help + Support for running natively on the hardware, i.e. without + a hypervisor. This option is not user-selectable but should + be selected by all platforms that need it. + +config UDBG_RTAS_CONSOLE + bool "RTAS based debug console" + depends on PPC_RTAS + default n + config XICS depends on PPC_PSERIES bool diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 93441e7a292..38a81967ca0 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile @@ -8,7 +8,7 @@ endif obj-y := fault.o mem.o lmb.o obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o -hash-$(CONFIG_PPC_MULTIPLATFORM) := hash_native_64.o +hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ hash_utils_64.o hash_low_64.o tlb_64.o \ slb_low.o slb.o stab.o mmap.o imalloc.o \ diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 51c510fed7f..4ccef2d5530 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile @@ -11,7 +11,7 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ timer_int.o ) oprofile-y := $(DRIVER_OBJS) common.o backtrace.o -oprofile-$(CONFIG_PPC_CELL) += op_model_cell.o +oprofile-$(CONFIG_PPC_CELL_NATIVE) += op_model_cell.o oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o oprofile-$(CONFIG_6xx) += op_model_7450.o diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 7a423437977..b6d82390b6a 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -147,7 +147,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) switch (cur_cpu_spec->oprofile_type) { #ifdef CONFIG_PPC64 -#ifdef CONFIG_PPC_CELL +#ifdef CONFIG_PPC_CELL_NATIVE case PPC_OPROFILE_CELL: model = &op_model_cell; break; diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index a57f7036dd1..49c0d010d49 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -293,6 +294,9 @@ static int __init ps3_mm_add_memory(void) unsigned long start_pfn; unsigned long nr_pages; + if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) + return 0; + BUG_ON(!mem_init_done); start_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size; diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index c1f6de50654..d8b5cadbe80 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c @@ -108,7 +108,7 @@ static int __init ps3_probe(void) if (!of_flat_dt_is_compatible(dt_root, "PS3")) return 0; - powerpc_firmware_features |= FW_FEATURE_LPAR; + powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; ps3_os_area_init(); ps3_mm_init(); diff --git a/drivers/ps3/system-bus.c b/drivers/ps3/system-bus.c index e19992c4db4..d79f949bcb2 100644 --- a/drivers/ps3/system-bus.c +++ b/drivers/ps3/system-bus.c @@ -27,6 +27,7 @@ #include #include #include +#include #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__) static void _dump_mmio_region(const struct ps3_mmio_region* r, @@ -167,6 +168,9 @@ int __init ps3_system_bus_init(void) { int result; + if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) + return 0; + result = bus_register(&ps3_system_bus_type); BUG_ON(result); return result; diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h index 84d43d6e13e..98f7b62422c 100644 --- a/include/asm-powerpc/firmware.h +++ b/include/asm-powerpc/firmware.h @@ -42,6 +42,7 @@ #define FW_FEATURE_SPLPAR ASM_CONST(0x0000000000100000) #define FW_FEATURE_ISERIES ASM_CONST(0x0000000000200000) #define FW_FEATURE_LPAR ASM_CONST(0x0000000000400000) +#define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000) #ifndef __ASSEMBLY__ @@ -58,8 +59,10 @@ enum { FW_FEATURE_PSERIES_ALWAYS = 0, FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, - FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR, - FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR, + FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, + FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, + FW_FEATURE_NATIVE_POSSIBLE = 0, + FW_FEATURE_NATIVE_ALWAYS = 0, FW_FEATURE_POSSIBLE = #ifdef CONFIG_PPC_PSERIES FW_FEATURE_PSERIES_POSSIBLE | @@ -69,6 +72,9 @@ enum { #endif #ifdef CONFIG_PPC_PS3 FW_FEATURE_PS3_POSSIBLE | +#endif +#ifdef CONFIG_PPC_NATIVE + FW_FEATURE_NATIVE_ALWAYS | #endif 0, FW_FEATURE_ALWAYS = @@ -80,6 +86,9 @@ enum { #endif #ifdef CONFIG_PPC_PS3 FW_FEATURE_PS3_ALWAYS & +#endif +#ifdef CONFIG_PPC_NATIVE + FW_FEATURE_NATIVE_ALWAYS & #endif FW_FEATURE_POSSIBLE, -- cgit v1.2.3-70-g09d2 From 11faa658c668030759d4aea6a273b7ac9a0b4746 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Nov 2006 19:19:00 +0100 Subject: [POWERPC] fix building without PCI At least the ide driver calls pcibus_to_node, which is not defined when CONFIG_PCI is disabled. This adds a nop function for the !PCI case. Signed-off-by: Arnd Bergmann --- include/asm-powerpc/topology.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h index 9fe7894ee03..50c014007de 100644 --- a/include/asm-powerpc/topology.h +++ b/include/asm-powerpc/topology.h @@ -32,7 +32,14 @@ static inline int node_to_first_cpu(int node) int of_node_to_nid(struct device_node *device); struct pci_bus; +#ifdef CONFIG_PCI extern int pcibus_to_node(struct pci_bus *bus); +#else +static inline int pcibus_to_node(struct pci_bus *bus) +{ + return -1; +} +#endif #define pcibus_to_cpumask(bus) (pcibus_to_node(bus) == -1 ? \ CPU_MASK_ALL : \ -- cgit v1.2.3-70-g09d2 From 4cfbdfff70989a0d99b6f357fbbe379c22a05f7c Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 1 Dec 2006 12:53:18 +0100 Subject: [POWERPC] include/asm-powerpc/: "extern inline" -> "static inline" "extern inline" generates a warning with -Wmissing-prototypes and I'm currently working on getting the kernel cleaned up for adding this to the CFLAGS since it will help us to avoid a nasty class of runtime errors. If there are places that really need a forced inline, __always_inline would be the correct solution. Signed-off-by: Adrian Bunk Signed-off-by: Paul Mackerras --- include/asm-powerpc/io.h | 4 ++-- include/asm-powerpc/tsi108.h | 4 ++-- include/asm-powerpc/uaccess.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index 75df3bce9cc..1cd532379c3 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h @@ -302,7 +302,7 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) #ifdef CONFIG_PPC32 #define __do_in_asm(name, op) \ -extern __inline__ unsigned int name(unsigned int port) \ +static inline unsigned int name(unsigned int port) \ { \ unsigned int x; \ __asm__ __volatile__( \ @@ -329,7 +329,7 @@ extern __inline__ unsigned int name(unsigned int port) \ } #define __do_out_asm(name, op) \ -extern __inline__ void name(unsigned int val, unsigned int port) \ +static inline void name(unsigned int val, unsigned int port) \ { \ __asm__ __volatile__( \ "sync\n" \ diff --git a/include/asm-powerpc/tsi108.h b/include/asm-powerpc/tsi108.h index 2c702d35a7c..4e95d153be8 100644 --- a/include/asm-powerpc/tsi108.h +++ b/include/asm-powerpc/tsi108.h @@ -98,12 +98,12 @@ typedef struct { extern u32 get_vir_csrbase(void); extern u32 tsi108_csr_vir_base; -extern inline u32 tsi108_read_reg(u32 reg_offset) +static inline u32 tsi108_read_reg(u32 reg_offset) { return in_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset)); } -extern inline void tsi108_write_reg(u32 reg_offset, u32 val) +static inline void tsi108_write_reg(u32 reg_offset, u32 val) { out_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset), val); } diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h index d83fc29c2bb..adbf16b8cfb 100644 --- a/include/asm-powerpc/uaccess.h +++ b/include/asm-powerpc/uaccess.h @@ -304,7 +304,7 @@ extern unsigned long __copy_tofrom_user(void __user *to, #ifndef __powerpc64__ -extern inline unsigned long copy_from_user(void *to, +static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) { unsigned long over; @@ -319,7 +319,7 @@ extern inline unsigned long copy_from_user(void *to, return n; } -extern inline unsigned long copy_to_user(void __user *to, +static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) { unsigned long over; -- cgit v1.2.3-70-g09d2 From 143db67af02cecab28032ec3a52e586b1433fe70 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Sun, 26 Nov 2006 17:36:15 +1100 Subject: [POWERPC] Provide dummy hard_irq_enable/disable() for PPC32 To allow arch/powerpc/kernel/crash.c to build on 32-bit we need a definition of hard_irq_disable(). 32-bit doesn't support the lazy interrupt disabling mechanism, so on 32-bit hard_irq_disable() is simply local_irq_disable(). Add a definition for hard_irq_enable() just for completeness. This allows (KEXEC=y && PPC32=y) to build again. Broken since d04c56f73c30a5e593202ecfcf25ed43d42363a2. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- include/asm-powerpc/hw_irq.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h index fd3f2a20627..d604863d72f 100644 --- a/include/asm-powerpc/hw_irq.h +++ b/include/asm-powerpc/hw_irq.h @@ -102,6 +102,9 @@ static inline void local_irq_save_ptr(unsigned long *flags) #define local_irq_save(flags) local_irq_save_ptr(&flags) #define irqs_disabled() ((mfmsr() & MSR_EE) == 0) +#define hard_irq_enable() local_irq_enable() +#define hard_irq_disable() local_irq_disable() + #endif /* CONFIG_PPC64 */ #define mask_irq(irq) \ -- cgit v1.2.3-70-g09d2 From e65fdfd6ca447353ad1b4c0a0d20df55f3f6f233 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Mon, 27 Nov 2006 14:16:26 -0700 Subject: [POWERPC] Separate IRQ config / register set from main header There is no need to expose these settings outside the scope of the interrupt controller code itself. Signed-off-by: Sylvain Munaut Signed-off-by: Grant Likely Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/52xx/mpc52xx_pic.c | 1 + arch/powerpc/platforms/52xx/mpc52xx_pic.h | 53 +++++++++++++++++++++++++++++++ include/asm-powerpc/mpc52xx.h | 37 --------------------- 3 files changed, 54 insertions(+), 37 deletions(-) create mode 100644 arch/powerpc/platforms/52xx/mpc52xx_pic.h (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 6df51f04b8f..504154fdf6a 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -33,6 +33,7 @@ #include #include #include +#include "mpc52xx_pic.h" /* * diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.h b/arch/powerpc/platforms/52xx/mpc52xx_pic.h new file mode 100644 index 00000000000..1a26bcdb304 --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.h @@ -0,0 +1,53 @@ +/* + * Header file for Freescale MPC52xx Interrupt controller + * + * Copyright (C) 2004-2005 Sylvain Munaut + * Copyright (C) 2003 MontaVista, Software, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef __POWERPC_SYSDEV_MPC52xx_PIC_H__ +#define __POWERPC_SYSDEV_MPC52xx_PIC_H__ + +#include + + +/* HW IRQ mapping */ +#define MPC52xx_IRQ_L1_CRIT (0) +#define MPC52xx_IRQ_L1_MAIN (1) +#define MPC52xx_IRQ_L1_PERP (2) +#define MPC52xx_IRQ_L1_SDMA (3) + +#define MPC52xx_IRQ_L1_OFFSET (6) +#define MPC52xx_IRQ_L1_MASK (0x00c0) + +#define MPC52xx_IRQ_L2_OFFSET (0) +#define MPC52xx_IRQ_L2_MASK (0x003f) + +#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0) + + +/* Interrupt controller Register set */ +struct mpc52xx_intr { + u32 per_mask; /* INTR + 0x00 */ + u32 per_pri1; /* INTR + 0x04 */ + u32 per_pri2; /* INTR + 0x08 */ + u32 per_pri3; /* INTR + 0x0c */ + u32 ctrl; /* INTR + 0x10 */ + u32 main_mask; /* INTR + 0x14 */ + u32 main_pri1; /* INTR + 0x18 */ + u32 main_pri2; /* INTR + 0x1c */ + u32 reserved1; /* INTR + 0x20 */ + u32 enc_status; /* INTR + 0x24 */ + u32 crit_status; /* INTR + 0x28 */ + u32 main_status; /* INTR + 0x2c */ + u32 per_status; /* INTR + 0x30 */ + u32 reserved2; /* INTR + 0x34 */ + u32 per_error; /* INTR + 0x38 */ +}; + +#endif /* __POWERPC_SYSDEV_MPC52xx_PIC_H__ */ + diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h index e9aa622f19f..fff752c4bd1 100644 --- a/include/asm-powerpc/mpc52xx.h +++ b/include/asm-powerpc/mpc52xx.h @@ -19,49 +19,12 @@ #endif /* __ASSEMBLY__ */ -/* ======================================================================== */ -/* HW IRQ mapping */ -/* ======================================================================== */ - -#define MPC52xx_IRQ_L1_CRIT (0) -#define MPC52xx_IRQ_L1_MAIN (1) -#define MPC52xx_IRQ_L1_PERP (2) -#define MPC52xx_IRQ_L1_SDMA (3) - -#define MPC52xx_IRQ_L1_OFFSET (6) -#define MPC52xx_IRQ_L1_MASK (0xc0) - -#define MPC52xx_IRQ_L2_OFFSET (0) -#define MPC52xx_IRQ_L2_MASK (0x3f) - -#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0) - - /* ======================================================================== */ /* Structures mapping of some unit register set */ /* ======================================================================== */ #ifndef __ASSEMBLY__ -/* Interrupt controller Register set */ -struct mpc52xx_intr { - u32 per_mask; /* INTR + 0x00 */ - u32 per_pri1; /* INTR + 0x04 */ - u32 per_pri2; /* INTR + 0x08 */ - u32 per_pri3; /* INTR + 0x0c */ - u32 ctrl; /* INTR + 0x10 */ - u32 main_mask; /* INTR + 0x14 */ - u32 main_pri1; /* INTR + 0x18 */ - u32 main_pri2; /* INTR + 0x1c */ - u32 reserved1; /* INTR + 0x20 */ - u32 enc_status; /* INTR + 0x24 */ - u32 crit_status; /* INTR + 0x28 */ - u32 main_status; /* INTR + 0x2c */ - u32 per_status; /* INTR + 0x30 */ - u32 reserved2; /* INTR + 0x34 */ - u32 per_error; /* INTR + 0x38 */ -}; - /* Memory Mapping Control */ struct mpc52xx_mmap_ctl { u32 mbar; /* MMAP_CTRL + 0x00 */ -- cgit v1.2.3-70-g09d2 From 6065170cf75c64267f6edec5fd359ce8444bd13d Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 27 Nov 2006 14:16:27 -0700 Subject: [POWERPC] Add common routines for 52xx support in arch/powerpc Adds utility routines used by 52xx device drivers and board support code. Main functionality is to add device nodes to the of_platform_bus, retrieve the IPB bus frequency, and find+ioremap device registers. Signed-off-by: Grant Likely Signed-off-by: Sylvain Munaut Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/52xx/Makefile | 2 +- arch/powerpc/platforms/52xx/mpc52xx_common.c | 124 +++++++++++++++++++++++++++ arch/powerpc/platforms/52xx/mpc52xx_pic.c | 110 +++++------------------- include/asm-powerpc/mpc52xx.h | 4 + 4 files changed, 151 insertions(+), 89 deletions(-) create mode 100644 arch/powerpc/platforms/52xx/mpc52xx_common.c (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile index 1c9c122123d..b8f27a86406 100644 --- a/arch/powerpc/platforms/52xx/Makefile +++ b/arch/powerpc/platforms/52xx/Makefile @@ -2,7 +2,7 @@ # Makefile for 52xx based boards # ifeq ($(CONFIG_PPC_MERGE),y) -obj-y += mpc52xx_pic.o +obj-y += mpc52xx_pic.o mpc52xx_common.o endif obj-$(CONFIG_PPC_EFIKA) += efika-setup.o efika-pci.o diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c new file mode 100644 index 00000000000..05b21444127 --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -0,0 +1,124 @@ +/* + * + * Utility functions for the Freescale MPC52xx. + * + * Copyright (C) 2006 Sylvain Munaut + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#undef DEBUG + +#include + +#include +#include +#include +#include + + +void __iomem * +mpc52xx_find_and_map(const char *compatible) +{ + struct device_node *ofn; + const u32 *regaddr_p; + u64 regaddr64, size64; + + ofn = of_find_compatible_node(NULL, NULL, compatible); + if (!ofn) + return NULL; + + regaddr_p = of_get_address(ofn, 0, &size64, NULL); + if (!regaddr_p) { + of_node_put(ofn); + return NULL; + } + + regaddr64 = of_translate_address(ofn, regaddr_p); + + of_node_put(ofn); + + return ioremap((u32)regaddr64, (u32)size64); +} + + +/** + * mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device + * @node: device node + * + * Returns IPB bus frequency, or 0 if the bus frequency cannot be found. + */ +unsigned int +mpc52xx_find_ipb_freq(struct device_node *node) +{ + struct device_node *np; + const unsigned int *p_ipb_freq = NULL; + + of_node_get(node); + while (node) { + p_ipb_freq = get_property(node, "bus-frequency", NULL); + if (p_ipb_freq) + break; + + np = of_get_parent(node); + of_node_put(node); + node = np; + } + if (node) + of_node_put(node); + + return p_ipb_freq ? *p_ipb_freq : 0; +} + + +void __init +mpc52xx_setup_cpu(void) +{ + struct mpc52xx_cdm __iomem *cdm; + struct mpc52xx_xlb __iomem *xlb; + + /* Map zones */ + cdm = mpc52xx_find_and_map("mpc52xx-cdm"); + xlb = mpc52xx_find_and_map("mpc52xx-xlb"); + + if (!cdm || !xlb) { + printk(KERN_ERR __FILE__ ": " + "Error while mapping CDM/XLB during mpc52xx_setup_cpu. " + "Expect some abnormal behavior\n"); + goto unmap_regs; + } + + /* Use internal 48 Mhz */ + out_8(&cdm->ext_48mhz_en, 0x00); + out_8(&cdm->fd_enable, 0x01); + if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ + out_be16(&cdm->fd_counters, 0x0001); + else + out_be16(&cdm->fd_counters, 0x5555); + + /* Configure the XLB Arbiter priorities */ + out_be32(&xlb->master_pri_enable, 0xff); + out_be32(&xlb->master_priority, 0x11111111); + + /* Disable XLB pipelining */ + /* (cfr errate 292. We could do this only just before ATA PIO + transaction and re-enable it afterwards ...) */ + out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); + + /* Unmap zones */ +unmap_regs: + if (cdm) iounmap(cdm); + if (xlb) iounmap(xlb); +} + +static int __init +mpc52xx_declare_of_platform_devices(void) +{ + /* Find every child of the SOC node and add it to of_platform */ + return of_platform_bus_probe(NULL, NULL, NULL); +} + +device_initcall(mpc52xx_declare_of_platform_devices); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 504154fdf6a..cd91a6c3aaf 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -54,12 +54,12 @@ static unsigned char mpc52xx_map_senses[4] = { * */ -static inline void io_be_setbit(u32 __iomem * addr, int bitno) +static inline void io_be_setbit(u32 __iomem *addr, int bitno) { out_be32(addr, in_be32(addr) | (1 << bitno)); } -static inline void io_be_clrbit(u32 __iomem * addr, int bitno) +static inline void io_be_clrbit(u32 __iomem *addr, int bitno) { out_be32(addr, in_be32(addr) & ~(1 << bitno)); } @@ -104,7 +104,7 @@ static void mpc52xx_extirq_ack(unsigned int virq) pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); - io_be_setbit(&intr->ctrl, 27 - l2irq); + io_be_setbit(&intr->ctrl, 27-l2irq); } static struct irq_chip mpc52xx_extirq_irqchip = { @@ -379,81 +379,21 @@ static struct irq_host_ops mpc52xx_irqhost_ops = { void __init mpc52xx_init_irq(void) { - struct device_node *picnode = NULL; - int picnode_regsize; - u32 picnode_regoffset; - - struct device_node *sdmanode = NULL; - int sdmanode_regsize; - u32 sdmanode_regoffset; - - u64 size64; - int flags; - u32 intr_ctrl; - - picnode = of_find_compatible_node(NULL, "interrupt-controller", - "mpc5200-pic"); - if (picnode == NULL) { - printk(KERN_ERR "MPC52xx PIC: " - "Unable to find the interrupt controller " - "in the OpenFirmware device tree\n"); - goto end; - } - - sdmanode = of_find_compatible_node(NULL, "dma-controller", - "mpc5200-bestcomm"); - if (sdmanode == NULL) { - printk(KERN_ERR "MPC52xx PIC" - "Unable to find the Bestcomm DMA controller device " - "in the OpenFirmware device tree\n"); - goto end; - } - - /* Retrieve PIC ressources */ - picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags); - if (picnode_regoffset == 0) { - printk(KERN_ERR "MPC52xx PIC" - "Unable to get the interrupt controller address\n"); - goto end; - } - - picnode_regoffset = - of_translate_address(picnode, (u32 *) picnode_regoffset); - picnode_regsize = (int)size64; - - /* Retrieve SDMA ressources */ - sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags); - if (sdmanode_regoffset == 0) { - printk(KERN_ERR "MPC52xx PIC: " - "Unable to get the Bestcomm DMA controller address\n"); - goto end; - } - - sdmanode_regoffset = - of_translate_address(sdmanode, (u32 *) sdmanode_regoffset); - sdmanode_regsize = (int)size64; + struct device_node *picnode; /* Remap the necessary zones */ - intr = ioremap(picnode_regoffset, picnode_regsize); - if (intr == NULL) { - printk(KERN_ERR "MPC52xx PIC: " - "Unable to ioremap interrupt controller registers!\n"); - goto end; - } + picnode = of_find_compatible_node(NULL, NULL, "mpc52xx-pic"); - sdma = ioremap(sdmanode_regoffset, sdmanode_regsize); - if (sdma == NULL) { - iounmap(intr); - printk(KERN_ERR "MPC52xx PIC: " - "Unable to ioremap Bestcomm DMA registers!\n"); - goto end; - } + intr = mpc52xx_find_and_map("mpc52xx-pic"); + if (!intr) + panic(__FILE__ ": find_and_map failed on 'mpc52xx-pic'. " + "Check node !"); - printk(KERN_INFO "MPC52xx PIC: MPC52xx PIC Remapped at 0x%8.8x\n", - picnode_regoffset); - printk(KERN_INFO "MPC52xx PIC: MPC52xx SDMA Remapped at 0x%8.8x\n", - sdmanode_regoffset); + sdma = mpc52xx_find_and_map("mpc52xx-bestcomm"); + if (!sdma) + panic(__FILE__ ": find_and_map failed on 'mpc52xx-bestcomm'. " + "Check node !"); /* Disable all interrupt sources. */ out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */ @@ -480,21 +420,15 @@ void __init mpc52xx_init_irq(void) * hw irq information provided by the ofw to linux virq */ - mpc52xx_irqhost = - irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTHWIRQ, - &mpc52xx_irqhost_ops, -1); + mpc52xx_irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, + MPC52xx_IRQ_HIGHTESTHWIRQ, + &mpc52xx_irqhost_ops, -1); - if (mpc52xx_irqhost) { - mpc52xx_irqhost->host_data = picnode; - printk(KERN_INFO "MPC52xx PIC is up and running!\n"); - } else { - printk(KERN_ERR - "MPC52xx PIC: Unable to allocate the IRQ host\n"); - } + if (!mpc52xx_irqhost) + panic(__FILE__ ": Cannot allocate the IRQ host\n"); -end: - of_node_put(picnode); - of_node_put(sdmanode); + mpc52xx_irqhost->host_data = picnode; + printk(KERN_INFO "MPC52xx PIC is up and running!\n"); } /* @@ -526,9 +460,10 @@ unsigned int mpc52xx_get_irq(void) irq = ffs(status) - 1; irq |= (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK; - } else + } else { irq |= (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK; + } } pr_debug("%s: irq=%x. virq=%d\n", __func__, irq, @@ -536,4 +471,3 @@ unsigned int mpc52xx_get_irq(void) return irq_linear_revmap(mpc52xx_irqhost, irq); } - diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h index fff752c4bd1..4a28a850998 100644 --- a/include/asm-powerpc/mpc52xx.h +++ b/include/asm-powerpc/mpc52xx.h @@ -241,6 +241,10 @@ struct mpc52xx_cdm { #ifndef __ASSEMBLY__ +extern void __iomem * mpc52xx_find_and_map(const char *); +extern unsigned int mpc52xx_find_ipb_freq(struct device_node *node); +extern void mpc52xx_setup_cpu(void); + extern void mpc52xx_init_irq(void); extern unsigned int mpc52xx_get_irq(void); -- cgit v1.2.3-70-g09d2 From 0470466dbafd1db0815bb884d26a6be431e19f96 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 30 Nov 2006 11:46:22 +1100 Subject: [POWERPC] Fix cputable.h for combined build Remove CPU_FTR_16M_PAGE from the cupfeatures mask at runtime on iSeries. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_utils_64.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 2 ++ include/asm-powerpc/cputable.h | 13 +++---------- 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 1915661c2c8..c0d2a694fa3 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -277,7 +277,7 @@ static void __init htab_init_page_sizes(void) * Not in the device-tree, let's fallback on known size * list for 16M capable GP & GR */ - if (cpu_has_feature(CPU_FTR_16M_PAGE) && !machine_is(iseries)) + if (cpu_has_feature(CPU_FTR_16M_PAGE)) memcpy(mmu_psize_defs, mmu_psize_defaults_gp, sizeof(mmu_psize_defaults_gp)); found: diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 1796644ec7d..bdf2afbb60c 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -643,6 +643,8 @@ static int __init iseries_probe(void) return 0; hpte_init_iSeries(); + /* iSeries does not support 16M pages */ + cur_cpu_spec->cpu_features &= ~CPU_FTR_16M_PAGE; return 1; } diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 354f66da9dc..6fe5c9d4ca3 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -155,16 +155,9 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #ifndef __ASSEMBLY__ -#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ - CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ - CPU_FTR_NODSISRALIGN) - -/* iSeries doesn't support large pages */ -#ifdef CONFIG_PPC_ISERIES -#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE) -#else -#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE) -#endif /* CONFIG_PPC_ISERIES */ +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_SLB | \ + CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ + CPU_FTR_NODSISRALIGN | CPU_FTR_16M_PAGE) /* We only set the altivec features if the kernel was compiled with altivec * support -- cgit v1.2.3-70-g09d2 From e62438630ca37539c8cc1553710bbfaa3cf960a7 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 4 Dec 2006 03:38:31 -0700 Subject: [PATCH] Centralise definitions of sector_t and blkcnt_t CONFIG_LBD and CONFIG_LSF are spread into asm/types.h for no particularly good reason. Centralising the definition in linux/types.h means that arch maintainers don't need to bother adding it, as well as fixing the problem with x86-64 users being asked to make a decision that has absolutely no effect. The H8/300 porters seem particularly confused since I'm not aware of any microcontrollers that need to support 2TB filesystems. Signed-off-by: Matthew Wilcox Signed-off-by: Linus Torvalds --- block/Kconfig | 6 ++---- include/asm-avr32/types.h | 5 ----- include/asm-h8300/types.h | 6 ------ include/asm-i386/types.h | 10 ---------- include/asm-mips/types.h | 10 ---------- include/asm-powerpc/types.h | 10 ---------- include/asm-s390/types.h | 10 ---------- include/asm-sh/types.h | 10 ---------- include/asm-x86_64/types.h | 3 --- include/linux/types.h | 14 +++++++++----- 10 files changed, 11 insertions(+), 73 deletions(-) (limited to 'include/asm-powerpc') diff --git a/block/Kconfig b/block/Kconfig index 83766a6bdee..a50f4811164 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -19,11 +19,9 @@ config BLOCK if BLOCK -#XXX - it makes sense to enable this only for 32-bit subarch's, not for x86_64 -#for instance. config LBD bool "Support for Large Block Devices" - depends on X86 || (MIPS && 32BIT) || PPC32 || (S390 && !64BIT) || SUPERH || UML + depends on !64BIT help Say Y here if you want to attach large (bigger than 2TB) discs to your machine, or if you want to have a raid or loopback device @@ -44,7 +42,7 @@ config BLK_DEV_IO_TRACE config LSF bool "Support for Large Single Files" - depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML + depends on !64BIT help Say Y here if you want to be able to handle very large files (bigger than 2TB), otherwise say N. diff --git a/include/asm-avr32/types.h b/include/asm-avr32/types.h index 3f47db9675a..2bff153a32e 100644 --- a/include/asm-avr32/types.h +++ b/include/asm-avr32/types.h @@ -57,11 +57,6 @@ typedef unsigned long long u64; typedef u32 dma_addr_t; -#ifdef CONFIG_LBD -typedef u64 sector_t; -#define HAVE_SECTOR_T -#endif - #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-h8300/types.h b/include/asm-h8300/types.h index da2402b8654..2a8b1b2be78 100644 --- a/include/asm-h8300/types.h +++ b/include/asm-h8300/types.h @@ -55,12 +55,6 @@ typedef unsigned long long u64; typedef u32 dma_addr_t; -#define HAVE_SECTOR_T -typedef u64 sector_t; - -#define HAVE_BLKCNT_T -typedef u64 blkcnt_t; - #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ diff --git a/include/asm-i386/types.h b/include/asm-i386/types.h index 4b4b295ccdb..ad0a55bd782 100644 --- a/include/asm-i386/types.h +++ b/include/asm-i386/types.h @@ -57,16 +57,6 @@ typedef u32 dma_addr_t; #endif typedef u64 dma64_addr_t; -#ifdef CONFIG_LBD -typedef u64 sector_t; -#define HAVE_SECTOR_T -#endif - -#ifdef CONFIG_LSF -typedef u64 blkcnt_t; -#define HAVE_BLKCNT_T -#endif - #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h index 2b52e180c6f..63a13c5bd83 100644 --- a/include/asm-mips/types.h +++ b/include/asm-mips/types.h @@ -93,16 +93,6 @@ typedef unsigned long long phys_t; typedef unsigned long phys_t; #endif -#ifdef CONFIG_LBD -typedef u64 sector_t; -#define HAVE_SECTOR_T -#endif - -#ifdef CONFIG_LSF -typedef u64 blkcnt_t; -#define HAVE_BLKCNT_T -#endif - #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/types.h b/include/asm-powerpc/types.h index d6fb56b8045..3b363757a2b 100644 --- a/include/asm-powerpc/types.h +++ b/include/asm-powerpc/types.h @@ -97,16 +97,6 @@ typedef struct { unsigned long env; } func_descr_t; -#ifdef CONFIG_LBD -typedef u64 sector_t; -#define HAVE_SECTOR_T -#endif - -#ifdef CONFIG_LSF -typedef u64 blkcnt_t; -#define HAVE_BLKCNT_T -#endif - #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-s390/types.h b/include/asm-s390/types.h index ae2951cc83a..fc5d7cf1932 100644 --- a/include/asm-s390/types.h +++ b/include/asm-s390/types.h @@ -87,16 +87,6 @@ typedef union { } subreg; } register_pair; -#ifdef CONFIG_LBD -typedef u64 sector_t; -#define HAVE_SECTOR_T -#endif - -#ifdef CONFIG_LSF -typedef u64 blkcnt_t; -#define HAVE_BLKCNT_T -#endif - #endif /* ! __s390x__ */ #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-sh/types.h b/include/asm-sh/types.h index 3c09dd4ca31..fd00dbb82f8 100644 --- a/include/asm-sh/types.h +++ b/include/asm-sh/types.h @@ -52,16 +52,6 @@ typedef unsigned long long u64; typedef u32 dma_addr_t; -#ifdef CONFIG_LBD -typedef u64 sector_t; -#define HAVE_SECTOR_T -#endif - -#ifdef CONFIG_LSF -typedef u64 blkcnt_t; -#define HAVE_BLKCNT_T -#endif - #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-x86_64/types.h b/include/asm-x86_64/types.h index c86c2e6793e..2d4491aae28 100644 --- a/include/asm-x86_64/types.h +++ b/include/asm-x86_64/types.h @@ -48,9 +48,6 @@ typedef unsigned long long u64; typedef u64 dma64_addr_t; typedef u64 dma_addr_t; -typedef u64 sector_t; -#define HAVE_SECTOR_T - #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/include/linux/types.h b/include/linux/types.h index 745c409ebbb..0351bf2fac8 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -136,15 +136,19 @@ typedef __s64 int64_t; * * Linux always considers sectors to be 512 bytes long independently * of the devices real block size. - * - * If required, asm/types.h can override it and define - * HAVE_SECTOR_T */ -#ifndef HAVE_SECTOR_T +#ifdef CONFIG_LBD +typedef u64 sector_t; +#else typedef unsigned long sector_t; #endif -#ifndef HAVE_BLKCNT_T +/* + * The type of the inode's block count. + */ +#ifdef CONFIG_LSF +typedef u64 blkcnt_t; +#else typedef unsigned long blkcnt_t; #endif -- cgit v1.2.3-70-g09d2 From a866374aecc90c7d90619727ccd851ac096b2fc7 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 6 Dec 2006 20:32:20 -0800 Subject: [PATCH] mm: pagefault_{disable,enable}() Introduce pagefault_{disable,enable}() and use these where previously we did manual preempt increments/decrements to make the pagefault handler do the atomic thing. Currently they still rely on the increased preempt count, but do not rely on the disabled preemption, this might go away in the future. (NOTE: the extra barrier() in pagefault_disable might fix some holes on machines which have too many registers for their own good) [heiko.carstens@de.ibm.com: s390 fix] Signed-off-by: Peter Zijlstra Acked-by: Nick Piggin Cc: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/futex.c | 4 ++-- arch/i386/mm/highmem.c | 10 ++++------ arch/mips/mm/highmem.c | 10 ++++------ arch/s390/lib/uaccess_std.c | 6 +++--- arch/sparc/mm/highmem.c | 8 +++----- include/asm-frv/highmem.h | 5 ++--- include/asm-generic/futex.h | 4 ++-- include/asm-i386/futex.h | 4 ++-- include/asm-ia64/futex.h | 4 ++-- include/asm-mips/futex.h | 4 ++-- include/asm-parisc/futex.h | 4 ++-- include/asm-powerpc/futex.h | 4 ++-- include/asm-ppc/highmem.h | 8 +++----- include/asm-sparc64/futex.h | 4 ++-- include/asm-x86_64/futex.h | 4 ++-- include/linux/uaccess.h | 39 +++++++++++++++++++++++++++++++++++++-- kernel/futex.c | 28 ++++++++++++++-------------- 17 files changed, 88 insertions(+), 62 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c index eae874a970c..53dc5ed1ebd 100644 --- a/arch/frv/kernel/futex.c +++ b/arch/frv/kernel/futex.c @@ -200,7 +200,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -223,7 +223,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) break; } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c index f9f647cdbc7..178bbfe6cba 100644 --- a/arch/i386/mm/highmem.c +++ b/arch/i386/mm/highmem.c @@ -32,7 +32,7 @@ void *kmap_atomic(struct page *page, enum km_type type) unsigned long vaddr; /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ - inc_preempt_count(); + pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -52,8 +52,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type) #ifdef CONFIG_DEBUG_HIGHMEM if (vaddr >= PAGE_OFFSET && vaddr < (unsigned long)high_memory) { - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); return; } @@ -68,8 +67,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type) */ kpte_clear_flush(kmap_pte-idx, vaddr); - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); } /* This is the same as kmap_atomic() but can map memory that doesn't @@ -80,7 +78,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) enum fixed_addresses idx; unsigned long vaddr; - inc_preempt_count(); + pagefault_disable(); idx = type + KM_TYPE_NR*smp_processor_id(); vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c index 99ebf3ccc22..675502ada5a 100644 --- a/arch/mips/mm/highmem.c +++ b/arch/mips/mm/highmem.c @@ -39,7 +39,7 @@ void *__kmap_atomic(struct page *page, enum km_type type) unsigned long vaddr; /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ - inc_preempt_count(); + pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -62,8 +62,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type) enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); if (vaddr < FIXADDR_START) { // FIXME - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); return; } @@ -78,8 +77,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type) local_flush_tlb_one(vaddr); #endif - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); } #ifndef CONFIG_LIMITED_DMA @@ -92,7 +90,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) enum fixed_addresses idx; unsigned long vaddr; - inc_preempt_count(); + pagefault_disable(); idx = type + KM_TYPE_NR*smp_processor_id(); vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c index 2d549ed2e11..bbaca66fa29 100644 --- a/arch/s390/lib/uaccess_std.c +++ b/arch/s390/lib/uaccess_std.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #ifndef __s390x__ @@ -258,7 +258,7 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old) { int oldval = 0, newval, ret; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -284,7 +284,7 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old) default: ret = -ENOSYS; } - dec_preempt_count(); + pagefault_enable(); *old = oldval; return ret; } diff --git a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c index 4d8ed9c6518..01fc6c25429 100644 --- a/arch/sparc/mm/highmem.c +++ b/arch/sparc/mm/highmem.c @@ -35,7 +35,7 @@ void *kmap_atomic(struct page *page, enum km_type type) unsigned long vaddr; /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ - inc_preempt_count(); + pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -70,8 +70,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type) unsigned long idx = type + KM_TYPE_NR*smp_processor_id(); if (vaddr < FIXADDR_START) { // FIXME - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); return; } @@ -97,8 +96,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type) #endif #endif - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); } /* We may be fed a pagetable here by ptep_to_xxx and others. */ diff --git a/include/asm-frv/highmem.h b/include/asm-frv/highmem.h index 0f390f41f81..ff4d6cdeb15 100644 --- a/include/asm-frv/highmem.h +++ b/include/asm-frv/highmem.h @@ -115,7 +115,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type) { unsigned long paddr; - inc_preempt_count(); + pagefault_disable(); paddr = page_to_phys(page); switch (type) { @@ -170,8 +170,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) default: BUG(); } - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); } #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h index df893c16031..f422df0956a 100644 --- a/include/asm-generic/futex.h +++ b/include/asm-generic/futex.h @@ -21,7 +21,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -33,7 +33,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) ret = -ENOSYS; } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h index 946d97cfea2..438ef0ec710 100644 --- a/include/asm-i386/futex.h +++ b/include/asm-i386/futex.h @@ -56,7 +56,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - inc_preempt_count(); + pagefault_disable(); if (op == FUTEX_OP_SET) __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); @@ -88,7 +88,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) } } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/include/asm-ia64/futex.h b/include/asm-ia64/futex.h index 07d77f3a8cb..8a98a265413 100644 --- a/include/asm-ia64/futex.h +++ b/include/asm-ia64/futex.h @@ -59,7 +59,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -83,7 +83,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) ret = -ENOSYS; } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h index 927a216bd53..47e5679c235 100644 --- a/include/asm-mips/futex.h +++ b/include/asm-mips/futex.h @@ -88,7 +88,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -115,7 +115,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) ret = -ENOSYS; } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/include/asm-parisc/futex.h b/include/asm-parisc/futex.h index d84bbb283fd..dbee6e60aa8 100644 --- a/include/asm-parisc/futex.h +++ b/include/asm-parisc/futex.h @@ -21,7 +21,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -33,7 +33,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) ret = -ENOSYS; } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h index 936422e5489..3f3673fd3ff 100644 --- a/include/asm-powerpc/futex.h +++ b/include/asm-powerpc/futex.h @@ -43,7 +43,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -65,7 +65,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) ret = -ENOSYS; } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/include/asm-ppc/highmem.h b/include/asm-ppc/highmem.h index 1d2c4ef81c2..f7b21ee302b 100644 --- a/include/asm-ppc/highmem.h +++ b/include/asm-ppc/highmem.h @@ -79,7 +79,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type) unsigned long vaddr; /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ - inc_preempt_count(); + pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -101,8 +101,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) unsigned int idx = type + KM_TYPE_NR*smp_processor_id(); if (vaddr < KMAP_FIX_BEGIN) { // FIXME - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); return; } @@ -115,8 +114,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) pte_clear(&init_mm, vaddr, kmap_pte+idx); flush_tlb_page(NULL, vaddr); #endif - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); } static inline struct page *kmap_atomic_to_page(void *ptr) diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h index 7392fc4a954..876312fe82c 100644 --- a/include/asm-sparc64/futex.h +++ b/include/asm-sparc64/futex.h @@ -45,7 +45,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -67,7 +67,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) ret = -ENOSYS; } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/include/asm-x86_64/futex.h b/include/asm-x86_64/futex.h index 9804bf07b09..5cdfb08013c 100644 --- a/include/asm-x86_64/futex.h +++ b/include/asm-x86_64/futex.h @@ -55,7 +55,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -78,7 +78,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) ret = -ENOSYS; } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index a48d7f11c7b..67918c22339 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h @@ -1,8 +1,43 @@ #ifndef __LINUX_UACCESS_H__ #define __LINUX_UACCESS_H__ +#include #include +/* + * These routines enable/disable the pagefault handler in that + * it will not take any locks and go straight to the fixup table. + * + * They have great resemblance to the preempt_disable/enable calls + * and in fact they are identical; this is because currently there is + * no other way to make the pagefault handlers do this. So we do + * disable preemption but we don't necessarily care about that. + */ +static inline void pagefault_disable(void) +{ + inc_preempt_count(); + /* + * make sure to have issued the store before a pagefault + * can hit. + */ + barrier(); +} + +static inline void pagefault_enable(void) +{ + /* + * make sure to issue those last loads/stores before enabling + * the pagefault handler again. + */ + barrier(); + dec_preempt_count(); + /* + * make sure we do.. + */ + barrier(); + preempt_check_resched(); +} + #ifndef ARCH_HAS_NOCACHE_UACCESS static inline unsigned long __copy_from_user_inatomic_nocache(void *to, @@ -35,9 +70,9 @@ static inline unsigned long __copy_from_user_nocache(void *to, ({ \ long ret; \ \ - inc_preempt_count(); \ + pagefault_disable(); \ ret = __get_user(retval, addr); \ - dec_preempt_count(); \ + pagefault_enable(); \ ret; \ }) diff --git a/kernel/futex.c b/kernel/futex.c index 93ef30ba209..af7b81cbde3 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -282,9 +282,9 @@ static inline int get_futex_value_locked(u32 *dest, u32 __user *from) { int ret; - inc_preempt_count(); + pagefault_disable(); ret = __copy_from_user_inatomic(dest, from, sizeof(u32)); - dec_preempt_count(); + pagefault_enable(); return ret ? -EFAULT : 0; } @@ -585,9 +585,9 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) if (!(uval & FUTEX_OWNER_DIED)) { newval = FUTEX_WAITERS | new_owner->pid; - inc_preempt_count(); + pagefault_disable(); curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); - dec_preempt_count(); + pagefault_enable(); if (curval == -EFAULT) return -EFAULT; if (curval != uval) @@ -618,9 +618,9 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval) * There is no waiter, so we unlock the futex. The owner died * bit has not to be preserved here. We are the owner: */ - inc_preempt_count(); + pagefault_disable(); oldval = futex_atomic_cmpxchg_inatomic(uaddr, uval, 0); - dec_preempt_count(); + pagefault_enable(); if (oldval == -EFAULT) return oldval; @@ -1158,9 +1158,9 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, */ newval = current->pid; - inc_preempt_count(); + pagefault_disable(); curval = futex_atomic_cmpxchg_inatomic(uaddr, 0, newval); - dec_preempt_count(); + pagefault_enable(); if (unlikely(curval == -EFAULT)) goto uaddr_faulted; @@ -1183,9 +1183,9 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, uval = curval; newval = uval | FUTEX_WAITERS; - inc_preempt_count(); + pagefault_disable(); curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); - dec_preempt_count(); + pagefault_enable(); if (unlikely(curval == -EFAULT)) goto uaddr_faulted; @@ -1215,10 +1215,10 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, newval = current->pid | FUTEX_OWNER_DIED | FUTEX_WAITERS; - inc_preempt_count(); + pagefault_disable(); curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); - dec_preempt_count(); + pagefault_enable(); if (unlikely(curval == -EFAULT)) goto uaddr_faulted; @@ -1390,9 +1390,9 @@ retry_locked: * anyone else up: */ if (!(uval & FUTEX_OWNER_DIED)) { - inc_preempt_count(); + pagefault_disable(); uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0); - dec_preempt_count(); + pagefault_enable(); } if (unlikely(uval == -EFAULT)) -- cgit v1.2.3-70-g09d2 From e18b890bb0881bbab6f4f1a6cd20d9c60d66b003 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 6 Dec 2006 20:33:20 -0800 Subject: [PATCH] slab: remove kmem_cache_t Replace all uses of kmem_cache_t with struct kmem_cache. The patch was generated using the following script: #!/bin/sh # # Replace one string by another in all the kernel sources. # set -e for file in `find * -name "*.c" -o -name "*.h"|xargs grep -l $1`; do quilt add $file sed -e "1,\$s/$1/$2/g" $file >/tmp/$$ mv /tmp/$$ $file quilt refresh done The script was run like this sh replace kmem_cache_t "struct kmem_cache" Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DMA-API.txt | 4 ++-- arch/arm/mach-s3c2410/dma.c | 4 ++-- arch/arm26/mm/memc.c | 6 +++--- arch/frv/mm/pgalloc.c | 6 +++--- arch/i386/mm/init.c | 4 ++-- arch/i386/mm/pgtable.c | 6 +++--- arch/ia64/ia32/ia32_support.c | 2 +- arch/ia64/ia32/sys_ia32.c | 2 +- arch/powerpc/kernel/rtas_flash.c | 4 ++-- arch/powerpc/mm/hugetlbpage.c | 2 +- arch/powerpc/mm/init_64.c | 6 +++--- arch/powerpc/platforms/cell/spufs/inode.c | 4 ++-- arch/sh/kernel/cpu/sh4/sq.c | 2 +- arch/sh/mm/pmb.c | 6 +++--- arch/sparc64/mm/init.c | 4 ++-- arch/sparc64/mm/tsb.c | 2 +- block/cfq-iosched.c | 4 ++-- block/ll_rw_blk.c | 6 +++--- drivers/block/aoe/aoeblk.c | 2 +- drivers/ieee1394/eth1394.c | 2 +- drivers/md/dm-crypt.c | 2 +- drivers/md/dm-mpath.c | 2 +- drivers/md/dm-snap.c | 6 +++--- drivers/md/dm.c | 4 ++-- drivers/md/kcopyd.c | 2 +- drivers/md/raid5.c | 4 ++-- drivers/message/i2o/i2o_block.h | 2 +- drivers/pci/msi.c | 2 +- drivers/s390/block/dasd_devmap.c | 2 +- drivers/s390/block/dasd_int.h | 2 +- drivers/s390/scsi/zfcp_def.h | 6 +++--- drivers/scsi/aic94xx/aic94xx.h | 4 ++-- drivers/scsi/aic94xx/aic94xx_hwi.c | 2 +- drivers/scsi/aic94xx/aic94xx_init.c | 4 ++-- drivers/scsi/libsas/sas_init.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 2 +- drivers/scsi/qla4xxx/ql4_os.c | 2 +- drivers/scsi/scsi.c | 2 +- drivers/scsi/scsi_lib.c | 4 ++-- drivers/scsi/scsi_tgt_lib.c | 2 +- drivers/usb/host/hc_crisv10.c | 6 +++--- drivers/usb/host/uhci-hcd.c | 2 +- drivers/usb/mon/mon_text.c | 6 +++--- fs/adfs/super.c | 4 ++-- fs/affs/super.c | 4 ++-- fs/afs/super.c | 6 +++--- fs/aio.c | 4 ++-- fs/befs/linuxvfs.c | 4 ++-- fs/bfs/inode.c | 4 ++-- fs/bio.c | 4 ++-- fs/block_dev.c | 4 ++-- fs/buffer.c | 4 ++-- fs/cifs/cifsfs.c | 14 +++++++------- fs/cifs/transport.c | 2 +- fs/coda/inode.c | 4 ++-- fs/configfs/configfs_internal.h | 2 +- fs/configfs/mount.c | 2 +- fs/dcache.c | 6 +++--- fs/dcookies.c | 2 +- fs/dlm/memory.c | 2 +- fs/dnotify.c | 2 +- fs/dquot.c | 2 +- fs/ecryptfs/main.c | 2 +- fs/efs/super.c | 4 ++-- fs/eventpoll.c | 4 ++-- fs/ext2/super.c | 4 ++-- fs/ext3/super.c | 4 ++-- fs/ext4/super.c | 4 ++-- fs/fat/cache.c | 4 ++-- fs/fat/inode.c | 4 ++-- fs/fcntl.c | 2 +- fs/freevxfs/vxfs_inode.c | 2 +- fs/fuse/dev.c | 2 +- fs/fuse/inode.c | 4 ++-- fs/gfs2/main.c | 4 ++-- fs/gfs2/util.c | 6 +++--- fs/gfs2/util.h | 6 +++--- fs/hfs/super.c | 4 ++-- fs/hfsplus/super.c | 4 ++-- fs/hpfs/super.c | 4 ++-- fs/hugetlbfs/inode.c | 4 ++-- fs/inode.c | 4 ++-- fs/inotify_user.c | 4 ++-- fs/isofs/inode.c | 4 ++-- fs/jbd/journal.c | 6 +++--- fs/jbd/revoke.c | 4 ++-- fs/jbd2/journal.c | 6 +++--- fs/jbd2/revoke.c | 4 ++-- fs/jffs/inode-v23.c | 4 ++-- fs/jffs/jffs_fm.c | 4 ++-- fs/jffs2/malloc.c | 18 +++++++++--------- fs/jffs2/super.c | 4 ++-- fs/jfs/jfs_metapage.c | 4 ++-- fs/jfs/super.c | 4 ++-- fs/locks.c | 4 ++-- fs/mbcache.c | 2 +- fs/minix/inode.c | 4 ++-- fs/namespace.c | 2 +- fs/ncpfs/inode.c | 4 ++-- fs/nfs/direct.c | 2 +- fs/nfs/inode.c | 4 ++-- fs/nfs/pagelist.c | 2 +- fs/nfs/read.c | 2 +- fs/nfs/write.c | 2 +- fs/nfsd/nfs4state.c | 10 +++++----- fs/ocfs2/dlm/dlmfs.c | 4 ++-- fs/ocfs2/dlm/dlmmaster.c | 2 +- fs/ocfs2/extent_map.c | 2 +- fs/ocfs2/inode.h | 2 +- fs/ocfs2/super.c | 4 ++-- fs/ocfs2/uptodate.c | 2 +- fs/openpromfs/inode.c | 4 ++-- fs/proc/inode.c | 4 ++-- fs/qnx4/inode.c | 4 ++-- fs/reiserfs/super.c | 4 ++-- fs/romfs/inode.c | 4 ++-- fs/smbfs/inode.c | 4 ++-- fs/smbfs/request.c | 2 +- fs/sysfs/mount.c | 2 +- fs/sysfs/sysfs.h | 2 +- fs/sysv/inode.c | 4 ++-- fs/udf/super.c | 4 ++-- fs/ufs/super.c | 4 ++-- include/acpi/platform/aclinux.h | 2 +- include/asm-arm26/pgalloc.h | 2 +- include/asm-i386/pgtable.h | 10 +++++----- include/asm-powerpc/pgalloc.h | 2 +- include/asm-sparc64/pgalloc.h | 2 +- include/linux/delayacct.h | 2 +- include/linux/i2o.h | 2 +- include/linux/jbd.h | 2 +- include/linux/jbd2.h | 2 +- include/linux/raid/raid5.h | 2 +- include/linux/rmap.h | 2 +- include/linux/skbuff.h | 2 +- include/linux/taskstats_kern.h | 2 +- include/net/dst.h | 2 +- include/net/inet_hashtables.h | 6 +++--- include/net/neighbour.h | 2 +- include/net/netfilter/nf_conntrack_expect.h | 2 +- include/net/request_sock.h | 2 +- include/net/sock.h | 2 +- include/net/timewait_sock.h | 2 +- include/scsi/libsas.h | 4 ++-- ipc/mqueue.c | 4 ++-- kernel/delayacct.c | 2 +- kernel/fork.c | 16 ++++++++-------- kernel/pid.c | 2 +- kernel/posix-timers.c | 2 +- kernel/signal.c | 2 +- kernel/taskstats.c | 2 +- kernel/user.c | 2 +- lib/idr.c | 4 ++-- lib/radix-tree.c | 4 ++-- net/bridge/br_fdb.c | 2 +- net/core/flow.c | 2 +- net/core/skbuff.c | 8 ++++---- net/core/sock.c | 2 +- net/dccp/ackvec.c | 4 ++-- net/dccp/ccid.c | 6 +++--- net/dccp/ccid.h | 4 ++-- net/dccp/ccids/lib/loss_interval.h | 2 +- net/dccp/ccids/lib/packet_history.h | 4 ++-- net/decnet/dn_table.c | 2 +- net/ipv4/fib_hash.c | 4 ++-- net/ipv4/fib_trie.c | 2 +- net/ipv4/inet_hashtables.c | 4 ++-- net/ipv4/inetpeer.c | 2 +- net/ipv4/ipmr.c | 2 +- net/ipv4/ipvs/ip_vs_conn.c | 2 +- net/ipv4/netfilter/ip_conntrack_core.c | 4 ++-- net/ipv6/ip6_fib.c | 2 +- net/ipv6/xfrm6_tunnel.c | 2 +- net/netfilter/nf_conntrack_core.c | 6 +++--- net/netfilter/nf_conntrack_expect.c | 2 +- net/netfilter/xt_hashlimit.c | 2 +- net/sctp/protocol.c | 4 ++-- net/sctp/sm_make_chunk.c | 2 +- net/sctp/socket.c | 2 +- net/socket.c | 4 ++-- net/sunrpc/rpc_pipe.c | 4 ++-- net/sunrpc/sched.c | 4 ++-- net/tipc/handler.c | 2 +- net/xfrm/xfrm_input.c | 2 +- net/xfrm/xfrm_policy.c | 2 +- security/keys/key.c | 2 +- security/selinux/avc.c | 2 +- security/selinux/hooks.c | 2 +- security/selinux/ss/avtab.c | 2 +- 189 files changed, 332 insertions(+), 332 deletions(-) (limited to 'include/asm-powerpc') diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index 05431621c86..8621a064f7e 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -77,7 +77,7 @@ To get this part of the dma_ API, you must #include Many drivers need lots of small dma-coherent memory regions for DMA descriptors or I/O buffers. Rather than allocating in units of a page or more using dma_alloc_coherent(), you can use DMA pools. These work -much like a kmem_cache_t, except that they use the dma-coherent allocator +much like a struct kmem_cache, except that they use the dma-coherent allocator not __get_free_pages(). Also, they understand common hardware constraints for alignment, like queue heads needing to be aligned on N byte boundaries. @@ -94,7 +94,7 @@ The pool create() routines initialize a pool of dma-coherent buffers for use with a given device. It must be called in a context which can sleep. -The "name" is for diagnostics (like a kmem_cache_t name); dev and size +The "name" is for diagnostics (like a struct kmem_cache name); dev and size are like what you'd pass to dma_alloc_coherent(). The device's hardware alignment requirement for this type of data is "align" (which is expressed in bytes, and must be a power of two). If your device has no boundary diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index 3d211dc2f2f..01abb0ace23 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -40,7 +40,7 @@ /* io map for dma */ static void __iomem *dma_base; -static kmem_cache_t *dma_kmem; +static struct kmem_cache *dma_kmem; struct s3c24xx_dma_selection dma_sel; @@ -1271,7 +1271,7 @@ struct sysdev_class dma_sysclass = { /* kmem cache implementation */ -static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f) +static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f) { memset(p, 0, sizeof(struct s3c2410_dma_buf)); } diff --git a/arch/arm26/mm/memc.c b/arch/arm26/mm/memc.c index 34def6397c3..f2901581d4d 100644 --- a/arch/arm26/mm/memc.c +++ b/arch/arm26/mm/memc.c @@ -24,7 +24,7 @@ #define MEMC_TABLE_SIZE (256*sizeof(unsigned long)) -kmem_cache_t *pte_cache, *pgd_cache; +struct kmem_cache *pte_cache, *pgd_cache; int page_nr; /* @@ -162,12 +162,12 @@ void __init create_memmap_holes(struct meminfo *mi) { } -static void pte_cache_ctor(void *pte, kmem_cache_t *cache, unsigned long flags) +static void pte_cache_ctor(void *pte, struct kmem_cache *cache, unsigned long flags) { memzero(pte, sizeof(pte_t) * PTRS_PER_PTE); } -static void pgd_cache_ctor(void *pgd, kmem_cache_t *cache, unsigned long flags) +static void pgd_cache_ctor(void *pgd, struct kmem_cache *cache, unsigned long flags) { memzero(pgd + MEMC_TABLE_SIZE, USER_PTRS_PER_PGD * sizeof(pgd_t)); } diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c index f76dd03ddd9..19b13be114a 100644 --- a/arch/frv/mm/pgalloc.c +++ b/arch/frv/mm/pgalloc.c @@ -18,7 +18,7 @@ #include pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE))); -kmem_cache_t *pgd_cache; +struct kmem_cache *pgd_cache; pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { @@ -100,7 +100,7 @@ static inline void pgd_list_del(pgd_t *pgd) set_page_private(next, (unsigned long) pprev); } -void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) +void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; @@ -120,7 +120,7 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) } /* never called when PTRS_PER_PMD > 1 */ -void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused) +void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; /* can be called from interrupt context */ diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 167416155ee..a6a8e397dd8 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -699,8 +699,8 @@ int remove_memory(u64 start, u64 size) #endif #endif -kmem_cache_t *pgd_cache; -kmem_cache_t *pmd_cache; +struct kmem_cache *pgd_cache; +struct kmem_cache *pmd_cache; void __init pgtable_cache_init(void) { diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c index 10126e3f817..33be236fc6a 100644 --- a/arch/i386/mm/pgtable.c +++ b/arch/i386/mm/pgtable.c @@ -193,7 +193,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) return pte; } -void pmd_ctor(void *pmd, kmem_cache_t *cache, unsigned long flags) +void pmd_ctor(void *pmd, struct kmem_cache *cache, unsigned long flags) { memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t)); } @@ -233,7 +233,7 @@ static inline void pgd_list_del(pgd_t *pgd) set_page_private(next, (unsigned long)pprev); } -void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) +void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; @@ -253,7 +253,7 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) } /* never called when PTRS_PER_PMD > 1 */ -void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused) +void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; /* can be called from interrupt context */ diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c index c187743965a..6af400a12ca 100644 --- a/arch/ia64/ia32/ia32_support.c +++ b/arch/ia64/ia32/ia32_support.c @@ -249,7 +249,7 @@ ia32_init (void) #if PAGE_SHIFT > IA32_PAGE_SHIFT { - extern kmem_cache_t *partial_page_cachep; + extern struct kmem_cache *partial_page_cachep; partial_page_cachep = kmem_cache_create("partial_page_cache", sizeof(struct partial_page), 0, 0, diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 9d6a3f21014..a4a6e1463af 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -254,7 +254,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro } /* SLAB cache for partial_page structures */ -kmem_cache_t *partial_page_cachep; +struct kmem_cache *partial_page_cachep; /* * init partial_page_list. diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index b9561d30051..7d0f13fecc0 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -101,7 +101,7 @@ struct flash_block_list_header { /* just the header of flash_block_list */ static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; /* Use slab cache to guarantee 4k alignment */ -static kmem_cache_t *flash_block_cache = NULL; +static struct kmem_cache *flash_block_cache = NULL; #define FLASH_BLOCK_LIST_VERSION (1UL) @@ -286,7 +286,7 @@ static ssize_t rtas_flash_read(struct file *file, char __user *buf, } /* constructor for flash_block_cache */ -void rtas_block_ctor(void *ptr, kmem_cache_t *cache, unsigned long flags) +void rtas_block_ctor(void *ptr, struct kmem_cache *cache, unsigned long flags) { memset(ptr, 0, RTAS_BLK_SIZE); } diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 424a8f57e15..89c836d5480 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -1047,7 +1047,7 @@ repeat: return err; } -static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) +static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags) { memset(addr, 0, kmem_cache_size(cache)); } diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 9a178549cbc..d12a87ec5ae 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -141,7 +141,7 @@ static int __init setup_kcore(void) } module_init(setup_kcore); -static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) +static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags) { memset(addr, 0, kmem_cache_size(cache)); } @@ -166,9 +166,9 @@ static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { /* Hugepages need one extra cache, initialized in hugetlbpage.c. We * can't put into the tables above, because HPAGE_SHIFT is not compile * time constant. */ -kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1]; +struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1]; #else -kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; +struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; #endif void pgtable_cache_init(void) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 7edfcc9d285..e3af9112c02 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -40,7 +40,7 @@ #include "spufs.h" -static kmem_cache_t *spufs_inode_cache; +static struct kmem_cache *spufs_inode_cache; char *isolated_loader; static struct inode * @@ -65,7 +65,7 @@ spufs_destroy_inode(struct inode *inode) } static void -spufs_init_once(void *p, kmem_cache_t * cachep, unsigned long flags) +spufs_init_once(void *p, struct kmem_cache * cachep, unsigned long flags) { struct spufs_inode_info *ei = p; diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c index 55f43506995..0c9ea38d2ca 100644 --- a/arch/sh/kernel/cpu/sh4/sq.c +++ b/arch/sh/kernel/cpu/sh4/sq.c @@ -38,7 +38,7 @@ struct sq_mapping { static struct sq_mapping *sq_mapping_list; static DEFINE_SPINLOCK(sq_mapping_lock); -static kmem_cache_t *sq_cache; +static struct kmem_cache *sq_cache; static unsigned long *sq_bitmap; #define store_queue_barrier() \ diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c index 92e745341e4..b60ad83a763 100644 --- a/arch/sh/mm/pmb.c +++ b/arch/sh/mm/pmb.c @@ -30,7 +30,7 @@ #define NR_PMB_ENTRIES 16 -static kmem_cache_t *pmb_cache; +static struct kmem_cache *pmb_cache; static unsigned long pmb_map; static struct pmb_entry pmb_init_map[] = { @@ -283,7 +283,7 @@ void pmb_unmap(unsigned long addr) } while (pmbe); } -static void pmb_cache_ctor(void *pmb, kmem_cache_t *cachep, unsigned long flags) +static void pmb_cache_ctor(void *pmb, struct kmem_cache *cachep, unsigned long flags) { struct pmb_entry *pmbe = pmb; @@ -297,7 +297,7 @@ static void pmb_cache_ctor(void *pmb, kmem_cache_t *cachep, unsigned long flags) spin_unlock_irq(&pmb_list_lock); } -static void pmb_cache_dtor(void *pmb, kmem_cache_t *cachep, unsigned long flags) +static void pmb_cache_dtor(void *pmb, struct kmem_cache *cachep, unsigned long flags) { spin_lock_irq(&pmb_list_lock); pmb_list_del(pmb); diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 09cb7fccc03..a8e8802eed4 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -176,9 +176,9 @@ unsigned long sparc64_kern_sec_context __read_mostly; int bigkernel = 0; -kmem_cache_t *pgtable_cache __read_mostly; +struct kmem_cache *pgtable_cache __read_mostly; -static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) +static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags) { clear_page(addr); } diff --git a/arch/sparc64/mm/tsb.c b/arch/sparc64/mm/tsb.c index beaa02810f0..236d02f41a0 100644 --- a/arch/sparc64/mm/tsb.c +++ b/arch/sparc64/mm/tsb.c @@ -239,7 +239,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign } } -static kmem_cache_t *tsb_caches[8] __read_mostly; +static struct kmem_cache *tsb_caches[8] __read_mostly; static const char *tsb_cache_names[8] = { "tsb_8KB", diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 84e9be07318..78c6b312bd3 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -43,8 +43,8 @@ static int cfq_slice_idle = HZ / 125; #define RQ_CIC(rq) ((struct cfq_io_context*)(rq)->elevator_private) #define RQ_CFQQ(rq) ((rq)->elevator_private2) -static kmem_cache_t *cfq_pool; -static kmem_cache_t *cfq_ioc_pool; +static struct kmem_cache *cfq_pool; +static struct kmem_cache *cfq_ioc_pool; static DEFINE_PER_CPU(unsigned long, ioc_count); static struct completion *ioc_gone; diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index cc6e95f8e5d..a4ff3271d4a 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -44,17 +44,17 @@ static struct io_context *current_io_context(gfp_t gfp_flags, int node); /* * For the allocated request tables */ -static kmem_cache_t *request_cachep; +static struct kmem_cache *request_cachep; /* * For queue allocation */ -static kmem_cache_t *requestq_cachep; +static struct kmem_cache *requestq_cachep; /* * For io context allocations */ -static kmem_cache_t *iocontext_cachep; +static struct kmem_cache *iocontext_cachep; /* * Controlling structure to kblockd diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index aa25f8b09fe..478489c568a 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -12,7 +12,7 @@ #include #include "aoe.h" -static kmem_cache_t *buf_pool_cache; +static struct kmem_cache *buf_pool_cache; static ssize_t aoedisk_show_state(struct gendisk * disk, char *page) { diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 31e5cc49d61..27d6c642415 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -133,7 +133,7 @@ struct eth1394_node_info { #define ETH1394_DRIVER_NAME "eth1394" static const char driver_name[] = ETH1394_DRIVER_NAME; -static kmem_cache_t *packet_task_cache; +static struct kmem_cache *packet_task_cache; static struct hpsb_highlevel eth1394_highlevel; diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ed2d4ef27fd..c7bee4f2eed 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -101,7 +101,7 @@ struct crypt_config { #define MIN_POOL_PAGES 32 #define MIN_BIO_PAGES 8 -static kmem_cache_t *_crypt_io_pool; +static struct kmem_cache *_crypt_io_pool; /* * Different IV generation algorithms: diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index e77ee6fd104..cf8bf052138 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -101,7 +101,7 @@ typedef int (*action_fn) (struct pgpath *pgpath); #define MIN_IOS 256 /* Mempool size */ -static kmem_cache_t *_mpio_cache; +static struct kmem_cache *_mpio_cache; struct workqueue_struct *kmultipathd; static void process_queued_ios(struct work_struct *work); diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 91c7aa1fed0..b0ce2ce8227 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -88,8 +88,8 @@ struct pending_exception { * Hash table mapping origin volumes to lists of snapshots and * a lock to protect it */ -static kmem_cache_t *exception_cache; -static kmem_cache_t *pending_cache; +static struct kmem_cache *exception_cache; +static struct kmem_cache *pending_cache; static mempool_t *pending_pool; /* @@ -228,7 +228,7 @@ static int init_exception_table(struct exception_table *et, uint32_t size) return 0; } -static void exit_exception_table(struct exception_table *et, kmem_cache_t *mem) +static void exit_exception_table(struct exception_table *et, struct kmem_cache *mem) { struct list_head *slot; struct exception *ex, *next; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index fc4f743f3b5..7ec1b112a6d 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -121,8 +121,8 @@ struct mapped_device { }; #define MIN_IOS 256 -static kmem_cache_t *_io_cache; -static kmem_cache_t *_tio_cache; +static struct kmem_cache *_io_cache; +static struct kmem_cache *_tio_cache; static int __init local_init(void) { diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index b3c01496c73..b46f6c575f7 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -203,7 +203,7 @@ struct kcopyd_job { /* FIXME: this should scale with the number of pages */ #define MIN_JOBS 512 -static kmem_cache_t *_job_cache; +static struct kmem_cache *_job_cache; static mempool_t *_job_pool; /* diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 69c3e201fa3..52914d5cec7 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -348,7 +348,7 @@ static int grow_one_stripe(raid5_conf_t *conf) static int grow_stripes(raid5_conf_t *conf, int num) { - kmem_cache_t *sc; + struct kmem_cache *sc; int devs = conf->raid_disks; sprintf(conf->cache_name[0], "raid5/%s", mdname(conf->mddev)); @@ -397,7 +397,7 @@ static int resize_stripes(raid5_conf_t *conf, int newsize) LIST_HEAD(newstripes); struct disk_info *ndisks; int err = 0; - kmem_cache_t *sc; + struct kmem_cache *sc; int i; if (newsize <= conf->pool_size) diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h index d9fdc95b440..67f921b4419 100644 --- a/drivers/message/i2o/i2o_block.h +++ b/drivers/message/i2o/i2o_block.h @@ -64,7 +64,7 @@ /* I2O Block OSM mempool struct */ struct i2o_block_mempool { - kmem_cache_t *slab; + struct kmem_cache *slab; mempool_t *pool; }; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9fc9a34ef24..9168401401b 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -26,7 +26,7 @@ static DEFINE_SPINLOCK(msi_lock); static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; -static kmem_cache_t* msi_cachep; +static struct kmem_cache* msi_cachep; static int pci_msi_enable = 1; diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 17fdd8c9f74..cf28ccc5794 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -25,7 +25,7 @@ #include "dasd_int.h" -kmem_cache_t *dasd_page_cache; +struct kmem_cache *dasd_page_cache; EXPORT_SYMBOL_GPL(dasd_page_cache); /* diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 9f52004f6fc..dc5dd509434 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -474,7 +474,7 @@ extern struct dasd_profile_info_t dasd_global_profile; extern unsigned int dasd_profile_level; extern struct block_device_operations dasd_device_operations; -extern kmem_cache_t *dasd_page_cache; +extern struct kmem_cache *dasd_page_cache; struct dasd_ccw_req * dasd_kmalloc_request(char *, int, int, struct dasd_device *); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 74c0eac083e..32933ed54b8 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -1032,9 +1032,9 @@ struct zfcp_data { wwn_t init_wwpn; fcp_lun_t init_fcp_lun; char *driver_version; - kmem_cache_t *fsf_req_qtcb_cache; - kmem_cache_t *sr_buffer_cache; - kmem_cache_t *gid_pn_cache; + struct kmem_cache *fsf_req_qtcb_cache; + struct kmem_cache *sr_buffer_cache; + struct kmem_cache *gid_pn_cache; }; /** diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h index 71a031df7a3..32f513b1b78 100644 --- a/drivers/scsi/aic94xx/aic94xx.h +++ b/drivers/scsi/aic94xx/aic94xx.h @@ -56,8 +56,8 @@ /* 2*ITNL timeout + 1 second */ #define AIC94XX_SCB_TIMEOUT (5*HZ) -extern kmem_cache_t *asd_dma_token_cache; -extern kmem_cache_t *asd_ascb_cache; +extern struct kmem_cache *asd_dma_token_cache; +extern struct kmem_cache *asd_ascb_cache; extern char sas_addr_str[2*SAS_ADDR_SIZE + 1]; static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr) diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index af7e0113436..da94e126ca8 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -1047,7 +1047,7 @@ irqreturn_t asd_hw_isr(int irq, void *dev_id) static inline struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha, gfp_t gfp_flags) { - extern kmem_cache_t *asd_ascb_cache; + extern struct kmem_cache *asd_ascb_cache; struct asd_seq_data *seq = &asd_ha->seq; struct asd_ascb *ascb; unsigned long flags; diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 42302ef05ee..fbc82b00a41 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -450,8 +450,8 @@ static inline void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha) asd_ha->scb_pool = NULL; } -kmem_cache_t *asd_dma_token_cache; -kmem_cache_t *asd_ascb_cache; +struct kmem_cache *asd_dma_token_cache; +struct kmem_cache *asd_ascb_cache; static int asd_create_global_caches(void) { diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index d65bc4e0f21..2f0c07fc3f4 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -36,7 +36,7 @@ #include "../scsi_sas_internal.h" -kmem_cache_t *sas_task_cache; +struct kmem_cache *sas_task_cache; /*------------ SAS addr hash -----------*/ void sas_hash_addr(u8 *hashed, const u8 *sas_addr) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index cbe0cad83b6..d03523d3bf3 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -24,7 +24,7 @@ char qla2x00_version_str[40]; /* * SRB allocation cache */ -static kmem_cache_t *srb_cachep; +static struct kmem_cache *srb_cachep; /* * Ioctl related information. diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 969c9e43102..9ef693c8809 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -19,7 +19,7 @@ char qla4xxx_version_str[40]; /* * SRB allocation cache */ -static kmem_cache_t *srb_cachep; +static struct kmem_cache *srb_cachep; /* * Module parameter information and variables diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index fafc00deaad..24cffd98ee6 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -136,7 +136,7 @@ const char * scsi_device_type(unsigned type) EXPORT_SYMBOL(scsi_device_type); struct scsi_host_cmd_pool { - kmem_cache_t *slab; + struct kmem_cache *slab; unsigned int users; char *name; unsigned int slab_flags; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index fb616c69151..1748e27501c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -36,7 +36,7 @@ struct scsi_host_sg_pool { size_t size; char *name; - kmem_cache_t *slab; + struct kmem_cache *slab; mempool_t *pool; }; @@ -241,7 +241,7 @@ struct scsi_io_context { char sense[SCSI_SENSE_BUFFERSIZE]; }; -static kmem_cache_t *scsi_io_context_cache; +static struct kmem_cache *scsi_io_context_cache; static void scsi_end_async(struct request *req, int uptodate) { diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 386dbae17b4..d402aff5f31 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -33,7 +33,7 @@ #include "scsi_tgt_priv.h" static struct workqueue_struct *scsi_tgtd; -static kmem_cache_t *scsi_tgt_cmd_cache; +static struct kmem_cache *scsi_tgt_cmd_cache; /* * TODO: this struct will be killed when the block layer supports large bios diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c index 7fd872aa654..9325e46a68c 100644 --- a/drivers/usb/host/hc_crisv10.c +++ b/drivers/usb/host/hc_crisv10.c @@ -275,13 +275,13 @@ static volatile USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4))); static int zout_buffer[4] __attribute__ ((aligned (4))); /* Cache for allocating new EP and SB descriptors. */ -static kmem_cache_t *usb_desc_cache; +static struct kmem_cache *usb_desc_cache; /* Cache for the registers allocated in the top half. */ -static kmem_cache_t *top_half_reg_cache; +static struct kmem_cache *top_half_reg_cache; /* Cache for the data allocated in the isoc descr top half. */ -static kmem_cache_t *isoc_compl_cache; +static struct kmem_cache *isoc_compl_cache; static struct usb_bus *etrax_usb_bus; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 226bf3de8ed..e87692c31be 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -81,7 +81,7 @@ MODULE_PARM_DESC(debug, "Debug level"); static char *errbuf; #define ERRBUF_LEN (32 * 1024) -static kmem_cache_t *uhci_up_cachep; /* urb_priv */ +static struct kmem_cache *uhci_up_cachep; /* urb_priv */ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state); static void wakeup_rh(struct uhci_hcd *uhci); diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 46aecc8754f..05cf2c9a8f8 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -50,7 +50,7 @@ struct mon_event_text { #define SLAB_NAME_SZ 30 struct mon_reader_text { - kmem_cache_t *e_slab; + struct kmem_cache *e_slab; int nevents; struct list_head e_list; struct mon_reader r; /* In C, parent class can be placed anywhere */ @@ -63,7 +63,7 @@ struct mon_reader_text { char slab_name[SLAB_NAME_SZ]; }; -static void mon_text_ctor(void *, kmem_cache_t *, unsigned long); +static void mon_text_ctor(void *, struct kmem_cache *, unsigned long); /* * mon_text_submit @@ -450,7 +450,7 @@ const struct file_operations mon_fops_text = { /* * Slab interface: constructor. */ -static void mon_text_ctor(void *mem, kmem_cache_t *slab, unsigned long sflags) +static void mon_text_ctor(void *mem, struct kmem_cache *slab, unsigned long sflags) { /* * Nothing to initialize. No, really! diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 52eb10ca654..e5a205c9f42 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -212,7 +212,7 @@ static int adfs_statfs(struct dentry *dentry, struct kstatfs *buf) return 0; } -static kmem_cache_t *adfs_inode_cachep; +static struct kmem_cache *adfs_inode_cachep; static struct inode *adfs_alloc_inode(struct super_block *sb) { @@ -228,7 +228,7 @@ static void adfs_destroy_inode(struct inode *inode) kmem_cache_free(adfs_inode_cachep, ADFS_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct adfs_inode_info *ei = (struct adfs_inode_info *) foo; diff --git a/fs/affs/super.c b/fs/affs/super.c index 81c73ec09f6..3de93e79994 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -66,7 +66,7 @@ affs_write_super(struct super_block *sb) pr_debug("AFFS: write_super() at %lu, clean=%d\n", get_seconds(), clean); } -static kmem_cache_t * affs_inode_cachep; +static struct kmem_cache * affs_inode_cachep; static struct inode *affs_alloc_inode(struct super_block *sb) { @@ -83,7 +83,7 @@ static void affs_destroy_inode(struct inode *inode) kmem_cache_free(affs_inode_cachep, AFFS_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct affs_inode_info *ei = (struct affs_inode_info *) foo; diff --git a/fs/afs/super.c b/fs/afs/super.c index c6ead009bf7..9a351c4c756 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -35,7 +35,7 @@ struct afs_mount_params { struct afs_volume *volume; }; -static void afs_i_init_once(void *foo, kmem_cache_t *cachep, +static void afs_i_init_once(void *foo, struct kmem_cache *cachep, unsigned long flags); static int afs_get_sb(struct file_system_type *fs_type, @@ -65,7 +65,7 @@ static struct super_operations afs_super_ops = { .put_super = afs_put_super, }; -static kmem_cache_t *afs_inode_cachep; +static struct kmem_cache *afs_inode_cachep; static atomic_t afs_count_active_inodes; /*****************************************************************************/ @@ -384,7 +384,7 @@ static void afs_put_super(struct super_block *sb) /* * initialise an inode cache slab element prior to any use */ -static void afs_i_init_once(void *_vnode, kmem_cache_t *cachep, +static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep, unsigned long flags) { struct afs_vnode *vnode = (struct afs_vnode *) _vnode; diff --git a/fs/aio.c b/fs/aio.c index 287a1bc7a18..13aa9298abf 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -47,8 +47,8 @@ unsigned long aio_nr; /* current system wide number of aio requests */ unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ /*----end sysctl variables---*/ -static kmem_cache_t *kiocb_cachep; -static kmem_cache_t *kioctx_cachep; +static struct kmem_cache *kiocb_cachep; +static struct kmem_cache *kioctx_cachep; static struct workqueue_struct *aio_wq; diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 995348df94a..bce402eee55 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -61,7 +61,7 @@ static const struct super_operations befs_sops = { }; /* slab cache for befs_inode_info objects */ -static kmem_cache_t *befs_inode_cachep; +static struct kmem_cache *befs_inode_cachep; static const struct file_operations befs_dir_operations = { .read = generic_read_dir, @@ -289,7 +289,7 @@ befs_destroy_inode(struct inode *inode) kmem_cache_free(befs_inode_cachep, BEFS_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct befs_inode_info *bi = (struct befs_inode_info *) foo; diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 2e45123c8f7..eac175ed9f4 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -228,7 +228,7 @@ static void bfs_write_super(struct super_block *s) unlock_kernel(); } -static kmem_cache_t * bfs_inode_cachep; +static struct kmem_cache * bfs_inode_cachep; static struct inode *bfs_alloc_inode(struct super_block *sb) { @@ -244,7 +244,7 @@ static void bfs_destroy_inode(struct inode *inode) kmem_cache_free(bfs_inode_cachep, BFS_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct bfs_inode_info *bi = foo; diff --git a/fs/bio.c b/fs/bio.c index 50c40ce2cea..7ec737eda72 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -30,7 +30,7 @@ #define BIO_POOL_SIZE 256 -static kmem_cache_t *bio_slab __read_mostly; +static struct kmem_cache *bio_slab __read_mostly; #define BIOVEC_NR_POOLS 6 @@ -44,7 +44,7 @@ mempool_t *bio_split_pool __read_mostly; struct biovec_slab { int nr_vecs; char *name; - kmem_cache_t *slab; + struct kmem_cache *slab; }; /* diff --git a/fs/block_dev.c b/fs/block_dev.c index 063506705f2..13816b4d76f 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -235,7 +235,7 @@ static int block_fsync(struct file *filp, struct dentry *dentry, int datasync) */ static __cacheline_aligned_in_smp DEFINE_SPINLOCK(bdev_lock); -static kmem_cache_t * bdev_cachep __read_mostly; +static struct kmem_cache * bdev_cachep __read_mostly; static struct inode *bdev_alloc_inode(struct super_block *sb) { @@ -253,7 +253,7 @@ static void bdev_destroy_inode(struct inode *inode) kmem_cache_free(bdev_cachep, bdi); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct bdev_inode *ei = (struct bdev_inode *) foo; struct block_device *bdev = &ei->bdev; diff --git a/fs/buffer.c b/fs/buffer.c index 35527dca1db..a8ca0ac2148 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2908,7 +2908,7 @@ asmlinkage long sys_bdflush(int func, long data) /* * Buffer-head allocation */ -static kmem_cache_t *bh_cachep; +static struct kmem_cache *bh_cachep; /* * Once the number of bh's in the machine exceeds this level, we start @@ -2961,7 +2961,7 @@ void free_buffer_head(struct buffer_head *bh) EXPORT_SYMBOL(free_buffer_head); static void -init_buffer_head(void *data, kmem_cache_t *cachep, unsigned long flags) +init_buffer_head(void *data, struct kmem_cache *cachep, unsigned long flags) { if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 84168629cea..e6b5866e500 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -81,7 +81,7 @@ extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_mid_poolp; -extern kmem_cache_t *cifs_oplock_cachep; +extern struct kmem_cache *cifs_oplock_cachep; static int cifs_read_super(struct super_block *sb, void *data, @@ -232,11 +232,11 @@ static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) return generic_permission(inode, mask, NULL); } -static kmem_cache_t *cifs_inode_cachep; -static kmem_cache_t *cifs_req_cachep; -static kmem_cache_t *cifs_mid_cachep; -kmem_cache_t *cifs_oplock_cachep; -static kmem_cache_t *cifs_sm_req_cachep; +static struct kmem_cache *cifs_inode_cachep; +static struct kmem_cache *cifs_req_cachep; +static struct kmem_cache *cifs_mid_cachep; +struct kmem_cache *cifs_oplock_cachep; +static struct kmem_cache *cifs_sm_req_cachep; mempool_t *cifs_sm_req_poolp; mempool_t *cifs_req_poolp; mempool_t *cifs_mid_poolp; @@ -668,7 +668,7 @@ const struct file_operations cifs_dir_ops = { }; static void -cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags) +cifs_init_once(void *inode, struct kmem_cache * cachep, unsigned long flags) { struct cifsInodeInfo *cifsi = inode; diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 1f727765a8e..f80007eaebf 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -34,7 +34,7 @@ #include "cifs_debug.h" extern mempool_t *cifs_mid_poolp; -extern kmem_cache_t *cifs_oplock_cachep; +extern struct kmem_cache *cifs_oplock_cachep; static struct mid_q_entry * AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 50cedd2617d..b64659fa82d 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -38,7 +38,7 @@ static void coda_clear_inode(struct inode *); static void coda_put_super(struct super_block *); static int coda_statfs(struct dentry *dentry, struct kstatfs *buf); -static kmem_cache_t * coda_inode_cachep; +static struct kmem_cache * coda_inode_cachep; static struct inode *coda_alloc_inode(struct super_block *sb) { @@ -58,7 +58,7 @@ static void coda_destroy_inode(struct inode *inode) kmem_cache_free(coda_inode_cachep, ITOC(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct coda_inode_info *ei = (struct coda_inode_info *) foo; diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index 3f4ff7a242b..f92cd303d2c 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h @@ -49,7 +49,7 @@ struct configfs_dirent { #define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR) extern struct vfsmount * configfs_mount; -extern kmem_cache_t *configfs_dir_cachep; +extern struct kmem_cache *configfs_dir_cachep; extern int configfs_is_root(struct config_item *item); diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index 68bd5c93ca5..ed678529ebb 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -38,7 +38,7 @@ struct vfsmount * configfs_mount = NULL; struct super_block * configfs_sb = NULL; -kmem_cache_t *configfs_dir_cachep; +struct kmem_cache *configfs_dir_cachep; static int configfs_mnt_count = 0; static struct super_operations configfs_ops = { diff --git a/fs/dcache.c b/fs/dcache.c index fd4a428998e..a7c67cee5d8 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -43,7 +43,7 @@ static __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); EXPORT_SYMBOL(dcache_lock); -static kmem_cache_t *dentry_cache __read_mostly; +static struct kmem_cache *dentry_cache __read_mostly; #define DNAME_INLINE_LEN (sizeof(struct dentry)-offsetof(struct dentry,d_iname)) @@ -2072,10 +2072,10 @@ static void __init dcache_init(unsigned long mempages) } /* SLAB cache for __getname() consumers */ -kmem_cache_t *names_cachep __read_mostly; +struct kmem_cache *names_cachep __read_mostly; /* SLAB cache for file structures */ -kmem_cache_t *filp_cachep __read_mostly; +struct kmem_cache *filp_cachep __read_mostly; EXPORT_SYMBOL(d_genocide); diff --git a/fs/dcookies.c b/fs/dcookies.c index 0c4b0674854..21af1629f9b 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c @@ -37,7 +37,7 @@ struct dcookie_struct { static LIST_HEAD(dcookie_users); static DEFINE_MUTEX(dcookie_mutex); -static kmem_cache_t *dcookie_cache __read_mostly; +static struct kmem_cache *dcookie_cache __read_mostly; static struct list_head *dcookie_hashtable __read_mostly; static size_t hash_size __read_mostly; diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c index 989b608fd83..5352b03ff5a 100644 --- a/fs/dlm/memory.c +++ b/fs/dlm/memory.c @@ -15,7 +15,7 @@ #include "config.h" #include "memory.h" -static kmem_cache_t *lkb_cache; +static struct kmem_cache *lkb_cache; int dlm_memory_init(void) diff --git a/fs/dnotify.c b/fs/dnotify.c index e778b1737b7..1f26a2b9eee 100644 --- a/fs/dnotify.c +++ b/fs/dnotify.c @@ -23,7 +23,7 @@ int dir_notify_enable __read_mostly = 1; -static kmem_cache_t *dn_cache __read_mostly; +static struct kmem_cache *dn_cache __read_mostly; static void redo_inode_mask(struct inode *inode) { diff --git a/fs/dquot.c b/fs/dquot.c index c6ae6c0e0cf..f9cd5e23ebd 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -131,7 +131,7 @@ static struct quota_format_type *quota_formats; /* List of registered formats */ static struct quota_module_name module_names[] = INIT_QUOTA_MODULE_NAMES; /* SLAB cache for dquot structures */ -static kmem_cache_t *dquot_cachep; +static struct kmem_cache *dquot_cachep; int register_quota_format(struct quota_format_type *fmt) { diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index a2c6ccbce30..306f8fbd1a0 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -546,7 +546,7 @@ inode_info_init_once(void *vptr, struct kmem_cache *cachep, unsigned long flags) } static struct ecryptfs_cache_info { - kmem_cache_t **cache; + struct kmem_cache **cache; const char *name; size_t size; void (*ctor)(void*, struct kmem_cache *, unsigned long); diff --git a/fs/efs/super.c b/fs/efs/super.c index 69b15a996cf..dfebf21289f 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -52,7 +52,7 @@ static struct pt_types sgi_pt_types[] = { }; -static kmem_cache_t * efs_inode_cachep; +static struct kmem_cache * efs_inode_cachep; static struct inode *efs_alloc_inode(struct super_block *sb) { @@ -68,7 +68,7 @@ static void efs_destroy_inode(struct inode *inode) kmem_cache_free(efs_inode_cachep, INODE_INFO(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct efs_inode_info *ei = (struct efs_inode_info *) foo; diff --git a/fs/eventpoll.c b/fs/eventpoll.c index f5c88435c6b..88a6f8d0b88 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -283,10 +283,10 @@ static struct mutex epmutex; static struct poll_safewake psw; /* Slab cache used to allocate "struct epitem" */ -static kmem_cache_t *epi_cache __read_mostly; +static struct kmem_cache *epi_cache __read_mostly; /* Slab cache used to allocate "struct eppoll_entry" */ -static kmem_cache_t *pwq_cache __read_mostly; +static struct kmem_cache *pwq_cache __read_mostly; /* Virtual fs used to allocate inodes for eventpoll files */ static struct vfsmount *eventpoll_mnt __read_mostly; diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 85c237e7385..3aafb1dd917 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -135,7 +135,7 @@ static void ext2_put_super (struct super_block * sb) return; } -static kmem_cache_t * ext2_inode_cachep; +static struct kmem_cache * ext2_inode_cachep; static struct inode *ext2_alloc_inode(struct super_block *sb) { @@ -156,7 +156,7 @@ static void ext2_destroy_inode(struct inode *inode) kmem_cache_free(ext2_inode_cachep, EXT2_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct ext2_inode_info *ei = (struct ext2_inode_info *) foo; diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 0cf633f0cfa..9856565d4dd 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -436,7 +436,7 @@ static void ext3_put_super (struct super_block * sb) return; } -static kmem_cache_t *ext3_inode_cachep; +static struct kmem_cache *ext3_inode_cachep; /* * Called inside transaction, so use GFP_NOFS @@ -462,7 +462,7 @@ static void ext3_destroy_inode(struct inode *inode) kmem_cache_free(ext3_inode_cachep, EXT3_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct ext3_inode_info *ei = (struct ext3_inode_info *) foo; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index c730cbc8403..f2e8c4aa0fd 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -486,7 +486,7 @@ static void ext4_put_super (struct super_block * sb) return; } -static kmem_cache_t *ext4_inode_cachep; +static struct kmem_cache *ext4_inode_cachep; /* * Called inside transaction, so use GFP_NOFS @@ -513,7 +513,7 @@ static void ext4_destroy_inode(struct inode *inode) kmem_cache_free(ext4_inode_cachep, EXT4_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct ext4_inode_info *ei = (struct ext4_inode_info *) foo; diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 8c272278455..05c2941c74f 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -34,9 +34,9 @@ static inline int fat_max_cache(struct inode *inode) return FAT_MAX_CACHE; } -static kmem_cache_t *fat_cache_cachep; +static struct kmem_cache *fat_cache_cachep; -static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct fat_cache *cache = (struct fat_cache *)foo; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index b58fd0c9f3c..a9e4688582a 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -477,7 +477,7 @@ static void fat_put_super(struct super_block *sb) kfree(sbi); } -static kmem_cache_t *fat_inode_cachep; +static struct kmem_cache *fat_inode_cachep; static struct inode *fat_alloc_inode(struct super_block *sb) { @@ -493,7 +493,7 @@ static void fat_destroy_inode(struct inode *inode) kmem_cache_free(fat_inode_cachep, MSDOS_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct msdos_inode_info *ei = (struct msdos_inode_info *)foo; diff --git a/fs/fcntl.c b/fs/fcntl.c index c03dc9cb21c..4740d35e52c 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -553,7 +553,7 @@ int send_sigurg(struct fown_struct *fown) } static DEFINE_RWLOCK(fasync_lock); -static kmem_cache_t *fasync_cache __read_mostly; +static struct kmem_cache *fasync_cache __read_mostly; /* * fasync_helper() is used by some character device drivers (mainly mice) diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index d2dd0d70007..0b7ae897cb7 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -46,7 +46,7 @@ extern const struct address_space_operations vxfs_immed_aops; extern struct inode_operations vxfs_immed_symlink_iops; -kmem_cache_t *vxfs_inode_cachep; +struct kmem_cache *vxfs_inode_cachep; #ifdef DIAGNOSTIC diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 8c15139f275..357764d85ff 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -19,7 +19,7 @@ MODULE_ALIAS_MISCDEV(FUSE_MINOR); -static kmem_cache_t *fuse_req_cachep; +static struct kmem_cache *fuse_req_cachep; static struct fuse_conn *fuse_get_conn(struct file *file) { diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index e039e2047cc..2bdc652b8b4 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -22,7 +22,7 @@ MODULE_AUTHOR("Miklos Szeredi "); MODULE_DESCRIPTION("Filesystem in Userspace"); MODULE_LICENSE("GPL"); -static kmem_cache_t *fuse_inode_cachep; +static struct kmem_cache *fuse_inode_cachep; struct list_head fuse_conn_list; DEFINE_MUTEX(fuse_mutex); @@ -601,7 +601,7 @@ static struct file_system_type fuse_fs_type = { static decl_subsys(fuse, NULL, NULL); static decl_subsys(connections, NULL, NULL); -static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep, +static void fuse_inode_init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct inode * inode = foo; diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 9889c1eacec..7c1a9e22a52 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c @@ -25,7 +25,7 @@ #include "util.h" #include "glock.h" -static void gfs2_init_inode_once(void *foo, kmem_cache_t *cachep, unsigned long flags) +static void gfs2_init_inode_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct gfs2_inode *ip = foo; if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == @@ -37,7 +37,7 @@ static void gfs2_init_inode_once(void *foo, kmem_cache_t *cachep, unsigned long } } -static void gfs2_init_glock_once(void *foo, kmem_cache_t *cachep, unsigned long flags) +static void gfs2_init_glock_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct gfs2_glock *gl = foo; if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index 196c604faad..e5707a9f78c 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c @@ -23,9 +23,9 @@ #include "lm.h" #include "util.h" -kmem_cache_t *gfs2_glock_cachep __read_mostly; -kmem_cache_t *gfs2_inode_cachep __read_mostly; -kmem_cache_t *gfs2_bufdata_cachep __read_mostly; +struct kmem_cache *gfs2_glock_cachep __read_mostly; +struct kmem_cache *gfs2_inode_cachep __read_mostly; +struct kmem_cache *gfs2_bufdata_cachep __read_mostly; void gfs2_assert_i(struct gfs2_sbd *sdp) { diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h index 76a50899fe9..7984dcf89ad 100644 --- a/fs/gfs2/util.h +++ b/fs/gfs2/util.h @@ -146,9 +146,9 @@ int gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh, gfs2_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__); -extern kmem_cache_t *gfs2_glock_cachep; -extern kmem_cache_t *gfs2_inode_cachep; -extern kmem_cache_t *gfs2_bufdata_cachep; +extern struct kmem_cache *gfs2_glock_cachep; +extern struct kmem_cache *gfs2_inode_cachep; +extern struct kmem_cache *gfs2_bufdata_cachep; static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt, unsigned int *p) diff --git a/fs/hfs/super.c b/fs/hfs/super.c index ffc6409132c..a3698796600 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -24,7 +24,7 @@ #include "hfs_fs.h" #include "btree.h" -static kmem_cache_t *hfs_inode_cachep; +static struct kmem_cache *hfs_inode_cachep; MODULE_LICENSE("GPL"); @@ -430,7 +430,7 @@ static struct file_system_type hfs_fs_type = { .fs_flags = FS_REQUIRES_DEV, }; -static void hfs_init_once(void *p, kmem_cache_t *cachep, unsigned long flags) +static void hfs_init_once(void *p, struct kmem_cache *cachep, unsigned long flags) { struct hfs_inode_info *i = p; diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 4a0c70c76c8..0f513c6bf84 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -434,7 +434,7 @@ MODULE_AUTHOR("Brad Boyer"); MODULE_DESCRIPTION("Extended Macintosh Filesystem"); MODULE_LICENSE("GPL"); -static kmem_cache_t *hfsplus_inode_cachep; +static struct kmem_cache *hfsplus_inode_cachep; static struct inode *hfsplus_alloc_inode(struct super_block *sb) { @@ -467,7 +467,7 @@ static struct file_system_type hfsplus_fs_type = { .fs_flags = FS_REQUIRES_DEV, }; -static void hfsplus_init_once(void *p, kmem_cache_t *cachep, unsigned long flags) +static void hfsplus_init_once(void *p, struct kmem_cache *cachep, unsigned long flags) { struct hfsplus_inode_info *i = p; diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 46ceadd6f16..34d68e21171 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -160,7 +160,7 @@ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf) return 0; } -static kmem_cache_t * hpfs_inode_cachep; +static struct kmem_cache * hpfs_inode_cachep; static struct inode *hpfs_alloc_inode(struct super_block *sb) { @@ -177,7 +177,7 @@ static void hpfs_destroy_inode(struct inode *inode) kmem_cache_free(hpfs_inode_cachep, hpfs_i(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo; diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 36e52173a54..0706f5aac6a 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -513,7 +513,7 @@ static void hugetlbfs_inc_free_inodes(struct hugetlbfs_sb_info *sbinfo) } -static kmem_cache_t *hugetlbfs_inode_cachep; +static struct kmem_cache *hugetlbfs_inode_cachep; static struct inode *hugetlbfs_alloc_inode(struct super_block *sb) { @@ -545,7 +545,7 @@ static const struct address_space_operations hugetlbfs_aops = { }; -static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo; diff --git a/fs/inode.c b/fs/inode.c index dd15984d51a..699aa4f7aa7 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -97,7 +97,7 @@ static DEFINE_MUTEX(iprune_mutex); */ struct inodes_stat_t inodes_stat; -static kmem_cache_t * inode_cachep __read_mostly; +static struct kmem_cache * inode_cachep __read_mostly; static struct inode *alloc_inode(struct super_block *sb) { @@ -209,7 +209,7 @@ void inode_init_once(struct inode *inode) EXPORT_SYMBOL(inode_init_once); -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct inode * inode = (struct inode *) foo; diff --git a/fs/inotify_user.c b/fs/inotify_user.c index 017cb0f134d..e1956e6f116 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c @@ -34,8 +34,8 @@ #include -static kmem_cache_t *watch_cachep __read_mostly; -static kmem_cache_t *event_cachep __read_mostly; +static struct kmem_cache *watch_cachep __read_mostly; +static struct kmem_cache *event_cachep __read_mostly; static struct vfsmount *inotify_mnt __read_mostly; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 4b6381cd2cf..ea55b6c469e 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -57,7 +57,7 @@ static void isofs_put_super(struct super_block *sb) static void isofs_read_inode(struct inode *); static int isofs_statfs (struct dentry *, struct kstatfs *); -static kmem_cache_t *isofs_inode_cachep; +static struct kmem_cache *isofs_inode_cachep; static struct inode *isofs_alloc_inode(struct super_block *sb) { @@ -73,7 +73,7 @@ static void isofs_destroy_inode(struct inode *inode) kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode)); } -static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags) { struct iso_inode_info *ei = foo; diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index b85c686b60d..a8774bed20b 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -1630,7 +1630,7 @@ void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry) #define JBD_MAX_SLABS 5 #define JBD_SLAB_INDEX(size) (size >> 11) -static kmem_cache_t *jbd_slab[JBD_MAX_SLABS]; +static struct kmem_cache *jbd_slab[JBD_MAX_SLABS]; static const char *jbd_slab_names[JBD_MAX_SLABS] = { "jbd_1k", "jbd_2k", "jbd_4k", NULL, "jbd_8k" }; @@ -1693,7 +1693,7 @@ void jbd_slab_free(void *ptr, size_t size) /* * Journal_head storage management */ -static kmem_cache_t *journal_head_cache; +static struct kmem_cache *journal_head_cache; #ifdef CONFIG_JBD_DEBUG static atomic_t nr_journal_heads = ATOMIC_INIT(0); #endif @@ -1996,7 +1996,7 @@ static void __exit remove_jbd_proc_entry(void) #endif -kmem_cache_t *jbd_handle_cache; +struct kmem_cache *jbd_handle_cache; static int __init journal_init_handle_cache(void) { diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c index c532429d8d9..d204ab394f3 100644 --- a/fs/jbd/revoke.c +++ b/fs/jbd/revoke.c @@ -70,8 +70,8 @@ #include #endif -static kmem_cache_t *revoke_record_cache; -static kmem_cache_t *revoke_table_cache; +static struct kmem_cache *revoke_record_cache; +static struct kmem_cache *revoke_table_cache; /* Each revoke record represents one single revoked block. During journal replay, this involves recording the transaction ID of the diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index c60f378b0f7..50356019ae3 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1641,7 +1641,7 @@ void * __jbd2_kmalloc (const char *where, size_t size, gfp_t flags, int retry) #define JBD_MAX_SLABS 5 #define JBD_SLAB_INDEX(size) (size >> 11) -static kmem_cache_t *jbd_slab[JBD_MAX_SLABS]; +static struct kmem_cache *jbd_slab[JBD_MAX_SLABS]; static const char *jbd_slab_names[JBD_MAX_SLABS] = { "jbd2_1k", "jbd2_2k", "jbd2_4k", NULL, "jbd2_8k" }; @@ -1704,7 +1704,7 @@ void jbd2_slab_free(void *ptr, size_t size) /* * Journal_head storage management */ -static kmem_cache_t *jbd2_journal_head_cache; +static struct kmem_cache *jbd2_journal_head_cache; #ifdef CONFIG_JBD_DEBUG static atomic_t nr_journal_heads = ATOMIC_INIT(0); #endif @@ -2007,7 +2007,7 @@ static void __exit jbd2_remove_jbd_proc_entry(void) #endif -kmem_cache_t *jbd2_handle_cache; +struct kmem_cache *jbd2_handle_cache; static int __init journal_init_handle_cache(void) { diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index 380d19917f3..f506646ad0f 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c @@ -70,8 +70,8 @@ #include #endif -static kmem_cache_t *jbd2_revoke_record_cache; -static kmem_cache_t *jbd2_revoke_table_cache; +static struct kmem_cache *jbd2_revoke_record_cache; +static struct kmem_cache *jbd2_revoke_table_cache; /* Each revoke record represents one single revoked block. During journal replay, this involves recording the transaction ID of the diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 3f7899ea4cb..9f15bce9202 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -61,8 +61,8 @@ static const struct file_operations jffs_dir_operations; static struct inode_operations jffs_dir_inode_operations; static const struct address_space_operations jffs_address_operations; -kmem_cache_t *node_cache = NULL; -kmem_cache_t *fm_cache = NULL; +struct kmem_cache *node_cache = NULL; +struct kmem_cache *fm_cache = NULL; /* Called by the VFS at mount time to initialize the whole file system. */ static int jffs_fill_super(struct super_block *sb, void *data, int silent) diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c index 29b68d939bd..077258b2103 100644 --- a/fs/jffs/jffs_fm.c +++ b/fs/jffs/jffs_fm.c @@ -29,8 +29,8 @@ static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset); static struct jffs_fm *jffs_alloc_fm(void); static void jffs_free_fm(struct jffs_fm *n); -extern kmem_cache_t *fm_cache; -extern kmem_cache_t *node_cache; +extern struct kmem_cache *fm_cache; +extern struct kmem_cache *node_cache; #if CONFIG_JFFS_FS_VERBOSE > 0 void diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index 33f29100501..83f9881ec4c 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -19,16 +19,16 @@ /* These are initialised to NULL in the kernel startup code. If you're porting to other operating systems, beware */ -static kmem_cache_t *full_dnode_slab; -static kmem_cache_t *raw_dirent_slab; -static kmem_cache_t *raw_inode_slab; -static kmem_cache_t *tmp_dnode_info_slab; -static kmem_cache_t *raw_node_ref_slab; -static kmem_cache_t *node_frag_slab; -static kmem_cache_t *inode_cache_slab; +static struct kmem_cache *full_dnode_slab; +static struct kmem_cache *raw_dirent_slab; +static struct kmem_cache *raw_inode_slab; +static struct kmem_cache *tmp_dnode_info_slab; +static struct kmem_cache *raw_node_ref_slab; +static struct kmem_cache *node_frag_slab; +static struct kmem_cache *inode_cache_slab; #ifdef CONFIG_JFFS2_FS_XATTR -static kmem_cache_t *xattr_datum_cache; -static kmem_cache_t *xattr_ref_cache; +static struct kmem_cache *xattr_datum_cache; +static struct kmem_cache *xattr_ref_cache; #endif int __init jffs2_create_slab_caches(void) diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 77be534ce42..7deb7825402 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -28,7 +28,7 @@ static void jffs2_put_super(struct super_block *); -static kmem_cache_t *jffs2_inode_cachep; +static struct kmem_cache *jffs2_inode_cachep; static struct inode *jffs2_alloc_inode(struct super_block *sb) { @@ -44,7 +44,7 @@ static void jffs2_destroy_inode(struct inode *inode) kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode)); } -static void jffs2_i_init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void jffs2_i_init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo; diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 0cccd1c39d7..b1a1c729601 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -74,7 +74,7 @@ static inline void lock_metapage(struct metapage *mp) } #define METAPOOL_MIN_PAGES 32 -static kmem_cache_t *metapage_cache; +static struct kmem_cache *metapage_cache; static mempool_t *metapage_mempool; #define MPS_PER_PAGE (PAGE_CACHE_SIZE >> L2PSIZE) @@ -180,7 +180,7 @@ static inline void remove_metapage(struct page *page, struct metapage *mp) #endif -static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct metapage *mp = (struct metapage *)foo; diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 9c1c6e0e633..ca3e1912853 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -44,7 +44,7 @@ MODULE_DESCRIPTION("The Journaled Filesystem (JFS)"); MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM"); MODULE_LICENSE("GPL"); -static kmem_cache_t * jfs_inode_cachep; +static struct kmem_cache * jfs_inode_cachep; static struct super_operations jfs_super_operations; static struct export_operations jfs_export_operations; @@ -748,7 +748,7 @@ static struct file_system_type jfs_fs_type = { .fs_flags = FS_REQUIRES_DEV, }; -static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags) { struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo; diff --git a/fs/locks.c b/fs/locks.c index a7b97d50c1e..1cb0c57fedb 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -142,7 +142,7 @@ int lease_break_time = 45; static LIST_HEAD(file_lock_list); static LIST_HEAD(blocked_list); -static kmem_cache_t *filelock_cache __read_mostly; +static struct kmem_cache *filelock_cache __read_mostly; /* Allocate an empty lock structure. */ static struct file_lock *locks_alloc_lock(void) @@ -199,7 +199,7 @@ EXPORT_SYMBOL(locks_init_lock); * Initialises the fields of the file lock which are invariant for * free file_locks. */ -static void init_once(void *foo, kmem_cache_t *cache, unsigned long flags) +static void init_once(void *foo, struct kmem_cache *cache, unsigned long flags) { struct file_lock *lock = (struct file_lock *) foo; diff --git a/fs/mbcache.c b/fs/mbcache.c index 0ff71256e65..deeb9dc062d 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -85,7 +85,7 @@ struct mb_cache { #ifndef MB_CACHE_INDEXES_COUNT int c_indexes_count; #endif - kmem_cache_t *c_entry_cache; + struct kmem_cache *c_entry_cache; struct list_head *c_block_hash; struct list_head *c_indexes_hash[0]; }; diff --git a/fs/minix/inode.c b/fs/minix/inode.c index ce532c2deda..629e09b38c5 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -51,7 +51,7 @@ static void minix_put_super(struct super_block *sb) return; } -static kmem_cache_t * minix_inode_cachep; +static struct kmem_cache * minix_inode_cachep; static struct inode *minix_alloc_inode(struct super_block *sb) { @@ -67,7 +67,7 @@ static void minix_destroy_inode(struct inode *inode) kmem_cache_free(minix_inode_cachep, minix_i(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct minix_inode_info *ei = (struct minix_inode_info *) foo; diff --git a/fs/namespace.c b/fs/namespace.c index 55442a6cf22..b00ac84ebbd 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -36,7 +36,7 @@ static int event; static struct list_head *mount_hashtable __read_mostly; static int hash_mask __read_mostly, hash_bits __read_mostly; -static kmem_cache_t *mnt_cache __read_mostly; +static struct kmem_cache *mnt_cache __read_mostly; static struct rw_semaphore namespace_sem; /* /sys/fs */ diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index ed84d899220..fae53243bb9 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -40,7 +40,7 @@ static void ncp_delete_inode(struct inode *); static void ncp_put_super(struct super_block *); static int ncp_statfs(struct dentry *, struct kstatfs *); -static kmem_cache_t * ncp_inode_cachep; +static struct kmem_cache * ncp_inode_cachep; static struct inode *ncp_alloc_inode(struct super_block *sb) { @@ -56,7 +56,7 @@ static void ncp_destroy_inode(struct inode *inode) kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 769fd0a0c77..2f488e1d9b6 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -58,7 +58,7 @@ #define NFSDBG_FACILITY NFSDBG_VFS -static kmem_cache_t *nfs_direct_cachep; +static struct kmem_cache *nfs_direct_cachep; /* * This represents a set of asynchronous requests that we're waiting on diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6b53aae4ed2..15afa460e62 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -55,7 +55,7 @@ static int nfs_update_inode(struct inode *, struct nfs_fattr *); static void nfs_zap_acl_cache(struct inode *); -static kmem_cache_t * nfs_inode_cachep; +static struct kmem_cache * nfs_inode_cachep; static inline unsigned long nfs_fattr_to_ino_t(struct nfs_fattr *fattr) @@ -1111,7 +1111,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi) #endif } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct nfs_inode *nfsi = (struct nfs_inode *) foo; diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index a1561a820ab..3fbfc2f0330 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -20,7 +20,7 @@ #define NFS_PARANOIA 1 -static kmem_cache_t *nfs_page_cachep; +static struct kmem_cache *nfs_page_cachep; static inline struct nfs_page * nfs_page_alloc(void) diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 56f66f0ccb6..244a8c45b68 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -38,7 +38,7 @@ static int nfs_pagein_one(struct list_head *, struct inode *); static const struct rpc_call_ops nfs_read_partial_ops; static const struct rpc_call_ops nfs_read_full_ops; -static kmem_cache_t *nfs_rdata_cachep; +static struct kmem_cache *nfs_rdata_cachep; static mempool_t *nfs_rdata_mempool; #define MIN_POOL_READ (32) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f7dd0d00595..41b07288f99 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -85,7 +85,7 @@ static const struct rpc_call_ops nfs_write_partial_ops; static const struct rpc_call_ops nfs_write_full_ops; static const struct rpc_call_ops nfs_commit_ops; -static kmem_cache_t *nfs_wdata_cachep; +static struct kmem_cache *nfs_wdata_cachep; static mempool_t *nfs_wdata_mempool; static mempool_t *nfs_commit_mempool; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index e431e93ab50..640c92b2a9f 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -84,10 +84,10 @@ static void nfs4_set_recdir(char *recdir); */ static DEFINE_MUTEX(client_mutex); -static kmem_cache_t *stateowner_slab = NULL; -static kmem_cache_t *file_slab = NULL; -static kmem_cache_t *stateid_slab = NULL; -static kmem_cache_t *deleg_slab = NULL; +static struct kmem_cache *stateowner_slab = NULL; +static struct kmem_cache *file_slab = NULL; +static struct kmem_cache *stateid_slab = NULL; +static struct kmem_cache *deleg_slab = NULL; void nfs4_lock_state(void) @@ -1003,7 +1003,7 @@ alloc_init_file(struct inode *ino) } static void -nfsd4_free_slab(kmem_cache_t **slab) +nfsd4_free_slab(struct kmem_cache **slab) { if (*slab == NULL) return; diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 01f91501f70..941acf14e61 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c @@ -66,7 +66,7 @@ static struct file_operations dlmfs_file_operations; static struct inode_operations dlmfs_dir_inode_operations; static struct inode_operations dlmfs_root_inode_operations; static struct inode_operations dlmfs_file_inode_operations; -static kmem_cache_t *dlmfs_inode_cache; +static struct kmem_cache *dlmfs_inode_cache; struct workqueue_struct *user_dlm_worker; @@ -257,7 +257,7 @@ static ssize_t dlmfs_file_write(struct file *filp, } static void dlmfs_init_once(void *foo, - kmem_cache_t *cachep, + struct kmem_cache *cachep, unsigned long flags) { struct dlmfs_inode_private *ip = diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index f784177b624..856012b4fa4 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -221,7 +221,7 @@ EXPORT_SYMBOL_GPL(dlm_dump_all_mles); #endif /* 0 */ -static kmem_cache_t *dlm_mle_cache = NULL; +static struct kmem_cache *dlm_mle_cache = NULL; static void dlm_mle_release(struct kref *kref); diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index fcd4475d1f8..80ac69f11d9 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -61,7 +61,7 @@ struct ocfs2_em_insert_context { struct ocfs2_extent_map_entry *right_ent; }; -static kmem_cache_t *ocfs2_em_ent_cachep = NULL; +static struct kmem_cache *ocfs2_em_ent_cachep = NULL; static struct ocfs2_extent_map_entry * diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 46a378fbc40..1a7dd2945b3 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h @@ -106,7 +106,7 @@ static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode) #define INODE_JOURNAL(i) (OCFS2_I(i)->ip_flags & OCFS2_INODE_JOURNAL) #define SET_INODE_JOURNAL(i) (OCFS2_I(i)->ip_flags |= OCFS2_INODE_JOURNAL) -extern kmem_cache_t *ocfs2_inode_cache; +extern struct kmem_cache *ocfs2_inode_cache; extern const struct address_space_operations ocfs2_aops; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 7574d26ee0f..0524f8a04ad 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -68,7 +68,7 @@ #include "buffer_head_io.h" -static kmem_cache_t *ocfs2_inode_cachep = NULL; +static struct kmem_cache *ocfs2_inode_cachep = NULL; /* OCFS2 needs to schedule several differnt types of work which * require cluster locking, disk I/O, recovery waits, etc. Since these @@ -914,7 +914,7 @@ bail: } static void ocfs2_inode_init_once(void *data, - kmem_cache_t *cachep, + struct kmem_cache *cachep, unsigned long flags) { struct ocfs2_inode_info *oi = data; diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c index 9707ed7a320..39814b900fc 100644 --- a/fs/ocfs2/uptodate.c +++ b/fs/ocfs2/uptodate.c @@ -69,7 +69,7 @@ struct ocfs2_meta_cache_item { sector_t c_block; }; -static kmem_cache_t *ocfs2_uptodate_cachep = NULL; +static struct kmem_cache *ocfs2_uptodate_cachep = NULL; void ocfs2_metadata_cache_init(struct inode *inode) { diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 911d1bcfc56..26f44e0074e 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -330,7 +330,7 @@ out: return 0; } -static kmem_cache_t *op_inode_cachep; +static struct kmem_cache *op_inode_cachep; static struct inode *openprom_alloc_inode(struct super_block *sb) { @@ -415,7 +415,7 @@ static struct file_system_type openprom_fs_type = { .kill_sb = kill_anon_super, }; -static void op_inode_init_once(void *data, kmem_cache_t * cachep, unsigned long flags) +static void op_inode_init_once(void *data, struct kmem_cache * cachep, unsigned long flags) { struct op_inode_info *oi = (struct op_inode_info *) data; diff --git a/fs/proc/inode.c b/fs/proc/inode.c index b24cdb2f17c..e26945ba685 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -81,7 +81,7 @@ static void proc_read_inode(struct inode * inode) inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; } -static kmem_cache_t * proc_inode_cachep; +static struct kmem_cache * proc_inode_cachep; static struct inode *proc_alloc_inode(struct super_block *sb) { @@ -105,7 +105,7 @@ static void proc_destroy_inode(struct inode *inode) kmem_cache_free(proc_inode_cachep, PROC_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct proc_inode *ei = (struct proc_inode *) foo; diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 5b943eb11d7..c047dc654d5 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -515,7 +515,7 @@ static void qnx4_read_inode(struct inode *inode) brelse(bh); } -static kmem_cache_t *qnx4_inode_cachep; +static struct kmem_cache *qnx4_inode_cachep; static struct inode *qnx4_alloc_inode(struct super_block *sb) { @@ -531,7 +531,7 @@ static void qnx4_destroy_inode(struct inode *inode) kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode)); } -static void init_once(void *foo, kmem_cache_t * cachep, +static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags) { struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo; diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 32332516d65..745bc714ba9 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -490,7 +490,7 @@ static void reiserfs_put_super(struct super_block *s) return; } -static kmem_cache_t *reiserfs_inode_cachep; +static struct kmem_cache *reiserfs_inode_cachep; static struct inode *reiserfs_alloc_inode(struct super_block *sb) { @@ -507,7 +507,7 @@ static void reiserfs_destroy_inode(struct inode *inode) kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode)); } -static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags) { struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo; diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index d1b455f9b66..c5af088d4a4 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -550,7 +550,7 @@ romfs_read_inode(struct inode *i) } } -static kmem_cache_t * romfs_inode_cachep; +static struct kmem_cache * romfs_inode_cachep; static struct inode *romfs_alloc_inode(struct super_block *sb) { @@ -566,7 +566,7 @@ static void romfs_destroy_inode(struct inode *inode) kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct romfs_inode_info *ei = (struct romfs_inode_info *) foo; diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 22161710348..4af4cd729a5 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -50,7 +50,7 @@ static void smb_put_super(struct super_block *); static int smb_statfs(struct dentry *, struct kstatfs *); static int smb_show_options(struct seq_file *, struct vfsmount *); -static kmem_cache_t *smb_inode_cachep; +static struct kmem_cache *smb_inode_cachep; static struct inode *smb_alloc_inode(struct super_block *sb) { @@ -66,7 +66,7 @@ static void smb_destroy_inode(struct inode *inode) kmem_cache_free(smb_inode_cachep, SMB_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct smb_inode_info *ei = (struct smb_inode_info *) foo; unsigned long flagmask = SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR; diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c index 3eb1402191b..a4bcae8a9af 100644 --- a/fs/smbfs/request.c +++ b/fs/smbfs/request.c @@ -25,7 +25,7 @@ #define ROUND_UP(x) (((x)+3) & ~3) /* cache for request structures */ -static kmem_cache_t *req_cachep; +static struct kmem_cache *req_cachep; static int smb_request_send_req(struct smb_request *req); diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 20551a1b8a5..e503f858fba 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -16,7 +16,7 @@ struct vfsmount *sysfs_mount; struct super_block * sysfs_sb = NULL; -kmem_cache_t *sysfs_dir_cachep; +struct kmem_cache *sysfs_dir_cachep; static struct super_operations sysfs_ops = { .statfs = simple_statfs, diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 6f3d6bd5288..bd7cec295da 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -1,6 +1,6 @@ extern struct vfsmount * sysfs_mount; -extern kmem_cache_t *sysfs_dir_cachep; +extern struct kmem_cache *sysfs_dir_cachep; extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index a6ca12b747c..ead9864567e 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -301,7 +301,7 @@ static void sysv_delete_inode(struct inode *inode) unlock_kernel(); } -static kmem_cache_t *sysv_inode_cachep; +static struct kmem_cache *sysv_inode_cachep; static struct inode *sysv_alloc_inode(struct super_block *sb) { @@ -318,7 +318,7 @@ static void sysv_destroy_inode(struct inode *inode) kmem_cache_free(sysv_inode_cachep, SYSV_I(inode)); } -static void init_once(void *p, kmem_cache_t *cachep, unsigned long flags) +static void init_once(void *p, struct kmem_cache *cachep, unsigned long flags) { struct sysv_inode_info *si = (struct sysv_inode_info *)p; diff --git a/fs/udf/super.c b/fs/udf/super.c index e50f24221de..397f54aaf66 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -107,7 +107,7 @@ static struct file_system_type udf_fstype = { .fs_flags = FS_REQUIRES_DEV, }; -static kmem_cache_t * udf_inode_cachep; +static struct kmem_cache * udf_inode_cachep; static struct inode *udf_alloc_inode(struct super_block *sb) { @@ -130,7 +130,7 @@ static void udf_destroy_inode(struct inode *inode) kmem_cache_free(udf_inode_cachep, UDF_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct udf_inode_info *ei = (struct udf_inode_info *) foo; diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 85a88c0c5e6..0b18d2cc2ef 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1204,7 +1204,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf) return 0; } -static kmem_cache_t * ufs_inode_cachep; +static struct kmem_cache * ufs_inode_cachep; static struct inode *ufs_alloc_inode(struct super_block *sb) { @@ -1221,7 +1221,7 @@ static void ufs_destroy_inode(struct inode *inode) kmem_cache_free(ufs_inode_cachep, UFS_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct ufs_inode_info *ei = (struct ufs_inode_info *) foo; diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 47faf27913a..7f1e92930b6 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -64,7 +64,7 @@ /* Host-dependent types and defines */ #define ACPI_MACHINE_WIDTH BITS_PER_LONG -#define acpi_cache_t kmem_cache_t +#define acpi_cache_t struct kmem_cache #define acpi_spinlock spinlock_t * #define ACPI_EXPORT_SYMBOL(symbol) EXPORT_SYMBOL(symbol); #define strtoul simple_strtoul diff --git a/include/asm-arm26/pgalloc.h b/include/asm-arm26/pgalloc.h index 6437167b1ff..7725af3ddb4 100644 --- a/include/asm-arm26/pgalloc.h +++ b/include/asm-arm26/pgalloc.h @@ -15,7 +15,7 @@ #include #include -extern kmem_cache_t *pte_cache; +extern struct kmem_cache *pte_cache; static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr){ return kmem_cache_alloc(pte_cache, GFP_KERNEL); diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 7d398f493dd..bfee7ddfff5 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -34,14 +34,14 @@ struct vm_area_struct; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) extern unsigned long empty_zero_page[1024]; extern pgd_t swapper_pg_dir[1024]; -extern kmem_cache_t *pgd_cache; -extern kmem_cache_t *pmd_cache; +extern struct kmem_cache *pgd_cache; +extern struct kmem_cache *pmd_cache; extern spinlock_t pgd_lock; extern struct page *pgd_list; -void pmd_ctor(void *, kmem_cache_t *, unsigned long); -void pgd_ctor(void *, kmem_cache_t *, unsigned long); -void pgd_dtor(void *, kmem_cache_t *, unsigned long); +void pmd_ctor(void *, struct kmem_cache *, unsigned long); +void pgd_ctor(void *, struct kmem_cache *, unsigned long); +void pgd_dtor(void *, struct kmem_cache *, unsigned long); void pgtable_cache_init(void); void paging_init(void); diff --git a/include/asm-powerpc/pgalloc.h b/include/asm-powerpc/pgalloc.h index ae63db7b3e7..b0830db68f8 100644 --- a/include/asm-powerpc/pgalloc.h +++ b/include/asm-powerpc/pgalloc.h @@ -11,7 +11,7 @@ #include #include -extern kmem_cache_t *pgtable_cache[]; +extern struct kmem_cache *pgtable_cache[]; #ifdef CONFIG_PPC_64K_PAGES #define PTE_CACHE_NUM 0 diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h index 010f9cd0a67..5891ff7ba76 100644 --- a/include/asm-sparc64/pgalloc.h +++ b/include/asm-sparc64/pgalloc.h @@ -13,7 +13,7 @@ #include /* Page table allocation/freeing. */ -extern kmem_cache_t *pgtable_cache; +extern struct kmem_cache *pgtable_cache; static inline pgd_t *pgd_alloc(struct mm_struct *mm) { diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h index 561e2a77805..55d1ca5e60f 100644 --- a/include/linux/delayacct.h +++ b/include/linux/delayacct.h @@ -30,7 +30,7 @@ #ifdef CONFIG_TASK_DELAY_ACCT extern int delayacct_on; /* Delay accounting turned on/off */ -extern kmem_cache_t *delayacct_cache; +extern struct kmem_cache *delayacct_cache; extern void delayacct_init(void); extern void __delayacct_tsk_init(struct task_struct *); extern void __delayacct_tsk_exit(struct task_struct *); diff --git a/include/linux/i2o.h b/include/linux/i2o.h index 1fb02e17f6f..2514f4e286b 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -490,7 +490,7 @@ struct i2o_dma { */ struct i2o_pool { char *name; - kmem_cache_t *slab; + struct kmem_cache *slab; mempool_t *mempool; }; diff --git a/include/linux/jbd.h b/include/linux/jbd.h index fe89444b1c6..dacd566c9f6 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -949,7 +949,7 @@ void journal_put_journal_head(struct journal_head *jh); /* * handle management */ -extern kmem_cache_t *jbd_handle_cache; +extern struct kmem_cache *jbd_handle_cache; static inline handle_t *jbd_alloc_handle(gfp_t gfp_flags) { diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index ddb12879578..98a0ae52660 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -958,7 +958,7 @@ void jbd2_journal_put_journal_head(struct journal_head *jh); /* * handle management */ -extern kmem_cache_t *jbd2_handle_cache; +extern struct kmem_cache *jbd2_handle_cache; static inline handle_t *jbd_alloc_handle(gfp_t gfp_flags) { diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index f13299a1559..03636d7918f 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -235,7 +235,7 @@ struct raid5_private_data { */ int active_name; char cache_name[2][20]; - kmem_cache_t *slab_cache; /* for allocating stripes */ + struct kmem_cache *slab_cache; /* for allocating stripes */ int seq_flush, seq_write; int quiesce; diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 61c2ab634b0..36f850373d2 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -30,7 +30,7 @@ struct anon_vma { #ifdef CONFIG_MMU -extern kmem_cache_t *anon_vma_cachep; +extern struct kmem_cache *anon_vma_cachep; static inline struct anon_vma *anon_vma_alloc(void) { diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 1d649f3eb00..4ff3940210d 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -345,7 +345,7 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size, return __alloc_skb(size, priority, 1, -1); } -extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, +extern struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp, unsigned int size, gfp_t priority); extern void kfree_skbmem(struct sk_buff *skb); diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h index f81a5af8a4f..ce8a912e542 100644 --- a/include/linux/taskstats_kern.h +++ b/include/linux/taskstats_kern.h @@ -12,7 +12,7 @@ #include #ifdef CONFIG_TASKSTATS -extern kmem_cache_t *taskstats_cache; +extern struct kmem_cache *taskstats_cache; extern struct mutex taskstats_exit_mutex; static inline void taskstats_exit_free(struct taskstats *tidstats) diff --git a/include/net/dst.h b/include/net/dst.h index e156e38e4ac..62b7e7598e9 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -98,7 +98,7 @@ struct dst_ops int entry_size; atomic_t entries; - kmem_cache_t *kmem_cachep; + struct kmem_cache *kmem_cachep; }; #ifdef __KERNEL__ diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index a9eb2eaf094..34cc76e3ddb 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -125,7 +125,7 @@ struct inet_hashinfo { rwlock_t lhash_lock ____cacheline_aligned; atomic_t lhash_users; wait_queue_head_t lhash_wait; - kmem_cache_t *bind_bucket_cachep; + struct kmem_cache *bind_bucket_cachep; }; static inline struct inet_ehash_bucket *inet_ehash_bucket( @@ -136,10 +136,10 @@ static inline struct inet_ehash_bucket *inet_ehash_bucket( } extern struct inet_bind_bucket * - inet_bind_bucket_create(kmem_cache_t *cachep, + inet_bind_bucket_create(struct kmem_cache *cachep, struct inet_bind_hashbucket *head, const unsigned short snum); -extern void inet_bind_bucket_destroy(kmem_cache_t *cachep, +extern void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket *tb); static inline int inet_bhashfn(const __u16 lport, const int bhash_size) diff --git a/include/net/neighbour.h b/include/net/neighbour.h index c8aacbd2e33..23967031ddb 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -160,7 +160,7 @@ struct neigh_table atomic_t entries; rwlock_t lock; unsigned long last_rand; - kmem_cache_t *kmem_cachep; + struct kmem_cache *kmem_cachep; struct neigh_statistics *stats; struct neighbour **hash_buckets; unsigned int hash_mask; diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index cef3136e22a..41bcc9eb420 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -7,7 +7,7 @@ #include extern struct list_head nf_conntrack_expect_list; -extern kmem_cache_t *nf_conntrack_expect_cachep; +extern struct kmem_cache *nf_conntrack_expect_cachep; extern struct file_operations exp_file_ops; struct nf_conntrack_expect diff --git a/include/net/request_sock.h b/include/net/request_sock.h index 426f0fe774e..7aed02ce2b6 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -29,7 +29,7 @@ struct proto; struct request_sock_ops { int family; int obj_size; - kmem_cache_t *slab; + struct kmem_cache *slab; int (*rtx_syn_ack)(struct sock *sk, struct request_sock *req, struct dst_entry *dst); diff --git a/include/net/sock.h b/include/net/sock.h index fe3a33fad03..730899ce516 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -571,7 +571,7 @@ struct proto { int *sysctl_rmem; int max_header; - kmem_cache_t *slab; + struct kmem_cache *slab; unsigned int obj_size; atomic_t *orphan_count; diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h index d7a306ea560..1e1ee3253fd 100644 --- a/include/net/timewait_sock.h +++ b/include/net/timewait_sock.h @@ -15,7 +15,7 @@ #include struct timewait_sock_ops { - kmem_cache_t *twsk_slab; + struct kmem_cache *twsk_slab; unsigned int twsk_obj_size; int (*twsk_unique)(struct sock *sk, struct sock *sktw, void *twp); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 9233ed5de66..0c775fceb67 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -557,7 +557,7 @@ struct sas_task { static inline struct sas_task *sas_alloc_task(gfp_t flags) { - extern kmem_cache_t *sas_task_cache; + extern struct kmem_cache *sas_task_cache; struct sas_task *task = kmem_cache_alloc(sas_task_cache, flags); if (task) { @@ -575,7 +575,7 @@ static inline struct sas_task *sas_alloc_task(gfp_t flags) static inline void sas_free_task(struct sas_task *task) { if (task) { - extern kmem_cache_t *sas_task_cache; + extern struct kmem_cache *sas_task_cache; BUG_ON(!list_empty(&task->list)); kmem_cache_free(sas_task_cache, task); } diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 813bb941342..3acc1661e51 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -90,7 +90,7 @@ static struct super_operations mqueue_super_ops; static void remove_notification(struct mqueue_inode_info *info); static spinlock_t mq_lock; -static kmem_cache_t *mqueue_inode_cachep; +static struct kmem_cache *mqueue_inode_cachep; static struct vfsmount *mqueue_mnt; static unsigned int queues_count; @@ -211,7 +211,7 @@ static int mqueue_get_sb(struct file_system_type *fs_type, return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt); } -static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags) { struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo; diff --git a/kernel/delayacct.c b/kernel/delayacct.c index 70e9ec60308..766d5912b26 100644 --- a/kernel/delayacct.c +++ b/kernel/delayacct.c @@ -20,7 +20,7 @@ #include int delayacct_on __read_mostly = 1; /* Delay accounting turned on/off */ -kmem_cache_t *delayacct_cache; +struct kmem_cache *delayacct_cache; static int __init delayacct_setup_disable(char *str) { diff --git a/kernel/fork.c b/kernel/fork.c index 711aa5f10da..2cf74edd329 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -82,26 +82,26 @@ int nr_processes(void) #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR # define alloc_task_struct() kmem_cache_alloc(task_struct_cachep, GFP_KERNEL) # define free_task_struct(tsk) kmem_cache_free(task_struct_cachep, (tsk)) -static kmem_cache_t *task_struct_cachep; +static struct kmem_cache *task_struct_cachep; #endif /* SLAB cache for signal_struct structures (tsk->signal) */ -static kmem_cache_t *signal_cachep; +static struct kmem_cache *signal_cachep; /* SLAB cache for sighand_struct structures (tsk->sighand) */ -kmem_cache_t *sighand_cachep; +struct kmem_cache *sighand_cachep; /* SLAB cache for files_struct structures (tsk->files) */ -kmem_cache_t *files_cachep; +struct kmem_cache *files_cachep; /* SLAB cache for fs_struct structures (tsk->fs) */ -kmem_cache_t *fs_cachep; +struct kmem_cache *fs_cachep; /* SLAB cache for vm_area_struct structures */ -kmem_cache_t *vm_area_cachep; +struct kmem_cache *vm_area_cachep; /* SLAB cache for mm_struct structures (tsk->mm) */ -static kmem_cache_t *mm_cachep; +static struct kmem_cache *mm_cachep; void free_task(struct task_struct *tsk) { @@ -1421,7 +1421,7 @@ long do_fork(unsigned long clone_flags, #define ARCH_MIN_MMSTRUCT_ALIGN 0 #endif -static void sighand_ctor(void *data, kmem_cache_t *cachep, unsigned long flags) +static void sighand_ctor(void *data, struct kmem_cache *cachep, unsigned long flags) { struct sighand_struct *sighand = data; diff --git a/kernel/pid.c b/kernel/pid.c index b914392085f..a48879b0b92 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -31,7 +31,7 @@ #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift) static struct hlist_head *pid_hash; static int pidhash_shift; -static kmem_cache_t *pid_cachep; +static struct kmem_cache *pid_cachep; int pid_max = PID_MAX_DEFAULT; diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 9cbb5d1be06..5fe87de10ff 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -70,7 +70,7 @@ /* * Lets keep our timers in a slab cache :-) */ -static kmem_cache_t *posix_timers_cache; +static struct kmem_cache *posix_timers_cache; static struct idr posix_timers_id; static DEFINE_SPINLOCK(idr_lock); diff --git a/kernel/signal.c b/kernel/signal.c index df18c167a2a..8e19d278548 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -33,7 +33,7 @@ * SLAB caches for signal bits. */ -static kmem_cache_t *sigqueue_cachep; +static struct kmem_cache *sigqueue_cachep; /* * In POSIX a signal is sent either to a specific thread (Linux task) diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 1b2b326cf70..f5f92014ae9 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -34,7 +34,7 @@ static DEFINE_PER_CPU(__u32, taskstats_seqnum) = { 0 }; static int family_registered; -kmem_cache_t *taskstats_cache; +struct kmem_cache *taskstats_cache; static struct genl_family family = { .id = GENL_ID_GENERATE, diff --git a/kernel/user.c b/kernel/user.c index c1f93c164c9..4869563080e 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -26,7 +26,7 @@ #define __uidhashfn(uid) (((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK) #define uidhashentry(uid) (uidhash_table + __uidhashfn((uid))) -static kmem_cache_t *uid_cachep; +static struct kmem_cache *uid_cachep; static struct list_head uidhash_table[UIDHASH_SZ]; /* diff --git a/lib/idr.c b/lib/idr.c index 16d2143fea4..71853531d3b 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -33,7 +33,7 @@ #include #include -static kmem_cache_t *idr_layer_cache; +static struct kmem_cache *idr_layer_cache; static struct idr_layer *alloc_layer(struct idr *idp) { @@ -445,7 +445,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id) } EXPORT_SYMBOL(idr_replace); -static void idr_cache_ctor(void * idr_layer, kmem_cache_t *idr_layer_cache, +static void idr_cache_ctor(void * idr_layer, struct kmem_cache *idr_layer_cache, unsigned long flags) { memset(idr_layer, 0, sizeof(struct idr_layer)); diff --git a/lib/radix-tree.c b/lib/radix-tree.c index aa9bfd0bdbd..9eb25955019 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -63,7 +63,7 @@ static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH] __read_mostly; /* * Radix tree node cache. */ -static kmem_cache_t *radix_tree_node_cachep; +static struct kmem_cache *radix_tree_node_cachep; /* * Per-cpu pool of preloaded nodes @@ -846,7 +846,7 @@ int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag) EXPORT_SYMBOL(radix_tree_tagged); static void -radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags) +radix_tree_node_ctor(void *node, struct kmem_cache *cachep, unsigned long flags) { memset(node, 0, sizeof(struct radix_tree_node)); } diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index d9f04864d15..8ca448db7a0 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -23,7 +23,7 @@ #include #include "br_private.h" -static kmem_cache_t *br_fdb_cache __read_mostly; +static struct kmem_cache *br_fdb_cache __read_mostly; static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr); diff --git a/net/core/flow.c b/net/core/flow.c index 5df3e297f81..104c25d00a1 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -44,7 +44,7 @@ static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables) = { NULL }; #define flow_table(cpu) (per_cpu(flow_tables, cpu)) -static kmem_cache_t *flow_cachep __read_mostly; +static struct kmem_cache *flow_cachep __read_mostly; static int flow_lwm, flow_hwm; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 7217fb8928f..de7801d589e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -68,8 +68,8 @@ #include "kmap_skb.h" -static kmem_cache_t *skbuff_head_cache __read_mostly; -static kmem_cache_t *skbuff_fclone_cache __read_mostly; +static struct kmem_cache *skbuff_head_cache __read_mostly; +static struct kmem_cache *skbuff_fclone_cache __read_mostly; /* * Keep out-of-line to prevent kernel bloat. @@ -144,7 +144,7 @@ EXPORT_SYMBOL(skb_truesize_bug); struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, int fclone, int node) { - kmem_cache_t *cache; + struct kmem_cache *cache; struct skb_shared_info *shinfo; struct sk_buff *skb; u8 *data; @@ -211,7 +211,7 @@ nodata: * Buffers may only be allocated from interrupts using a @gfp_mask of * %GFP_ATOMIC. */ -struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, +struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp, unsigned int size, gfp_t gfp_mask) { diff --git a/net/core/sock.c b/net/core/sock.c index 419c7d3289c..4a432da441e 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -841,7 +841,7 @@ struct sock *sk_alloc(int family, gfp_t priority, struct proto *prot, int zero_it) { struct sock *sk = NULL; - kmem_cache_t *slab = prot->slab; + struct kmem_cache *slab = prot->slab; if (slab != NULL) sk = kmem_cache_alloc(slab, priority); diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index bdf1bb7a82c..1f4727ddbdb 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -21,8 +21,8 @@ #include -static kmem_cache_t *dccp_ackvec_slab; -static kmem_cache_t *dccp_ackvec_record_slab; +static struct kmem_cache *dccp_ackvec_slab; +static struct kmem_cache *dccp_ackvec_record_slab; static struct dccp_ackvec_record *dccp_ackvec_record_new(void) { diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c index ff05e59043c..d8cf92f09e6 100644 --- a/net/dccp/ccid.c +++ b/net/dccp/ccid.c @@ -55,9 +55,9 @@ static inline void ccids_read_unlock(void) #define ccids_read_unlock() do { } while(0) #endif -static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...) +static struct kmem_cache *ccid_kmem_cache_create(int obj_size, const char *fmt,...) { - kmem_cache_t *slab; + struct kmem_cache *slab; char slab_name_fmt[32], *slab_name; va_list args; @@ -75,7 +75,7 @@ static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...) return slab; } -static void ccid_kmem_cache_destroy(kmem_cache_t *slab) +static void ccid_kmem_cache_destroy(struct kmem_cache *slab) { if (slab != NULL) { const char *name = kmem_cache_name(slab); diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index c7c29514dce..bcc2d12ae81 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -27,9 +27,9 @@ struct ccid_operations { unsigned char ccid_id; const char *ccid_name; struct module *ccid_owner; - kmem_cache_t *ccid_hc_rx_slab; + struct kmem_cache *ccid_hc_rx_slab; __u32 ccid_hc_rx_obj_size; - kmem_cache_t *ccid_hc_tx_slab; + struct kmem_cache *ccid_hc_tx_slab; __u32 ccid_hc_tx_obj_size; int (*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk); int (*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk); diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h index 0ae85f0340b..eb257014dd7 100644 --- a/net/dccp/ccids/lib/loss_interval.h +++ b/net/dccp/ccids/lib/loss_interval.h @@ -20,7 +20,7 @@ #define DCCP_LI_HIST_IVAL_F_LENGTH 8 struct dccp_li_hist { - kmem_cache_t *dccplih_slab; + struct kmem_cache *dccplih_slab; }; extern struct dccp_li_hist *dccp_li_hist_new(const char *name); diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h index 067cf1c85a3..9a8bcf224aa 100644 --- a/net/dccp/ccids/lib/packet_history.h +++ b/net/dccp/ccids/lib/packet_history.h @@ -68,14 +68,14 @@ struct dccp_rx_hist_entry { }; struct dccp_tx_hist { - kmem_cache_t *dccptxh_slab; + struct kmem_cache *dccptxh_slab; }; extern struct dccp_tx_hist *dccp_tx_hist_new(const char *name); extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist); struct dccp_rx_hist { - kmem_cache_t *dccprxh_slab; + struct kmem_cache *dccprxh_slab; }; extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name); diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index 101e5ccaf09..13b2421991b 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -79,7 +79,7 @@ for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_n static struct hlist_head dn_fib_table_hash[DN_FIB_TABLE_HASHSZ]; static DEFINE_RWLOCK(dn_fib_tables_lock); -static kmem_cache_t *dn_hash_kmem __read_mostly; +static struct kmem_cache *dn_hash_kmem __read_mostly; static int dn_fib_hash_zombies; static inline dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz) diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index 4463443e42c..648f47c1c39 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -45,8 +45,8 @@ #include "fib_lookup.h" -static kmem_cache_t *fn_hash_kmem __read_mostly; -static kmem_cache_t *fn_alias_kmem __read_mostly; +static struct kmem_cache *fn_hash_kmem __read_mostly; +static struct kmem_cache *fn_alias_kmem __read_mostly; struct fib_node { struct hlist_node fn_hash; diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 6be6caf1af3..cfb249cc0a5 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -172,7 +172,7 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn); static struct tnode *halve(struct trie *t, struct tnode *tn); static void tnode_free(struct tnode *tn); -static kmem_cache_t *fn_alias_kmem __read_mostly; +static struct kmem_cache *fn_alias_kmem __read_mostly; static struct trie *trie_local = NULL, *trie_main = NULL; diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index bd6c9bc4189..8c79c8a4ea5 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -27,7 +27,7 @@ * Allocate and initialize a new local port bind bucket. * The bindhash mutex for snum's hash chain must be held here. */ -struct inet_bind_bucket *inet_bind_bucket_create(kmem_cache_t *cachep, +struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep, struct inet_bind_hashbucket *head, const unsigned short snum) { @@ -45,7 +45,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(kmem_cache_t *cachep, /* * Caller must hold hashbucket lock for this tb with local BH disabled */ -void inet_bind_bucket_destroy(kmem_cache_t *cachep, struct inet_bind_bucket *tb) +void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket *tb) { if (hlist_empty(&tb->owners)) { __hlist_del(&tb->node); diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index f072f3875af..711eb6d0285 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -73,7 +73,7 @@ /* Exported for inet_getid inline function. */ DEFINE_SPINLOCK(inet_peer_idlock); -static kmem_cache_t *peer_cachep __read_mostly; +static struct kmem_cache *peer_cachep __read_mostly; #define node_height(x) x->avl_height static struct inet_peer peer_fake_node = { diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index efcf45ecc81..ecb5422ea23 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -105,7 +105,7 @@ static DEFINE_SPINLOCK(mfc_unres_lock); In this case data path is free of exclusive locks at all. */ -static kmem_cache_t *mrt_cachep __read_mostly; +static struct kmem_cache *mrt_cachep __read_mostly; static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local); static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert); diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index 8832eb517d5..8086787a2c5 100644 --- a/net/ipv4/ipvs/ip_vs_conn.c +++ b/net/ipv4/ipvs/ip_vs_conn.c @@ -44,7 +44,7 @@ static struct list_head *ip_vs_conn_tab; /* SLAB cache for IPVS connections */ -static kmem_cache_t *ip_vs_conn_cachep __read_mostly; +static struct kmem_cache *ip_vs_conn_cachep __read_mostly; /* counter for current IPVS connections */ static atomic_t ip_vs_conn_count = ATOMIC_INIT(0); diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index f4b0e68a16d..8556a4f4f60 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -65,8 +65,8 @@ static LIST_HEAD(helpers); unsigned int ip_conntrack_htable_size __read_mostly = 0; int ip_conntrack_max __read_mostly; struct list_head *ip_conntrack_hash __read_mostly; -static kmem_cache_t *ip_conntrack_cachep __read_mostly; -static kmem_cache_t *ip_conntrack_expect_cachep __read_mostly; +static struct kmem_cache *ip_conntrack_cachep __read_mostly; +static struct kmem_cache *ip_conntrack_expect_cachep __read_mostly; struct ip_conntrack ip_conntrack_untracked; unsigned int ip_ct_log_invalid __read_mostly; static LIST_HEAD(unconfirmed); diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 97a8cfbb61a..96d8310ae9c 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -50,7 +50,7 @@ struct rt6_statistics rt6_stats; -static kmem_cache_t * fib6_node_kmem __read_mostly; +static struct kmem_cache * fib6_node_kmem __read_mostly; enum fib_walk_state_t { diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index d4f68b0f27d..12e426b9aac 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -50,7 +50,7 @@ static u32 xfrm6_tunnel_spi; #define XFRM6_TUNNEL_SPI_MIN 1 #define XFRM6_TUNNEL_SPI_MAX 0xffffffff -static kmem_cache_t *xfrm6_tunnel_spi_kmem __read_mostly; +static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly; #define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256 #define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256 diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index eaa0f8a1adb..a9638ff52a7 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -108,7 +108,7 @@ static struct { size_t size; /* slab cache pointer */ - kmem_cache_t *cachep; + struct kmem_cache *cachep; /* allocated slab cache + modules which uses this slab cache */ int use; @@ -147,7 +147,7 @@ int nf_conntrack_register_cache(u_int32_t features, const char *name, { int ret = 0; char *cache_name; - kmem_cache_t *cachep; + struct kmem_cache *cachep; DEBUGP("nf_conntrack_register_cache: features=0x%x, name=%s, size=%d\n", features, name, size); @@ -226,7 +226,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_register_cache); /* FIXME: In the current, only nf_conntrack_cleanup() can call this function. */ void nf_conntrack_unregister_cache(u_int32_t features) { - kmem_cache_t *cachep; + struct kmem_cache *cachep; char *name; /* diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 588d3793704..c20f901fa17 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -29,7 +29,7 @@ LIST_HEAD(nf_conntrack_expect_list); EXPORT_SYMBOL_GPL(nf_conntrack_expect_list); -kmem_cache_t *nf_conntrack_expect_cachep __read_mostly; +struct kmem_cache *nf_conntrack_expect_cachep __read_mostly; static unsigned int nf_conntrack_expect_next_id; /* nf_conntrack_expect helper functions */ diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index a98de0b54d6..a5a6e192ac2 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -92,7 +92,7 @@ struct xt_hashlimit_htable { static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */ static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */ static HLIST_HEAD(hashlimit_htables); -static kmem_cache_t *hashlimit_cachep __read_mostly; +static struct kmem_cache *hashlimit_cachep __read_mostly; static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b) { diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 11f3b549f4a..f2ba8615895 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -79,8 +79,8 @@ static struct sctp_pf *sctp_pf_inet_specific; static struct sctp_af *sctp_af_v4_specific; static struct sctp_af *sctp_af_v6_specific; -kmem_cache_t *sctp_chunk_cachep __read_mostly; -kmem_cache_t *sctp_bucket_cachep __read_mostly; +struct kmem_cache *sctp_chunk_cachep __read_mostly; +struct kmem_cache *sctp_bucket_cachep __read_mostly; /* Return the address of the control sock. */ struct sock *sctp_get_ctl_sock(void) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 8d55d10041f..30927d3a597 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -65,7 +65,7 @@ #include #include -extern kmem_cache_t *sctp_chunk_cachep; +extern struct kmem_cache *sctp_chunk_cachep; SCTP_STATIC struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 49607792cbd..1e8132b8c4d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -107,7 +107,7 @@ static void sctp_sock_migrate(struct sock *, struct sock *, struct sctp_association *, sctp_socket_type_t); static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; -extern kmem_cache_t *sctp_bucket_cachep; +extern struct kmem_cache *sctp_bucket_cachep; /* Get the sndbuf space available at the time on the association. */ static inline int sctp_wspace(struct sctp_association *asoc) diff --git a/net/socket.c b/net/socket.c index 4f417c2ddc1..43eff489c87 100644 --- a/net/socket.c +++ b/net/socket.c @@ -230,7 +230,7 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, #define SOCKFS_MAGIC 0x534F434B -static kmem_cache_t *sock_inode_cachep __read_mostly; +static struct kmem_cache *sock_inode_cachep __read_mostly; static struct inode *sock_alloc_inode(struct super_block *sb) { @@ -257,7 +257,7 @@ static void sock_destroy_inode(struct inode *inode) container_of(inode, struct socket_alloc, vfs_inode)); } -static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct socket_alloc *ei = (struct socket_alloc *)foo; diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index df753d0a884..19703aa9659 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -33,7 +33,7 @@ static int rpc_mount_count; static struct file_system_type rpc_pipe_fs_type; -static kmem_cache_t *rpc_inode_cachep __read_mostly; +static struct kmem_cache *rpc_inode_cachep __read_mostly; #define RPC_UPCALL_TIMEOUT (30*HZ) @@ -824,7 +824,7 @@ static struct file_system_type rpc_pipe_fs_type = { }; static void -init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct rpc_inode *rpci = (struct rpc_inode *) foo; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index eff44bcdc95..225e6510b52 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -34,8 +34,8 @@ static int rpc_task_id; #define RPC_BUFFER_MAXSIZE (2048) #define RPC_BUFFER_POOLSIZE (8) #define RPC_TASK_POOLSIZE (8) -static kmem_cache_t *rpc_task_slabp __read_mostly; -static kmem_cache_t *rpc_buffer_slabp __read_mostly; +static struct kmem_cache *rpc_task_slabp __read_mostly; +static struct kmem_cache *rpc_buffer_slabp __read_mostly; static mempool_t *rpc_task_mempool __read_mostly; static mempool_t *rpc_buffer_mempool __read_mostly; diff --git a/net/tipc/handler.c b/net/tipc/handler.c index ae6ddf00a1a..eb80778d6d9 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c @@ -42,7 +42,7 @@ struct queue_item { unsigned long data; }; -static kmem_cache_t *tipc_queue_item_cache; +static struct kmem_cache *tipc_queue_item_cache; static struct list_head signal_queue_head; static DEFINE_SPINLOCK(qitem_lock); static int handler_enabled = 0; diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index a898a6a83a5..414f8907038 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -12,7 +12,7 @@ #include #include -static kmem_cache_t *secpath_cachep __read_mostly; +static struct kmem_cache *secpath_cachep __read_mostly; void __secpath_destroy(struct sec_path *sp) { diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index f6c77bd36fd..3f3f563eb4a 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -39,7 +39,7 @@ EXPORT_SYMBOL(xfrm_policy_count); static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; -static kmem_cache_t *xfrm_dst_cache __read_mostly; +static struct kmem_cache *xfrm_dst_cache __read_mostly; static struct work_struct xfrm_policy_gc_work; static HLIST_HEAD(xfrm_policy_gc_list); diff --git a/security/keys/key.c b/security/keys/key.c index 157bac658bf..0db816f10f8 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -20,7 +20,7 @@ #include #include "internal.h" -static kmem_cache_t *key_jar; +static struct kmem_cache *key_jar; struct rb_root key_serial_tree; /* tree of keys indexed by serial */ DEFINE_SPINLOCK(key_serial_lock); diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 65b4ec9c699..e7c0b5e2066 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -124,7 +124,7 @@ DEFINE_PER_CPU(struct avc_cache_stats, avc_cache_stats) = { 0 }; static struct avc_cache avc_cache; static struct avc_callback_node *avc_callbacks; -static kmem_cache_t *avc_node_cachep; +static struct kmem_cache *avc_node_cachep; static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) { diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ac1aeed0b28..44e9cd47054 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -124,7 +124,7 @@ static struct security_operations *secondary_ops = NULL; static LIST_HEAD(superblock_security_head); static DEFINE_SPINLOCK(sb_security_lock); -static kmem_cache_t *sel_inode_cache; +static struct kmem_cache *sel_inode_cache; /* Return security context for a given sid or just the context length if the buffer is null or length is 0 */ diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 2dfc6134c2c..ebb993c5c24 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -28,7 +28,7 @@ (keyp->source_type << 9)) & \ AVTAB_HASH_MASK) -static kmem_cache_t *avtab_node_cachep; +static struct kmem_cache *avtab_node_cachep; static struct avtab_node* avtab_insert_node(struct avtab *h, int hvalue, -- cgit v1.2.3-70-g09d2 From f5738ceed46782aea7663d62cb6398eb05fc4ce0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 6 Dec 2006 20:37:29 -0800 Subject: [PATCH] remove kernel syscalls The last thing we agreed on was to remove the macros entirely for 2.6.19, on all architectures. Unfortunately, I think nobody actually _did_ that, so they are still there. [akpm@osdl.org: x86_64 fix] Cc: David Woodhouse Cc: Greg Schafer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/vsyscall.c | 1 + include/asm-alpha/unistd.h | 182 ---------------------------- include/asm-arm/unistd.h | 150 ----------------------- include/asm-arm26/unistd.h | 133 --------------------- include/asm-frv/unistd.h | 119 ------------------- include/asm-h8300/unistd.h | 166 -------------------------- include/asm-i386/unistd.h | 98 --------------- include/asm-m32r/unistd.h | 111 ----------------- include/asm-m68k/unistd.h | 97 --------------- include/asm-m68knommu/unistd.h | 150 ----------------------- include/asm-mips/unistd.h | 262 ----------------------------------------- include/asm-powerpc/unistd.h | 109 ----------------- include/asm-s390/unistd.h | 154 ------------------------ include/asm-sh/unistd.h | 137 --------------------- include/asm-sh64/unistd.h | 142 ---------------------- include/asm-sparc/unistd.h | 130 -------------------- include/asm-sparc64/unistd.h | 118 ------------------- include/asm-v850/unistd.h | 160 ------------------------- include/asm-x86_64/unistd.h | 99 ---------------- include/asm-xtensa/unistd.h | 184 ----------------------------- 20 files changed, 1 insertion(+), 2701 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c index 92546c1526f..630036c06c7 100644 --- a/arch/x86_64/kernel/vsyscall.c +++ b/arch/x86_64/kernel/vsyscall.c @@ -42,6 +42,7 @@ #include #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr))) +#define __syscall_clobber "r11","rcx","memory" int __sysctl_vsyscall __section_sysctl_vsyscall = 1; seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED; diff --git a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h index 2cabbd465c0..84313d14e78 100644 --- a/include/asm-alpha/unistd.h +++ b/include/asm-alpha/unistd.h @@ -387,188 +387,6 @@ #define NR_SYSCALLS 447 -#if defined(__GNUC__) - -#define _syscall_return(type) \ - return (_sc_err ? errno = _sc_ret, _sc_ret = -1L : 0), (type) _sc_ret - -#define _syscall_clobbers \ - "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \ - "$22", "$23", "$24", "$25", "$27", "$28" \ - -#define _syscall0(type, name) \ -type name(void) \ -{ \ - long _sc_ret, _sc_err; \ - { \ - register long _sc_0 __asm__("$0"); \ - register long _sc_19 __asm__("$19"); \ - \ - _sc_0 = __NR_##name; \ - __asm__("callsys # %0 %1 %2" \ - : "=r"(_sc_0), "=r"(_sc_19) \ - : "0"(_sc_0) \ - : _syscall_clobbers); \ - _sc_ret = _sc_0, _sc_err = _sc_19; \ - } \ - _syscall_return(type); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ - long _sc_ret, _sc_err; \ - { \ - register long _sc_0 __asm__("$0"); \ - register long _sc_16 __asm__("$16"); \ - register long _sc_19 __asm__("$19"); \ - \ - _sc_0 = __NR_##name; \ - _sc_16 = (long) (arg1); \ - __asm__("callsys # %0 %1 %2 %3" \ - : "=r"(_sc_0), "=r"(_sc_19) \ - : "0"(_sc_0), "r"(_sc_16) \ - : _syscall_clobbers); \ - _sc_ret = _sc_0, _sc_err = _sc_19; \ - } \ - _syscall_return(type); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ - long _sc_ret, _sc_err; \ - { \ - register long _sc_0 __asm__("$0"); \ - register long _sc_16 __asm__("$16"); \ - register long _sc_17 __asm__("$17"); \ - register long _sc_19 __asm__("$19"); \ - \ - _sc_0 = __NR_##name; \ - _sc_16 = (long) (arg1); \ - _sc_17 = (long) (arg2); \ - __asm__("callsys # %0 %1 %2 %3 %4" \ - : "=r"(_sc_0), "=r"(_sc_19) \ - : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17) \ - : _syscall_clobbers); \ - _sc_ret = _sc_0, _sc_err = _sc_19; \ - } \ - _syscall_return(type); \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ - long _sc_ret, _sc_err; \ - { \ - register long _sc_0 __asm__("$0"); \ - register long _sc_16 __asm__("$16"); \ - register long _sc_17 __asm__("$17"); \ - register long _sc_18 __asm__("$18"); \ - register long _sc_19 __asm__("$19"); \ - \ - _sc_0 = __NR_##name; \ - _sc_16 = (long) (arg1); \ - _sc_17 = (long) (arg2); \ - _sc_18 = (long) (arg3); \ - __asm__("callsys # %0 %1 %2 %3 %4 %5" \ - : "=r"(_sc_0), "=r"(_sc_19) \ - : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17), \ - "r"(_sc_18) \ - : _syscall_clobbers); \ - _sc_ret = _sc_0, _sc_err = _sc_19; \ - } \ - _syscall_return(type); \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ - long _sc_ret, _sc_err; \ - { \ - register long _sc_0 __asm__("$0"); \ - register long _sc_16 __asm__("$16"); \ - register long _sc_17 __asm__("$17"); \ - register long _sc_18 __asm__("$18"); \ - register long _sc_19 __asm__("$19"); \ - \ - _sc_0 = __NR_##name; \ - _sc_16 = (long) (arg1); \ - _sc_17 = (long) (arg2); \ - _sc_18 = (long) (arg3); \ - _sc_19 = (long) (arg4); \ - __asm__("callsys # %0 %1 %2 %3 %4 %5 %6" \ - : "=r"(_sc_0), "=r"(_sc_19) \ - : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17), \ - "r"(_sc_18), "1"(_sc_19) \ - : _syscall_clobbers); \ - _sc_ret = _sc_0, _sc_err = _sc_19; \ - } \ - _syscall_return(type); \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ - long _sc_ret, _sc_err; \ - { \ - register long _sc_0 __asm__("$0"); \ - register long _sc_16 __asm__("$16"); \ - register long _sc_17 __asm__("$17"); \ - register long _sc_18 __asm__("$18"); \ - register long _sc_19 __asm__("$19"); \ - register long _sc_20 __asm__("$20"); \ - \ - _sc_0 = __NR_##name; \ - _sc_16 = (long) (arg1); \ - _sc_17 = (long) (arg2); \ - _sc_18 = (long) (arg3); \ - _sc_19 = (long) (arg4); \ - _sc_20 = (long) (arg5); \ - __asm__("callsys # %0 %1 %2 %3 %4 %5 %6 %7" \ - : "=r"(_sc_0), "=r"(_sc_19) \ - : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17), \ - "r"(_sc_18), "1"(_sc_19), "r"(_sc_20) \ - : _syscall_clobbers); \ - _sc_ret = _sc_0, _sc_err = _sc_19; \ - } \ - _syscall_return(type); \ -} - -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5,type6,arg6) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6)\ -{ \ - long _sc_ret, _sc_err; \ - { \ - register long _sc_0 __asm__("$0"); \ - register long _sc_16 __asm__("$16"); \ - register long _sc_17 __asm__("$17"); \ - register long _sc_18 __asm__("$18"); \ - register long _sc_19 __asm__("$19"); \ - register long _sc_20 __asm__("$20"); \ - register long _sc_21 __asm__("$21"); \ - \ - _sc_0 = __NR_##name; \ - _sc_16 = (long) (arg1); \ - _sc_17 = (long) (arg2); \ - _sc_18 = (long) (arg3); \ - _sc_19 = (long) (arg4); \ - _sc_20 = (long) (arg5); \ - _sc_21 = (long) (arg6); \ - __asm__("callsys # %0 %1 %2 %3 %4 %5 %6 %7 %8" \ - : "=r"(_sc_0), "=r"(_sc_19) \ - : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17), \ - "r"(_sc_18), "1"(_sc_19), "r"(_sc_20), "r"(_sc_21) \ - : _syscall_clobbers); \ - _sc_ret = _sc_0, _sc_err = _sc_19; \ - } \ - _syscall_return(type); \ -} - -#endif /* __GNUC__ */ - #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h index 14a87eec5a2..d44c629d842 100644 --- a/include/asm-arm/unistd.h +++ b/include/asm-arm/unistd.h @@ -377,156 +377,6 @@ #endif #ifdef __KERNEL__ -#include -#include - -#define __sys2(x) #x -#define __sys1(x) __sys2(x) - -#ifndef __syscall -#if defined(__thumb__) || defined(__ARM_EABI__) -#define __SYS_REG(name) register long __sysreg __asm__("r7") = __NR_##name; -#define __SYS_REG_LIST(regs...) "r" (__sysreg) , ##regs -#define __syscall(name) "swi\t0" -#else -#define __SYS_REG(name) -#define __SYS_REG_LIST(regs...) regs -#define __syscall(name) "swi\t" __sys1(__NR_##name) "" -#endif -#endif - -#define __syscall_return(type, res) \ -do { \ - if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \ - errno = -(res); \ - res = -1; \ - } \ - return (type) (res); \ -} while (0) - -#define _syscall0(type,name) \ -type name(void) { \ - __SYS_REG(name) \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : __SYS_REG_LIST() \ - : "memory" ); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) { \ - __SYS_REG(name) \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0) ) \ - : "memory" ); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) { \ - __SYS_REG(name) \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __r1 __asm__("r1") = (long)arg2; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) \ - : "memory" ); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) { \ - __SYS_REG(name) \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __r1 __asm__("r1") = (long)arg2; \ - register long __r2 __asm__("r2") = (long)arg3; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) \ - : "memory" ); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - __SYS_REG(name) \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __r1 __asm__("r1") = (long)arg2; \ - register long __r2 __asm__("r2") = (long)arg3; \ - register long __r3 __asm__("r3") = (long)arg4; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) \ - : "memory" ); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - __SYS_REG(name) \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __r1 __asm__("r1") = (long)arg2; \ - register long __r2 __asm__("r2") = (long)arg3; \ - register long __r3 __asm__("r3") = (long)arg4; \ - register long __r4 __asm__("r4") = (long)arg5; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \ - "r" (__r3), "r" (__r4) ) \ - : "memory" ); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - __SYS_REG(name) \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __r1 __asm__("r1") = (long)arg2; \ - register long __r2 __asm__("r2") = (long)arg3; \ - register long __r3 __asm__("r3") = (long)arg4; \ - register long __r4 __asm__("r4") = (long)arg5; \ - register long __r5 __asm__("r5") = (long)arg6; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \ - "r" (__r3), "r" (__r4), "r" (__r5) ) \ - : "memory" ); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_STAT64 diff --git a/include/asm-arm26/unistd.h b/include/asm-arm26/unistd.h index 25a5eead85b..4c3b919177e 100644 --- a/include/asm-arm26/unistd.h +++ b/include/asm-arm26/unistd.h @@ -311,139 +311,6 @@ #define __ARM_NR_usr26 (__ARM_NR_BASE+3) #ifdef __KERNEL__ -#include -#include - -#define __sys2(x) #x -#define __sys1(x) __sys2(x) - -#ifndef __syscall -#define __syscall(name) "swi\t" __sys1(__NR_##name) "" -#endif - -#define __syscall_return(type, res) \ -do { \ - if ((unsigned long)(res) >= (unsigned long)-MAX_ERRNO) { \ - errno = -(res); \ - res = -1; \ - } \ - return (type) (res); \ -} while (0) - -#define _syscall0(type,name) \ -type name(void) { \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : \ - : "lr"); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) { \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : "r" (__r0) \ - : "lr"); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) { \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __r1 __asm__("r1") = (long)arg2; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : "r" (__r0),"r" (__r1) \ - : "lr"); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) { \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __r1 __asm__("r1") = (long)arg2; \ - register long __r2 __asm__("r2") = (long)arg3; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : "r" (__r0),"r" (__r1),"r" (__r2) \ - : "lr"); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __r1 __asm__("r1") = (long)arg2; \ - register long __r2 __asm__("r2") = (long)arg3; \ - register long __r3 __asm__("r3") = (long)arg4; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3) \ - : "lr"); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __r1 __asm__("r1") = (long)arg2; \ - register long __r2 __asm__("r2") = (long)arg3; \ - register long __r3 __asm__("r3") = (long)arg4; \ - register long __r4 __asm__("r4") = (long)arg5; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3),"r" (__r4) \ - : "lr"); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} - -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ - register long __r0 __asm__("r0") = (long)arg1; \ - register long __r1 __asm__("r1") = (long)arg2; \ - register long __r2 __asm__("r2") = (long)arg3; \ - register long __r3 __asm__("r3") = (long)arg4; \ - register long __r4 __asm__("r4") = (long)arg5; \ - register long __r5 __asm__("r5") = (long)arg6; \ - register long __res_r0 __asm__("r0"); \ - long __res; \ - __asm__ __volatile__ ( \ - __syscall(name) \ - : "=r" (__res_r0) \ - : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3), "r" (__r4),"r" (__r5) \ - : "lr"); \ - __res = __res_r0; \ - __syscall_return(type,__res); \ -} #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h index 725e854928c..584c0417ae4 100644 --- a/include/asm-frv/unistd.h +++ b/include/asm-frv/unistd.h @@ -320,125 +320,6 @@ #ifdef __KERNEL__ #define NR_syscalls 310 -#include - -/* - * process the return value of a syscall, consigning it to one of two possible fates - * - user-visible error numbers are in the range -1 - -4095: see - */ -#undef __syscall_return -#define __syscall_return(type, res) \ -do { \ - unsigned long __sr2 = (res); \ - if (__builtin_expect(__sr2 >= (unsigned long)(-MAX_ERRNO), 0)) { \ - errno = (-__sr2); \ - __sr2 = ~0UL; \ - } \ - return (type) __sr2; \ -} while (0) - -/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ - -#undef _syscall0 -#define _syscall0(type,name) \ -type name(void) \ -{ \ - register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ - register unsigned long __sc0 __asm__ ("gr8"); \ - __asm__ __volatile__ ("tira gr0,#0" \ - : "=r" (__sc0) \ - : "r" (__scnum)); \ - __syscall_return(type, __sc0); \ -} - -#undef _syscall1 -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ - register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ - register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ - __asm__ __volatile__ ("tira gr0,#0" \ - : "+r" (__sc0) \ - : "r" (__scnum)); \ - __syscall_return(type, __sc0); \ -} - -#undef _syscall2 -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ - register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ - register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ - register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ - __asm__ __volatile__ ("tira gr0,#0" \ - : "+r" (__sc0) \ - : "r" (__scnum), "r" (__sc1)); \ - __syscall_return(type, __sc0); \ -} - -#undef _syscall3 -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ - register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ - register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ - register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ - register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ - __asm__ __volatile__ ("tira gr0,#0" \ - : "+r" (__sc0) \ - : "r" (__scnum), "r" (__sc1), "r" (__sc2)); \ - __syscall_return(type, __sc0); \ -} - -#undef _syscall4 -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ - register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ - register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ - register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ - register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ - register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4; \ - __asm__ __volatile__ ("tira gr0,#0" \ - : "+r" (__sc0) \ - : "r" (__scnum), "r" (__sc1), "r" (__sc2), "r" (__sc3)); \ - __syscall_return(type, __sc0); \ -} - -#undef _syscall5 -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ -{ \ - register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ - register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ - register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ - register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ - register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4; \ - register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5; \ - __asm__ __volatile__ ("tira gr0,#0" \ - : "+r" (__sc0) \ - : "r" (__scnum), "r" (__sc1), "r" (__sc2), \ - "r" (__sc3), "r" (__sc4)); \ - __syscall_return(type, __sc0); \ -} - -#undef _syscall6 -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5, type6, arg6) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ -{ \ - register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ - register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ - register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ - register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ - register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4; \ - register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5; \ - register unsigned long __sc5 __asm__ ("gr13") = (unsigned long) arg6; \ - __asm__ __volatile__ ("tira gr0,#0" \ - : "+r" (__sc0) \ - : "r" (__scnum), "r" (__sc1), "r" (__sc2), \ - "r" (__sc3), "r" (__sc4), "r" (__sc5)); \ - __syscall_return(type, __sc0); \ -} #define __ARCH_WANT_IPC_PARSE_VERSION /* #define __ARCH_WANT_OLD_READDIR */ diff --git a/include/asm-h8300/unistd.h b/include/asm-h8300/unistd.h index 747788d629a..7ddd414f8d1 100644 --- a/include/asm-h8300/unistd.h +++ b/include/asm-h8300/unistd.h @@ -295,172 +295,6 @@ #ifdef __KERNEL__ #define NR_syscalls 289 -#include - -/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see - */ - -#define __syscall_return(type, res) \ -do { \ - if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \ - /* avoid using res which is declared to be in register d0; \ - errno might expand to a function call and clobber it. */ \ - int __err = -(res); \ - errno = __err; \ - res = -1; \ - } \ - return (type) (res); \ -} while (0) - -#define _syscall0(type, name) \ -type name(void) \ -{ \ - register long __res __asm__("er0"); \ - __asm__ __volatile__ ("mov.l %1,er0\n\t" \ - "trapa #0\n\t" \ - : "=r" (__res) \ - : "g" (__NR_##name) \ - : "cc", "memory"); \ - __syscall_return(type, __res); \ -} - -#define _syscall1(type, name, atype, a) \ -type name(atype a) \ -{ \ - register long __res __asm__("er0"); \ - register long _a __asm__("er1"); \ - _a = (long)a; \ - __asm__ __volatile__ ("mov.l %1,er0\n\t" \ - "trapa #0\n\t" \ - : "=r" (__res) \ - : "g" (__NR_##name), \ - "g" (_a) \ - : "cc", "memory"); \ - __syscall_return(type, __res); \ -} - -#define _syscall2(type, name, atype, a, btype, b) \ -type name(atype a, btype b) \ -{ \ - register long __res __asm__("er0"); \ - register long _a __asm__("er1"); \ - register long _b __asm__("er2"); \ - _a = (long)a; \ - _b = (long)b; \ - __asm__ __volatile__ ("mov.l %1,er0\n\t" \ - "trapa #0\n\t" \ - : "=r" (__res) \ - : "g" (__NR_##name), \ - "g" (_a), \ - "g" (_b) \ - : "cc", "memory"); \ - __syscall_return(type, __res); \ -} - -#define _syscall3(type, name, atype, a, btype, b, ctype, c) \ -type name(atype a, btype b, ctype c) \ -{ \ - register long __res __asm__("er0"); \ - register long _a __asm__("er1"); \ - register long _b __asm__("er2"); \ - register long _c __asm__("er3"); \ - _a = (long)a; \ - _b = (long)b; \ - _c = (long)c; \ - __asm__ __volatile__ ("mov.l %1,er0\n\t" \ - "trapa #0\n\t" \ - : "=r" (__res) \ - : "g" (__NR_##name), \ - "g" (_a), \ - "g" (_b), \ - "g" (_c) \ - : "cc", "memory"); \ - __syscall_return(type, __res); \ -} - -#define _syscall4(type, name, atype, a, btype, b, \ - ctype, c, dtype, d) \ -type name(atype a, btype b, ctype c, dtype d) \ -{ \ - register long __res __asm__("er0"); \ - register long _a __asm__("er1"); \ - register long _b __asm__("er2"); \ - register long _c __asm__("er3"); \ - register long _d __asm__("er4"); \ - _a = (long)a; \ - _b = (long)b; \ - _c = (long)c; \ - _d = (long)d; \ - __asm__ __volatile__ ("mov.l %1,er0\n\t" \ - "trapa #0\n\t" \ - : "=r" (__res) \ - : "g" (__NR_##name), \ - "g" (_a), \ - "g" (_b), \ - "g" (_c), \ - "g" (_d) \ - : "cc", "memory"); \ - __syscall_return(type, __res); \ -} - -#define _syscall5(type, name, atype, a, btype, b, \ - ctype, c, dtype, d, etype, e) \ -type name(atype a, btype b, ctype c, dtype d, etype e) \ -{ \ - register long __res __asm__("er0"); \ - register long _a __asm__("er1"); \ - register long _b __asm__("er2"); \ - register long _c __asm__("er3"); \ - register long _d __asm__("er4"); \ - register long _e __asm__("er5"); \ - _a = (long)a; \ - _b = (long)b; \ - _c = (long)c; \ - _d = (long)d; \ - _e = (long)e; \ - __asm__ __volatile__ ("mov.l %1,er0\n\t" \ - "trapa #0\n\t" \ - : "=r" (__res) \ - : "g" (__NR_##name), \ - "g" (_a), \ - "g" (_b), \ - "g" (_c), \ - "g" (_d), \ - "g" (_e) \ - : "cc", "memory"); \ - __syscall_return(type, __res); \ -} - -#define _syscall6(type, name, atype, a, btype, b, \ - ctype, c, dtype, d, etype, e, ftype, f) \ -type name(atype a, btype b, ctype c, dtype d, etype e, ftype f) \ -{ \ - register long __res __asm__("er0"); \ - register long _a __asm__("er1"); \ - register long _b __asm__("er2"); \ - register long _c __asm__("er3"); \ - register long _d __asm__("er4"); \ - register long _e __asm__("er5"); \ - register long _f __asm__("er6"); \ - _a = (long)a; \ - _b = (long)b; \ - _c = (long)c; \ - _d = (long)d; \ - _e = (long)e; \ - _f = (long)f; \ - __asm__ __volatile__ ("mov.l %1,er0\n\t" \ - "trapa #0\n\t" \ - : "=r" (__res) \ - : "g" (__NR_##name), \ - "g" (_a), \ - "g" (_b), \ - "g" (_c), \ - "g" (_d), \ - "g" (_e) \ - "g" (_f) \ - : "cc", "memory"); \ - __syscall_return(type, __res); \ -} #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index beeeaf6b054..833fa1704ff 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -329,104 +329,6 @@ #ifdef __KERNEL__ #define NR_syscalls 320 -#include - -/* - * user-visible error numbers are in the range -1 - -MAX_ERRNO: see - * - */ -#define __syscall_return(type, res) \ -do { \ - if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \ - errno = -(res); \ - res = -1; \ - } \ - return (type) (res); \ -} while (0) - -/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ -#define _syscall0(type,name) \ -type name(void) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name)); \ -__syscall_return(type,__res); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ -long __res; \ -__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ - : "=a" (__res) \ - : "0" (__NR_##name),"ri" ((long)(arg1)) : "memory"); \ -__syscall_return(type,__res); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ -long __res; \ -__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ - : "=a" (__res) \ - : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)) \ - : "memory"); \ -__syscall_return(type,__res); \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ -long __res; \ -__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ - : "=a" (__res) \ - : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)) : "memory"); \ -__syscall_return(type,__res); \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ -long __res; \ -__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ - : "=a" (__res) \ - : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); \ -__syscall_return(type,__res); \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ -long __res; \ -__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; movl %1,%%eax ; " \ - "int $0x80 ; pop %%ebx" \ - : "=a" (__res) \ - : "i" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \ - : "memory"); \ -__syscall_return(type,__res); \ -} - -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5,type6,arg6) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ -{ \ -long __res; \ - struct { long __a1; long __a6; } __s = { (long)arg1, (long)arg6 }; \ -__asm__ volatile ("push %%ebp ; push %%ebx ; movl 4(%2),%%ebp ; " \ - "movl 0(%2),%%ebx ; movl %1,%%eax ; int $0x80 ; " \ - "pop %%ebx ; pop %%ebp" \ - : "=a" (__res) \ - : "i" (__NR_##name),"0" ((long)(&__s)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \ - : "memory"); \ -__syscall_return(type,__res); \ -} #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h index 95aa34298d8..5b66bd3c6ed 100644 --- a/include/asm-m32r/unistd.h +++ b/include/asm-m32r/unistd.h @@ -296,117 +296,6 @@ #ifdef __KERNEL__ #define NR_syscalls 285 -#include - -/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see - * - */ - -#include /* SYSCALL_* */ - -#define __syscall_return(type, res) \ -do { \ - if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \ - /* Avoid using "res" which is declared to be in register r0; \ - errno might expand to a function call and clobber it. */ \ - int __err = -(res); \ - errno = __err; \ - res = -1; \ - } \ - return (type) (res); \ -} while (0) - -#define _syscall0(type,name) \ -type name(void) \ -{ \ -register long __scno __asm__ ("r7") = __NR_##name; \ -register long __res __asm__("r0"); \ -__asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ - : "=r" (__res) \ - : "r" (__scno) \ - : "memory"); \ -__syscall_return(type,__res); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ -register long __scno __asm__ ("r7") = __NR_##name; \ -register long __res __asm__ ("r0") = (long)(arg1); \ -__asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ - : "=r" (__res) \ - : "r" (__scno), "0" (__res) \ - : "memory"); \ -__syscall_return(type,__res); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ -register long __scno __asm__ ("r7") = __NR_##name; \ -register long __arg2 __asm__ ("r1") = (long)(arg2); \ -register long __res __asm__ ("r0") = (long)(arg1); \ -__asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ - : "=r" (__res) \ - : "r" (__scno), "0" (__res), "r" (__arg2) \ - : "memory"); \ -__syscall_return(type,__res); \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ -register long __scno __asm__ ("r7") = __NR_##name; \ -register long __arg3 __asm__ ("r2") = (long)(arg3); \ -register long __arg2 __asm__ ("r1") = (long)(arg2); \ -register long __res __asm__ ("r0") = (long)(arg1); \ -__asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ - : "=r" (__res) \ - : "r" (__scno), "0" (__res), "r" (__arg2), \ - "r" (__arg3) \ - : "memory"); \ -__syscall_return(type,__res); \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name(type1 arg1,type2 arg2,type3 arg3,type4 arg4) \ -{ \ -register long __scno __asm__ ("r7") = __NR_##name; \ -register long __arg4 __asm__ ("r3") = (long)(arg4); \ -register long __arg3 __asm__ ("r2") = (long)(arg3); \ -register long __arg2 __asm__ ("r1") = (long)(arg2); \ -register long __res __asm__ ("r0") = (long)(arg1); \ -__asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ - : "=r" (__res) \ - : "r" (__scno), "0" (__res), "r" (__arg2), \ - "r" (__arg3), "r" (__arg4) \ - : "memory"); \ -__syscall_return(type,__res); \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name(type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ -register long __scno __asm__ ("r7") = __NR_##name; \ -register long __arg5 __asm__ ("r4") = (long)(arg5); \ -register long __arg4 __asm__ ("r3") = (long)(arg4); \ -register long __arg3 __asm__ ("r2") = (long)(arg3); \ -register long __arg2 __asm__ ("r1") = (long)(arg2); \ -register long __res __asm__ ("r0") = (long)(arg1); \ -__asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ - : "=r" (__res) \ - : "r" (__scno), "0" (__res), "r" (__arg2), \ - "r" (__arg3), "r" (__arg4), "r" (__arg5) \ - : "memory"); \ -__syscall_return(type,__res); \ -} #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_STAT64 diff --git a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h index ad4348058c6..fdbb60e6a0d 100644 --- a/include/asm-m68k/unistd.h +++ b/include/asm-m68k/unistd.h @@ -317,103 +317,6 @@ #ifdef __KERNEL__ #define NR_syscalls 311 -#include - -/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see - */ - -#define __syscall_return(type, res) \ -do { \ - if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \ - /* avoid using res which is declared to be in register d0; \ - errno might expand to a function call and clobber it. */ \ - int __err = -(res); \ - errno = __err; \ - res = -1; \ - } \ - return (type) (res); \ -} while (0) - -#define _syscall0(type,name) \ -type name(void) \ -{ \ -register long __res __asm__ ("%d0") = __NR_##name; \ -__asm__ __volatile__ ("trap #0" \ - : "+d" (__res) ); \ -__syscall_return(type,__res); \ -} - -#define _syscall1(type,name,atype,a) \ -type name(atype a) \ -{ \ -register long __res __asm__ ("%d0") = __NR_##name; \ -register long __a __asm__ ("%d1") = (long)(a); \ -__asm__ __volatile__ ("trap #0" \ - : "+d" (__res) \ - : "d" (__a) ); \ -__syscall_return(type,__res); \ -} - -#define _syscall2(type,name,atype,a,btype,b) \ -type name(atype a,btype b) \ -{ \ -register long __res __asm__ ("%d0") = __NR_##name; \ -register long __a __asm__ ("%d1") = (long)(a); \ -register long __b __asm__ ("%d2") = (long)(b); \ -__asm__ __volatile__ ("trap #0" \ - : "+d" (__res) \ - : "d" (__a), "d" (__b) \ - ); \ -__syscall_return(type,__res); \ -} - -#define _syscall3(type,name,atype,a,btype,b,ctype,c) \ -type name(atype a,btype b,ctype c) \ -{ \ -register long __res __asm__ ("%d0") = __NR_##name; \ -register long __a __asm__ ("%d1") = (long)(a); \ -register long __b __asm__ ("%d2") = (long)(b); \ -register long __c __asm__ ("%d3") = (long)(c); \ -__asm__ __volatile__ ("trap #0" \ - : "+d" (__res) \ - : "d" (__a), "d" (__b), \ - "d" (__c) \ - ); \ -__syscall_return(type,__res); \ -} - -#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \ -type name (atype a, btype b, ctype c, dtype d) \ -{ \ -register long __res __asm__ ("%d0") = __NR_##name; \ -register long __a __asm__ ("%d1") = (long)(a); \ -register long __b __asm__ ("%d2") = (long)(b); \ -register long __c __asm__ ("%d3") = (long)(c); \ -register long __d __asm__ ("%d4") = (long)(d); \ -__asm__ __volatile__ ("trap #0" \ - : "+d" (__res) \ - : "d" (__a), "d" (__b), \ - "d" (__c), "d" (__d) \ - ); \ -__syscall_return(type,__res); \ -} - -#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \ -type name (atype a,btype b,ctype c,dtype d,etype e) \ -{ \ -register long __res __asm__ ("%d0") = __NR_##name; \ -register long __a __asm__ ("%d1") = (long)(a); \ -register long __b __asm__ ("%d2") = (long)(b); \ -register long __c __asm__ ("%d3") = (long)(c); \ -register long __d __asm__ ("%d4") = (long)(d); \ -register long __e __asm__ ("%d5") = (long)(e); \ -__asm__ __volatile__ ("trap #0" \ - : "+d" (__res) \ - : "d" (__a), "d" (__b), \ - "d" (__c), "d" (__d), "d" (__e) \ - ); \ -__syscall_return(type,__res); \ -} #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-m68knommu/unistd.h b/include/asm-m68knommu/unistd.h index ebaf0319711..82e03195f32 100644 --- a/include/asm-m68knommu/unistd.h +++ b/include/asm-m68knommu/unistd.h @@ -318,156 +318,6 @@ #ifdef __KERNEL__ #define NR_syscalls 311 -#include - -/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see - */ - -#define __syscall_return(type, res) \ -do { \ - if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \ - /* avoid using res which is declared to be in register d0; \ - errno might expand to a function call and clobber it. */ \ - int __err = -(res); \ - errno = __err; \ - res = -1; \ - } \ - return (type) (res); \ -} while (0) - -#define _syscall0(type, name) \ -type name(void) \ -{ \ - long __res; \ - __asm__ __volatile__ ("movel %1, %%d0\n\t" \ - "trap #0\n\t" \ - "movel %%d0, %0" \ - : "=g" (__res) \ - : "i" (__NR_##name) \ - : "cc", "%d0"); \ - if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ - errno = -__res; \ - __res = -1; \ - } \ - return (type)__res; \ -} - -#define _syscall1(type, name, atype, a) \ -type name(atype a) \ -{ \ - long __res; \ - __asm__ __volatile__ ("movel %2, %%d1\n\t" \ - "movel %1, %%d0\n\t" \ - "trap #0\n\t" \ - "movel %%d0, %0" \ - : "=g" (__res) \ - : "i" (__NR_##name), \ - "g" ((long)a) \ - : "cc", "%d0", "%d1"); \ - if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ - errno = -__res; \ - __res = -1; \ - } \ - return (type)__res; \ -} - -#define _syscall2(type, name, atype, a, btype, b) \ -type name(atype a, btype b) \ -{ \ - long __res; \ - __asm__ __volatile__ ("movel %3, %%d2\n\t" \ - "movel %2, %%d1\n\t" \ - "movel %1, %%d0\n\t" \ - "trap #0\n\t" \ - "movel %%d0, %0" \ - : "=g" (__res) \ - : "i" (__NR_##name), \ - "a" ((long)a), \ - "g" ((long)b) \ - : "cc", "%d0", "%d1", "%d2"); \ - if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ - errno = -__res; \ - __res = -1; \ - } \ - return (type)__res; \ -} - -#define _syscall3(type, name, atype, a, btype, b, ctype, c) \ -type name(atype a, btype b, ctype c) \ -{ \ - long __res; \ - __asm__ __volatile__ ("movel %4, %%d3\n\t" \ - "movel %3, %%d2\n\t" \ - "movel %2, %%d1\n\t" \ - "movel %1, %%d0\n\t" \ - "trap #0\n\t" \ - "movel %%d0, %0" \ - : "=g" (__res) \ - : "i" (__NR_##name), \ - "a" ((long)a), \ - "a" ((long)b), \ - "g" ((long)c) \ - : "cc", "%d0", "%d1", "%d2", "%d3"); \ - if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ - errno = -__res; \ - __res = -1; \ - } \ - return (type)__res; \ -} - -#define _syscall4(type, name, atype, a, btype, b, ctype, c, dtype, d) \ -type name(atype a, btype b, ctype c, dtype d) \ -{ \ - long __res; \ - __asm__ __volatile__ ("movel %5, %%d4\n\t" \ - "movel %4, %%d3\n\t" \ - "movel %3, %%d2\n\t" \ - "movel %2, %%d1\n\t" \ - "movel %1, %%d0\n\t" \ - "trap #0\n\t" \ - "movel %%d0, %0" \ - : "=g" (__res) \ - : "i" (__NR_##name), \ - "a" ((long)a), \ - "a" ((long)b), \ - "a" ((long)c), \ - "g" ((long)d) \ - : "cc", "%d0", "%d1", "%d2", "%d3", \ - "%d4"); \ - if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ - errno = -__res; \ - __res = -1; \ - } \ - return (type)__res; \ -} - -#define _syscall5(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e) \ -type name(atype a, btype b, ctype c, dtype d, etype e) \ -{ \ - long __res; \ - __asm__ __volatile__ ("movel %6, %%d5\n\t" \ - "movel %5, %%d4\n\t" \ - "movel %4, %%d3\n\t" \ - "movel %3, %%d2\n\t" \ - "movel %2, %%d1\n\t" \ - "movel %1, %%d0\n\t" \ - "trap #0\n\t" \ - "movel %%d0, %0" \ - : "=g" (__res) \ - : "i" (__NR_##name), \ - "a" ((long)a), \ - "a" ((long)b), \ - "a" ((long)c), \ - "a" ((long)d), \ - "g" ((long)e) \ - : "cc", "%d0", "%d1", "%d2", "%d3", \ - "%d4", "%d5"); \ - if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ - errno = -__res; \ - __res = -1; \ - } \ - return (type)__res; \ -} #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h index ec56aa52f66..696cff39a1d 100644 --- a/include/asm-mips/unistd.h +++ b/include/asm-mips/unistd.h @@ -933,268 +933,6 @@ #ifndef __ASSEMBLY__ -/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ -#define _syscall0(type,name) \ -type name(void) \ -{ \ - register unsigned long __a3 asm("$7"); \ - unsigned long __v0; \ - \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %2\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "move\t%0, $2\n\t" \ - ".set\treorder" \ - : "=&r" (__v0), "=r" (__a3) \ - : "i" (__NR_##name) \ - : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ - "memory"); \ - \ - if (__a3 == 0) \ - return (type) __v0; \ - errno = __v0; \ - return (type) -1; \ -} - -/* - * DANGER: This macro isn't usable for the pipe(2) call - * which has a unusual return convention. - */ -#define _syscall1(type,name,atype,a) \ -type name(atype a) \ -{ \ - register unsigned long __a0 asm("$4") = (unsigned long) a; \ - register unsigned long __a3 asm("$7"); \ - unsigned long __v0; \ - \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %3\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "move\t%0, $2\n\t" \ - ".set\treorder" \ - : "=&r" (__v0), "=r" (__a3) \ - : "r" (__a0), "i" (__NR_##name) \ - : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ - "memory"); \ - \ - if (__a3 == 0) \ - return (type) __v0; \ - errno = __v0; \ - return (type) -1; \ -} - -#define _syscall2(type,name,atype,a,btype,b) \ -type name(atype a, btype b) \ -{ \ - register unsigned long __a0 asm("$4") = (unsigned long) a; \ - register unsigned long __a1 asm("$5") = (unsigned long) b; \ - register unsigned long __a3 asm("$7"); \ - unsigned long __v0; \ - \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %4\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "move\t%0, $2\n\t" \ - ".set\treorder" \ - : "=&r" (__v0), "=r" (__a3) \ - : "r" (__a0), "r" (__a1), "i" (__NR_##name) \ - : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ - "memory"); \ - \ - if (__a3 == 0) \ - return (type) __v0; \ - errno = __v0; \ - return (type) -1; \ -} - -#define _syscall3(type,name,atype,a,btype,b,ctype,c) \ -type name(atype a, btype b, ctype c) \ -{ \ - register unsigned long __a0 asm("$4") = (unsigned long) a; \ - register unsigned long __a1 asm("$5") = (unsigned long) b; \ - register unsigned long __a2 asm("$6") = (unsigned long) c; \ - register unsigned long __a3 asm("$7"); \ - unsigned long __v0; \ - \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %5\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "move\t%0, $2\n\t" \ - ".set\treorder" \ - : "=&r" (__v0), "=r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name) \ - : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ - "memory"); \ - \ - if (__a3 == 0) \ - return (type) __v0; \ - errno = __v0; \ - return (type) -1; \ -} - -#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \ -type name(atype a, btype b, ctype c, dtype d) \ -{ \ - register unsigned long __a0 asm("$4") = (unsigned long) a; \ - register unsigned long __a1 asm("$5") = (unsigned long) b; \ - register unsigned long __a2 asm("$6") = (unsigned long) c; \ - register unsigned long __a3 asm("$7") = (unsigned long) d; \ - unsigned long __v0; \ - \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %5\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "move\t%0, $2\n\t" \ - ".set\treorder" \ - : "=&r" (__v0), "+r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name) \ - : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ - "memory"); \ - \ - if (__a3 == 0) \ - return (type) __v0; \ - errno = __v0; \ - return (type) -1; \ -} - -#if (_MIPS_SIM == _MIPS_SIM_ABI32) - -/* - * Using those means your brain needs more than an oil change ;-) - */ - -#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \ -type name(atype a, btype b, ctype c, dtype d, etype e) \ -{ \ - register unsigned long __a0 asm("$4") = (unsigned long) a; \ - register unsigned long __a1 asm("$5") = (unsigned long) b; \ - register unsigned long __a2 asm("$6") = (unsigned long) c; \ - register unsigned long __a3 asm("$7") = (unsigned long) d; \ - unsigned long __v0; \ - \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "lw\t$2, %6\n\t" \ - "subu\t$29, 32\n\t" \ - "sw\t$2, 16($29)\n\t" \ - "li\t$2, %5\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "move\t%0, $2\n\t" \ - "addiu\t$29, 32\n\t" \ - ".set\treorder" \ - : "=&r" (__v0), "+r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name), \ - "m" ((unsigned long)e) \ - : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ - "memory"); \ - \ - if (__a3 == 0) \ - return (type) __v0; \ - errno = __v0; \ - return (type) -1; \ -} - -#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \ -type name(atype a, btype b, ctype c, dtype d, etype e, ftype f) \ -{ \ - register unsigned long __a0 asm("$4") = (unsigned long) a; \ - register unsigned long __a1 asm("$5") = (unsigned long) b; \ - register unsigned long __a2 asm("$6") = (unsigned long) c; \ - register unsigned long __a3 asm("$7") = (unsigned long) d; \ - unsigned long __v0; \ - \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "lw\t$2, %6\n\t" \ - "lw\t$8, %7\n\t" \ - "subu\t$29, 32\n\t" \ - "sw\t$2, 16($29)\n\t" \ - "sw\t$8, 20($29)\n\t" \ - "li\t$2, %5\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "move\t%0, $2\n\t" \ - "addiu\t$29, 32\n\t" \ - ".set\treorder" \ - : "=&r" (__v0), "+r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name), \ - "m" ((unsigned long)e), "m" ((unsigned long)f) \ - : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ - "memory"); \ - \ - if (__a3 == 0) \ - return (type) __v0; \ - errno = __v0; \ - return (type) -1; \ -} - -#endif /* (_MIPS_SIM == _MIPS_SIM_ABI32) */ - -#if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) - -#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \ -type name (atype a,btype b,ctype c,dtype d,etype e) \ -{ \ - register unsigned long __a0 asm("$4") = (unsigned long) a; \ - register unsigned long __a1 asm("$5") = (unsigned long) b; \ - register unsigned long __a2 asm("$6") = (unsigned long) c; \ - register unsigned long __a3 asm("$7") = (unsigned long) d; \ - register unsigned long __a4 asm("$8") = (unsigned long) e; \ - unsigned long __v0; \ - \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %6\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "move\t%0, $2\n\t" \ - ".set\treorder" \ - : "=&r" (__v0), "+r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4), "i" (__NR_##name) \ - : "$2", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ - "memory"); \ - \ - if (__a3 == 0) \ - return (type) __v0; \ - errno = __v0; \ - return (type) -1; \ -} - -#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \ -type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \ -{ \ - register unsigned long __a0 asm("$4") = (unsigned long) a; \ - register unsigned long __a1 asm("$5") = (unsigned long) b; \ - register unsigned long __a2 asm("$6") = (unsigned long) c; \ - register unsigned long __a3 asm("$7") = (unsigned long) d; \ - register unsigned long __a4 asm("$8") = (unsigned long) e; \ - register unsigned long __a5 asm("$9") = (unsigned long) f; \ - unsigned long __v0; \ - \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %7\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "move\t%0, $2\n\t" \ - ".set\treorder" \ - : "=&r" (__v0), "+r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4), "r" (__a5), \ - "i" (__NR_##name) \ - : "$2", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ - "memory"); \ - \ - if (__a3 == 0) \ - return (type) __v0; \ - errno = __v0; \ - return (type) -1; \ -} - -#endif /* (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) */ - - #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index 04b6c17cc59..0ae954e3d25 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h @@ -334,115 +334,6 @@ #ifndef __ASSEMBLY__ -/* On powerpc a system call basically clobbers the same registers like a - * function call, with the exception of LR (which is needed for the - * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal - * an error return status). - */ - -#define __syscall_nr(nr, type, name, args...) \ - unsigned long __sc_ret, __sc_err; \ - { \ - register unsigned long __sc_0 __asm__ ("r0"); \ - register unsigned long __sc_3 __asm__ ("r3"); \ - register unsigned long __sc_4 __asm__ ("r4"); \ - register unsigned long __sc_5 __asm__ ("r5"); \ - register unsigned long __sc_6 __asm__ ("r6"); \ - register unsigned long __sc_7 __asm__ ("r7"); \ - register unsigned long __sc_8 __asm__ ("r8"); \ - \ - __sc_loadargs_##nr(name, args); \ - __asm__ __volatile__ \ - ("sc \n\t" \ - "mfcr %0 " \ - : "=&r" (__sc_0), \ - "=&r" (__sc_3), "=&r" (__sc_4), \ - "=&r" (__sc_5), "=&r" (__sc_6), \ - "=&r" (__sc_7), "=&r" (__sc_8) \ - : __sc_asm_input_##nr \ - : "cr0", "ctr", "memory", \ - "r9", "r10","r11", "r12"); \ - __sc_ret = __sc_3; \ - __sc_err = __sc_0; \ - } \ - if (__sc_err & 0x10000000) \ - { \ - errno = __sc_ret; \ - __sc_ret = -1; \ - } \ - return (type) __sc_ret - -#define __sc_loadargs_0(name, dummy...) \ - __sc_0 = __NR_##name -#define __sc_loadargs_1(name, arg1) \ - __sc_loadargs_0(name); \ - __sc_3 = (unsigned long) (arg1) -#define __sc_loadargs_2(name, arg1, arg2) \ - __sc_loadargs_1(name, arg1); \ - __sc_4 = (unsigned long) (arg2) -#define __sc_loadargs_3(name, arg1, arg2, arg3) \ - __sc_loadargs_2(name, arg1, arg2); \ - __sc_5 = (unsigned long) (arg3) -#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4) \ - __sc_loadargs_3(name, arg1, arg2, arg3); \ - __sc_6 = (unsigned long) (arg4) -#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5) \ - __sc_loadargs_4(name, arg1, arg2, arg3, arg4); \ - __sc_7 = (unsigned long) (arg5) -#define __sc_loadargs_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ - __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5); \ - __sc_8 = (unsigned long) (arg6) - -#define __sc_asm_input_0 "0" (__sc_0) -#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3) -#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4) -#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5) -#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6) -#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7) -#define __sc_asm_input_6 __sc_asm_input_5, "6" (__sc_8) - -#define _syscall0(type,name) \ -type name(void) \ -{ \ - __syscall_nr(0, type, name); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ - __syscall_nr(1, type, name, arg1); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1, type2 arg2) \ -{ \ - __syscall_nr(2, type, name, arg1, arg2); \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1, type2 arg2, type3 arg3) \ -{ \ - __syscall_nr(3, type, name, arg1, arg2, arg3); \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ - __syscall_nr(4, type, name, arg1, arg2, arg3, arg4); \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ -{ \ - __syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5); \ -} -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ -{ \ - __syscall_nr(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \ -} - - #include #include #include diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h index 71d3c21b84f..fb6fef97d73 100644 --- a/include/asm-s390/unistd.h +++ b/include/asm-s390/unistd.h @@ -345,160 +345,6 @@ #ifdef __KERNEL__ -#include - -#define __syscall_return(type, res) \ -do { \ - if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \ - errno = -(res); \ - res = -1; \ - } \ - return (type) (res); \ -} while (0) - -#define _svc_clobber "1", "cc", "memory" - -#define _syscall0(type,name) \ -type name(void) { \ - register long __svcres asm("2"); \ - long __res; \ - asm volatile( \ - " .if %1 < 256\n" \ - " svc %b1\n" \ - " .else\n" \ - " la %%r1,%1\n" \ - " svc 0\n" \ - " .endif" \ - : "=d" (__svcres) \ - : "i" (__NR_##name) \ - : _svc_clobber); \ - __res = __svcres; \ - __syscall_return(type,__res); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) { \ - register type1 __arg1 asm("2") = arg1; \ - register long __svcres asm("2"); \ - long __res; \ - asm volatile( \ - " .if %1 < 256\n" \ - " svc %b1\n" \ - " .else\n" \ - " la %%r1,%1\n" \ - " svc 0\n" \ - " .endif" \ - : "=d" (__svcres) \ - : "i" (__NR_##name), \ - "0" (__arg1) \ - : _svc_clobber); \ - __res = __svcres; \ - __syscall_return(type,__res); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1, type2 arg2) { \ - register type1 __arg1 asm("2") = arg1; \ - register type2 __arg2 asm("3") = arg2; \ - register long __svcres asm("2"); \ - long __res; \ - asm volatile( \ - " .if %1 < 256\n" \ - " svc %b1\n" \ - " .else\n" \ - " la %%r1,%1\n" \ - " svc 0\n" \ - " .endif" \ - : "=d" (__svcres) \ - : "i" (__NR_##name), \ - "0" (__arg1), \ - "d" (__arg2) \ - : _svc_clobber ); \ - __res = __svcres; \ - __syscall_return(type,__res); \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1, type2 arg2, type3 arg3) { \ - register type1 __arg1 asm("2") = arg1; \ - register type2 __arg2 asm("3") = arg2; \ - register type3 __arg3 asm("4") = arg3; \ - register long __svcres asm("2"); \ - long __res; \ - asm volatile( \ - " .if %1 < 256\n" \ - " svc %b1\n" \ - " .else\n" \ - " la %%r1,%1\n" \ - " svc 0\n" \ - " .endif" \ - : "=d" (__svcres) \ - : "i" (__NR_##name), \ - "0" (__arg1), \ - "d" (__arg2), \ - "d" (__arg3) \ - : _svc_clobber); \ - __res = __svcres; \ - __syscall_return(type,__res); \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3, \ - type4,name4) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ - register type1 __arg1 asm("2") = arg1; \ - register type2 __arg2 asm("3") = arg2; \ - register type3 __arg3 asm("4") = arg3; \ - register type4 __arg4 asm("5") = arg4; \ - register long __svcres asm("2"); \ - long __res; \ - asm volatile( \ - " .if %1 < 256\n" \ - " svc %b1\n" \ - " .else\n" \ - " la %%r1,%1\n" \ - " svc 0\n" \ - " .endif" \ - : "=d" (__svcres) \ - : "i" (__NR_##name), \ - "0" (__arg1), \ - "d" (__arg2), \ - "d" (__arg3), \ - "d" (__arg4) \ - : _svc_clobber); \ - __res = __svcres; \ - __syscall_return(type,__res); \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3, \ - type4,name4,type5,name5) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ - type5 arg5) { \ - register type1 __arg1 asm("2") = arg1; \ - register type2 __arg2 asm("3") = arg2; \ - register type3 __arg3 asm("4") = arg3; \ - register type4 __arg4 asm("5") = arg4; \ - register type5 __arg5 asm("6") = arg5; \ - register long __svcres asm("2"); \ - long __res; \ - asm volatile( \ - " .if %1 < 256\n" \ - " svc %b1\n" \ - " .else\n" \ - " la %%r1,%1\n" \ - " svc 0\n" \ - " .endif" \ - : "=d" (__svcres) \ - : "i" (__NR_##name), \ - "0" (__arg1), \ - "d" (__arg2), \ - "d" (__arg3), \ - "d" (__arg4), \ - "d" (__arg5) \ - : _svc_clobber); \ - __res = __svcres; \ - __syscall_return(type,__res); \ -} - #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h index 0cae1d24876..f982073dc6c 100644 --- a/include/asm-sh/unistd.h +++ b/include/asm-sh/unistd.h @@ -332,143 +332,6 @@ #ifdef __KERNEL__ -#include - -/* user-visible error numbers are in the range -1 - -MAX_ERRNO: - * see */ - -#define __syscall_return(type, res) \ -do { \ - if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \ - /* Avoid using "res" which is declared to be in register r0; \ - errno might expand to a function call and clobber it. */ \ - int __err = -(res); \ - errno = __err; \ - res = -1; \ - } \ - return (type) (res); \ -} while (0) - -#if defined(__sh2__) || defined(__SH2E__) || defined(__SH2A__) -#define SYSCALL_ARG0 "trapa #0x20" -#define SYSCALL_ARG1 "trapa #0x21" -#define SYSCALL_ARG2 "trapa #0x22" -#define SYSCALL_ARG3 "trapa #0x23" -#define SYSCALL_ARG4 "trapa #0x24" -#define SYSCALL_ARG5 "trapa #0x25" -#define SYSCALL_ARG6 "trapa #0x26" -#else -#define SYSCALL_ARG0 "trapa #0x10" -#define SYSCALL_ARG1 "trapa #0x11" -#define SYSCALL_ARG2 "trapa #0x12" -#define SYSCALL_ARG3 "trapa #0x13" -#define SYSCALL_ARG4 "trapa #0x14" -#define SYSCALL_ARG5 "trapa #0x15" -#define SYSCALL_ARG6 "trapa #0x16" -#endif - -/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ -#define _syscall0(type,name) \ -type name(void) \ -{ \ -register long __sc0 __asm__ ("r3") = __NR_##name; \ -__asm__ __volatile__ (SYSCALL_ARG0 \ - : "=z" (__sc0) \ - : "0" (__sc0) \ - : "memory" ); \ -__syscall_return(type,__sc0); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ -register long __sc0 __asm__ ("r3") = __NR_##name; \ -register long __sc4 __asm__ ("r4") = (long) arg1; \ -__asm__ __volatile__ (SYSCALL_ARG1 \ - : "=z" (__sc0) \ - : "0" (__sc0), "r" (__sc4) \ - : "memory"); \ -__syscall_return(type,__sc0); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ -register long __sc0 __asm__ ("r3") = __NR_##name; \ -register long __sc4 __asm__ ("r4") = (long) arg1; \ -register long __sc5 __asm__ ("r5") = (long) arg2; \ -__asm__ __volatile__ (SYSCALL_ARG2 \ - : "=z" (__sc0) \ - : "0" (__sc0), "r" (__sc4), "r" (__sc5) \ - : "memory"); \ -__syscall_return(type,__sc0); \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ -register long __sc0 __asm__ ("r3") = __NR_##name; \ -register long __sc4 __asm__ ("r4") = (long) arg1; \ -register long __sc5 __asm__ ("r5") = (long) arg2; \ -register long __sc6 __asm__ ("r6") = (long) arg3; \ -__asm__ __volatile__ (SYSCALL_ARG3 \ - : "=z" (__sc0) \ - : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) \ - : "memory"); \ -__syscall_return(type,__sc0); \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ -register long __sc0 __asm__ ("r3") = __NR_##name; \ -register long __sc4 __asm__ ("r4") = (long) arg1; \ -register long __sc5 __asm__ ("r5") = (long) arg2; \ -register long __sc6 __asm__ ("r6") = (long) arg3; \ -register long __sc7 __asm__ ("r7") = (long) arg4; \ -__asm__ __volatile__ (SYSCALL_ARG4 \ - : "=z" (__sc0) \ - : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), \ - "r" (__sc7) \ - : "memory" ); \ -__syscall_return(type,__sc0); \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ -{ \ -register long __sc3 __asm__ ("r3") = __NR_##name; \ -register long __sc4 __asm__ ("r4") = (long) arg1; \ -register long __sc5 __asm__ ("r5") = (long) arg2; \ -register long __sc6 __asm__ ("r6") = (long) arg3; \ -register long __sc7 __asm__ ("r7") = (long) arg4; \ -register long __sc0 __asm__ ("r0") = (long) arg5; \ -__asm__ __volatile__ (SYSCALL_ARG5 \ - : "=z" (__sc0) \ - : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7), \ - "r" (__sc3) \ - : "memory" ); \ -__syscall_return(type,__sc0); \ -} - -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ -{ \ -register long __sc3 __asm__ ("r3") = __NR_##name; \ -register long __sc4 __asm__ ("r4") = (long) arg1; \ -register long __sc5 __asm__ ("r5") = (long) arg2; \ -register long __sc6 __asm__ ("r6") = (long) arg3; \ -register long __sc7 __asm__ ("r7") = (long) arg4; \ -register long __sc0 __asm__ ("r0") = (long) arg5; \ -register long __sc1 __asm__ ("r1") = (long) arg6; \ -__asm__ __volatile__ (SYSCALL_ARG6 \ - : "=z" (__sc0) \ - : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7), \ - "r" (__sc3), "r" (__sc1) \ - : "memory" ); \ -__syscall_return(type,__sc0); \ -} - #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT diff --git a/include/asm-sh64/unistd.h b/include/asm-sh64/unistd.h index ee7828b27ad..1f38a7aacaa 100644 --- a/include/asm-sh64/unistd.h +++ b/include/asm-sh64/unistd.h @@ -347,148 +347,6 @@ #ifdef __KERNEL__ #define NR_syscalls 321 -#include - -/* user-visible error numbers are in the range -1 - -MAX_ERRNO: - * see */ - -#define __syscall_return(type, res) \ -do { \ - /* Note: when returning from kernel the return value is in r9 \ - ** This prevents conflicts between return value and arg1 \ - ** when dispatching signal handler, in other words makes \ - ** life easier in the system call epilogue (see entry.S) \ - */ \ - register unsigned long __sr2 __asm__ ("r2") = res; \ - if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \ - errno = -(res); \ - __sr2 = -1; \ - } \ - return (type) (__sr2); \ -} while (0) - -/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ - -#define _syscall0(type,name) \ -type name(void) \ -{ \ -register unsigned long __sc0 __asm__ ("r9") = ((0x10 << 16) | __NR_##name); \ -__asm__ __volatile__ ("trapa %1 !\t\t\t" #name "()" \ - : "=r" (__sc0) \ - : "r" (__sc0) ); \ -__syscall_return(type,__sc0); \ -} - - /* - * The apparent spurious "dummy" assembler comment is *needed*, - * as without it, the compiler treats the arg variables - * as no longer live just before the asm. The compiler can - * then optimize the storage into any registers it wishes. - * The additional dummy statement forces the compiler to put - * the arguments into the correct registers before the TRAPA. - */ -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ -register unsigned long __sc0 __asm__ ("r9") = ((0x11 << 16) | __NR_##name); \ -register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ -__asm__ __volatile__ ("trapa %1 !\t\t\t" #name "(%2)" \ - : "=r" (__sc0) \ - : "r" (__sc0), "r" (__sc2)); \ -__asm__ __volatile__ ("!dummy %0 %1" \ - : \ - : "r" (__sc0), "r" (__sc2)); \ -__syscall_return(type,__sc0); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ -register unsigned long __sc0 __asm__ ("r9") = ((0x12 << 16) | __NR_##name); \ -register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ -register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ -__asm__ __volatile__ ("trapa %1 !\t\t\t" #name "(%2,%3)" \ - : "=r" (__sc0) \ - : "r" (__sc0), "r" (__sc2), "r" (__sc3) ); \ -__asm__ __volatile__ ("!dummy %0 %1 %2" \ - : \ - : "r" (__sc0), "r" (__sc2), "r" (__sc3) ); \ -__syscall_return(type,__sc0); \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ -register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_##name); \ -register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ -register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ -register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ -__asm__ __volatile__ ("trapa %1 !\t\t\t" #name "(%2,%3,%4)" \ - : "=r" (__sc0) \ - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) ); \ -__asm__ __volatile__ ("!dummy %0 %1 %2 %3" \ - : \ - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) ); \ -__syscall_return(type,__sc0); \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ -register unsigned long __sc0 __asm__ ("r9") = ((0x14 << 16) | __NR_##name); \ -register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ -register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ -register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ -register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4; \ -__asm__ __volatile__ ("trapa %1 !\t\t\t" #name "(%2,%3,%4,%5)" \ - : "=r" (__sc0) \ - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5) );\ -__asm__ __volatile__ ("!dummy %0 %1 %2 %3 %4" \ - : \ - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5) );\ -__syscall_return(type,__sc0); \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ -{ \ -register unsigned long __sc0 __asm__ ("r9") = ((0x15 << 16) | __NR_##name); \ -register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ -register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ -register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ -register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4; \ -register unsigned long __sc6 __asm__ ("r6") = (unsigned long) arg5; \ -__asm__ __volatile__ ("trapa %1 !\t\t\t" #name "(%2,%3,%4,%5,%6)" \ - : "=r" (__sc0) \ - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \ - "r" (__sc6)); \ -__asm__ __volatile__ ("!dummy %0 %1 %2 %3 %4 %5" \ - : \ - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \ - "r" (__sc6)); \ -__syscall_return(type,__sc0); \ -} - -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5, type6, arg6) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ -{ \ -register unsigned long __sc0 __asm__ ("r9") = ((0x16 << 16) | __NR_##name); \ -register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ -register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ -register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ -register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4; \ -register unsigned long __sc6 __asm__ ("r6") = (unsigned long) arg5; \ -register unsigned long __sc7 __asm__ ("r7") = (unsigned long) arg6; \ -__asm__ __volatile__ ("trapa %1 !\t\t\t" #name "(%2,%3,%4,%5,%6,%7)" \ - : "=r" (__sc0) \ - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \ - "r" (__sc6), "r" (__sc7)); \ -__asm__ __volatile__ ("!dummy %0 %1 %2 %3 %4 %5 %6" \ - : \ - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \ - "r" (__sc6), "r" (__sc7)); \ -__syscall_return(type,__sc0); \ -} #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h index f7827fa4cd5..d5b2f8053b3 100644 --- a/include/asm-sparc/unistd.h +++ b/include/asm-sparc/unistd.h @@ -329,136 +329,6 @@ * find a free slot in the 0-302 range. */ -#define _syscall0(type,name) \ -type name(void) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -__asm__ __volatile__ ("t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res)\ - : "r" (__g1) \ - : "o0", "cc"); \ -if (__res < -255 || __res >= 0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -register long __o0 __asm__ ("o0") = (long)(arg1); \ -__asm__ __volatile__ ("t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__g1) \ - : "cc"); \ -if (__res < -255 || __res >= 0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -register long __o0 __asm__ ("o0") = (long)(arg1); \ -register long __o1 __asm__ ("o1") = (long)(arg2); \ -__asm__ __volatile__ ("t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__g1) \ - : "cc"); \ -if (__res < -255 || __res >= 0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -register long __o0 __asm__ ("o0") = (long)(arg1); \ -register long __o1 __asm__ ("o1") = (long)(arg2); \ -register long __o2 __asm__ ("o2") = (long)(arg3); \ -__asm__ __volatile__ ("t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \ - : "cc"); \ -if (__res < -255 || __res>=0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -register long __o0 __asm__ ("o0") = (long)(arg1); \ -register long __o1 __asm__ ("o1") = (long)(arg2); \ -register long __o2 __asm__ ("o2") = (long)(arg3); \ -register long __o3 __asm__ ("o3") = (long)(arg4); \ -__asm__ __volatile__ ("t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \ - : "cc"); \ -if (__res < -255 || __res>=0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -register long __o0 __asm__ ("o0") = (long)(arg1); \ -register long __o1 __asm__ ("o1") = (long)(arg2); \ -register long __o2 __asm__ ("o2") = (long)(arg3); \ -register long __o3 __asm__ ("o3") = (long)(arg4); \ -register long __o4 __asm__ ("o4") = (long)(arg5); \ -__asm__ __volatile__ ("t 0x10\n\t" \ - "bcc 1f\n\t" \ - "mov %%o0, %0\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "1:\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \ - : "cc"); \ -if (__res < -255 || __res>=0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h index 63669dad0d7..47047536f26 100644 --- a/include/asm-sparc64/unistd.h +++ b/include/asm-sparc64/unistd.h @@ -332,124 +332,6 @@ * find a free slot in the 0-302 range. */ -#define _syscall0(type,name) \ -type name(void) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -__asm__ __volatile__ ("t 0x6d\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "movcc %%xcc, %%o0, %0\n\t" \ - : "=r" (__res)\ - : "r" (__g1) \ - : "o0", "cc"); \ -if (__res >= 0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -register long __o0 __asm__ ("o0") = (long)(arg1); \ -__asm__ __volatile__ ("t 0x6d\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "movcc %%xcc, %%o0, %0\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__g1) \ - : "cc"); \ -if (__res >= 0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -register long __o0 __asm__ ("o0") = (long)(arg1); \ -register long __o1 __asm__ ("o1") = (long)(arg2); \ -__asm__ __volatile__ ("t 0x6d\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "movcc %%xcc, %%o0, %0\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__g1) \ - : "cc"); \ -if (__res >= 0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -register long __o0 __asm__ ("o0") = (long)(arg1); \ -register long __o1 __asm__ ("o1") = (long)(arg2); \ -register long __o2 __asm__ ("o2") = (long)(arg3); \ -__asm__ __volatile__ ("t 0x6d\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "movcc %%xcc, %%o0, %0\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \ - : "cc"); \ -if (__res>=0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -register long __o0 __asm__ ("o0") = (long)(arg1); \ -register long __o1 __asm__ ("o1") = (long)(arg2); \ -register long __o2 __asm__ ("o2") = (long)(arg3); \ -register long __o3 __asm__ ("o3") = (long)(arg4); \ -__asm__ __volatile__ ("t 0x6d\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "movcc %%xcc, %%o0, %0\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \ - : "cc"); \ -if (__res>=0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ -long __res; \ -register long __g1 __asm__ ("g1") = __NR_##name; \ -register long __o0 __asm__ ("o0") = (long)(arg1); \ -register long __o1 __asm__ ("o1") = (long)(arg2); \ -register long __o2 __asm__ ("o2") = (long)(arg3); \ -register long __o3 __asm__ ("o3") = (long)(arg4); \ -register long __o4 __asm__ ("o4") = (long)(arg5); \ -__asm__ __volatile__ ("t 0x6d\n\t" \ - "sub %%g0, %%o0, %0\n\t" \ - "movcc %%xcc, %%o0, %0\n\t" \ - : "=r" (__res), "=&r" (__o0) \ - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \ - : "cc"); \ -if (__res>=0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - /* sysconf options, for SunOS compatibility */ #define _SC_ARG_MAX 1 #define _SC_CHILD_MAX 2 diff --git a/include/asm-v850/unistd.h b/include/asm-v850/unistd.h index 737401e7d3a..2241ed45ecf 100644 --- a/include/asm-v850/unistd.h +++ b/include/asm-v850/unistd.h @@ -204,168 +204,8 @@ #define __NR_gettid 201 #define __NR_tkill 202 - -/* Syscall protocol: - Syscall number in r12, args in r6-r9, r13-r14 - Return value in r10 - Trap 0 for `short' syscalls, where all the args can fit in function - call argument registers, and trap 1 when there are additional args in - r13-r14. */ - -#define SYSCALL_NUM "r12" -#define SYSCALL_ARG0 "r6" -#define SYSCALL_ARG1 "r7" -#define SYSCALL_ARG2 "r8" -#define SYSCALL_ARG3 "r9" -#define SYSCALL_ARG4 "r13" -#define SYSCALL_ARG5 "r14" -#define SYSCALL_RET "r10" - -#define SYSCALL_SHORT_TRAP "0" -#define SYSCALL_LONG_TRAP "1" - -/* Registers clobbered by any syscall. This _doesn't_ include the syscall - number (r12) or the `extended arg' registers (r13, r14), even though - they are actually clobbered too (this is because gcc's `asm' statement - doesn't allow a clobber to be used as an input or output). */ -#define SYSCALL_CLOBBERS "r1", "r5", "r11", "r15", "r16", \ - "r17", "r18", "r19" - -/* Registers clobbered by a `short' syscall. This includes all clobbers - except the syscall number (r12). */ -#define SYSCALL_SHORT_CLOBBERS SYSCALL_CLOBBERS, "r13", "r14" - #ifdef __KERNEL__ -#include -#include - -#define __syscall_return(type, res) \ - do { \ - /* user-visible error numbers are in the range -1 - -MAX_ERRNO: \ - see */ \ - if (__builtin_expect ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO), 0)) { \ - errno = -(res); \ - res = -1; \ - } \ - return (type) (res); \ - } while (0) - - -#define _syscall0(type, name) \ -type name (void) \ -{ \ - register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \ - register unsigned long __ret __asm__ (SYSCALL_RET); \ - __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP \ - : "=r" (__ret), "=r" (__syscall) \ - : "1" (__syscall) \ - : SYSCALL_SHORT_CLOBBERS); \ - __syscall_return (type, __ret); \ -} - -#define _syscall1(type, name, atype, a) \ -type name (atype a) \ -{ \ - register atype __a __asm__ (SYSCALL_ARG0) = a; \ - register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \ - register unsigned long __ret __asm__ (SYSCALL_RET); \ - __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP \ - : "=r" (__ret), "=r" (__syscall) \ - : "1" (__syscall), "r" (__a) \ - : SYSCALL_SHORT_CLOBBERS); \ - __syscall_return (type, __ret); \ -} - -#define _syscall2(type, name, atype, a, btype, b) \ -type name (atype a, btype b) \ -{ \ - register atype __a __asm__ (SYSCALL_ARG0) = a; \ - register btype __b __asm__ (SYSCALL_ARG1) = b; \ - register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \ - register unsigned long __ret __asm__ (SYSCALL_RET); \ - __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP \ - : "=r" (__ret), "=r" (__syscall) \ - : "1" (__syscall), "r" (__a), "r" (__b) \ - : SYSCALL_SHORT_CLOBBERS); \ - __syscall_return (type, __ret); \ -} - -#define _syscall3(type, name, atype, a, btype, b, ctype, c) \ -type name (atype a, btype b, ctype c) \ -{ \ - register atype __a __asm__ (SYSCALL_ARG0) = a; \ - register btype __b __asm__ (SYSCALL_ARG1) = b; \ - register ctype __c __asm__ (SYSCALL_ARG2) = c; \ - register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \ - register unsigned long __ret __asm__ (SYSCALL_RET); \ - __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP \ - : "=r" (__ret), "=r" (__syscall) \ - : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c) \ - : SYSCALL_SHORT_CLOBBERS); \ - __syscall_return (type, __ret); \ -} - -#define _syscall4(type, name, atype, a, btype, b, ctype, c, dtype, d) \ -type name (atype a, btype b, ctype c, dtype d) \ -{ \ - register atype __a __asm__ (SYSCALL_ARG0) = a; \ - register btype __b __asm__ (SYSCALL_ARG1) = b; \ - register ctype __c __asm__ (SYSCALL_ARG2) = c; \ - register dtype __d __asm__ (SYSCALL_ARG3) = d; \ - register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \ - register unsigned long __ret __asm__ (SYSCALL_RET); \ - __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP \ - : "=r" (__ret), "=r" (__syscall) \ - : "1" (__syscall), \ - "r" (__a), "r" (__b), "r" (__c), "r" (__d) \ - : SYSCALL_SHORT_CLOBBERS); \ - __syscall_return (type, __ret); \ -} - -#define _syscall5(type, name, atype, a, btype, b, ctype, c, dtype, d, etype,e)\ -type name (atype a, btype b, ctype c, dtype d, etype e) \ -{ \ - register atype __a __asm__ (SYSCALL_ARG0) = a; \ - register btype __b __asm__ (SYSCALL_ARG1) = b; \ - register ctype __c __asm__ (SYSCALL_ARG2) = c; \ - register dtype __d __asm__ (SYSCALL_ARG3) = d; \ - register etype __e __asm__ (SYSCALL_ARG4) = e; \ - register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \ - register unsigned long __ret __asm__ (SYSCALL_RET); \ - __asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP \ - : "=r" (__ret), "=r" (__syscall), "=r" (__e) \ - : "1" (__syscall), \ - "r" (__a), "r" (__b), "r" (__c), "r" (__d), "2" (__e) \ - : SYSCALL_CLOBBERS); \ - __syscall_return (type, __ret); \ -} - -#define __SYSCALL6_TRAP(syscall, ret, a, b, c, d, e, f) \ - __asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP \ - : "=r" (ret), "=r" (syscall), \ - "=r" (e), "=r" (f) \ - : "1" (syscall), \ - "r" (a), "r" (b), "r" (c), "r" (d), \ - "2" (e), "3" (f) \ - : SYSCALL_CLOBBERS); - -#define _syscall6(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \ -type name (atype a, btype b, ctype c, dtype d, etype e, ftype f) \ -{ \ - register atype __a __asm__ (SYSCALL_ARG0) = a; \ - register btype __b __asm__ (SYSCALL_ARG1) = b; \ - register ctype __c __asm__ (SYSCALL_ARG2) = c; \ - register dtype __d __asm__ (SYSCALL_ARG3) = d; \ - register etype __e __asm__ (SYSCALL_ARG4) = e; \ - register etype __f __asm__ (SYSCALL_ARG5) = f; \ - register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name; \ - register unsigned long __ret __asm__ (SYSCALL_RET); \ - __SYSCALL6_TRAP(__syscall, __ret, __a, __b, __c, __d, __e, __f); \ - __syscall_return (type, __ret); \ -} - - #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index 777288eb7e7..c5f596e71fa 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -622,25 +622,7 @@ __SYSCALL(__NR_move_pages, sys_move_pages) #define __NR_syscall_max __NR_move_pages -#ifdef __KERNEL__ -#include -#endif - #ifndef __NO_STUBS - -/* user-visible error numbers are in the range -1 - -MAX_ERRNO */ - -#define __syscall_clobber "r11","rcx","memory" - -#define __syscall_return(type, res) \ -do { \ - if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \ - errno = -(res); \ - res = -1; \ - } \ - return (type) (res); \ -} while (0) - #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT #define __ARCH_WANT_SYS_ALARM @@ -664,87 +646,6 @@ do { \ #define __ARCH_WANT_SYS_TIME #define __ARCH_WANT_COMPAT_SYS_TIME -#define __syscall "syscall" - -#define _syscall0(type,name) \ -type name(void) \ -{ \ -long __res; \ -__asm__ volatile (__syscall \ - : "=a" (__res) \ - : "0" (__NR_##name) : __syscall_clobber ); \ -__syscall_return(type,__res); \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ -long __res; \ -__asm__ volatile (__syscall \ - : "=a" (__res) \ - : "0" (__NR_##name),"D" ((long)(arg1)) : __syscall_clobber ); \ -__syscall_return(type,__res); \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ -long __res; \ -__asm__ volatile (__syscall \ - : "=a" (__res) \ - : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)) : __syscall_clobber ); \ -__syscall_return(type,__res); \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ -long __res; \ -__asm__ volatile (__syscall \ - : "=a" (__res) \ - : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)), \ - "d" ((long)(arg3)) : __syscall_clobber); \ -__syscall_return(type,__res); \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ -long __res; \ -__asm__ volatile ("movq %5,%%r10 ;" __syscall \ - : "=a" (__res) \ - : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)), \ - "d" ((long)(arg3)),"g" ((long)(arg4)) : __syscall_clobber,"r10" ); \ -__syscall_return(type,__res); \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ -long __res; \ -__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall \ - : "=a" (__res) \ - : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)), \ - "d" ((long)(arg3)),"g" ((long)(arg4)),"g" ((long)(arg5)) : \ - __syscall_clobber,"r8","r10" ); \ -__syscall_return(type,__res); \ -} - -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5,type6,arg6) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ -{ \ -long __res; \ -__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; movq %7,%%r9 ; " __syscall \ - : "=a" (__res) \ - : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)), \ - "d" ((long)(arg3)), "g" ((long)(arg4)), "g" ((long)(arg5)), \ - "g" ((long)(arg6)) : \ - __syscall_clobber,"r8","r10","r9" ); \ -__syscall_return(type,__res); \ -} - #ifdef __KERNEL__ #ifndef __ASSEMBLY__ diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h index 411f810a55c..2e1a1b997e7 100644 --- a/include/asm-xtensa/unistd.h +++ b/include/asm-xtensa/unistd.h @@ -218,190 +218,6 @@ #define SYSXTENSA_COUNT 5 /* count of syscall0 functions*/ -#ifdef __KERNEL__ -#include - -#define __syscall_return(type, res) return ((type)(res)) - -/* Tensilica's xt-xcc compiler is much more agressive at code - * optimization than gcc. Multiple __asm__ statements are - * insufficient for xt-xcc because subsequent optimization passes - * (beyond the front-end that knows of __asm__ statements and other - * such GNU Extensions to C) can modify the register selection for - * containment of C variables. - * - * xt-xcc cannot modify the contents of a single __asm__ statement, so - * we create single-asm versions of the syscall macros that are - * suitable and optimal for both xt-xcc and gcc. - * - * Linux takes system-call arguments in registers. The following - * design is optimized for user-land apps (e.g., glibc) which - * typically have a function wrapper around the "syscall" assembly - * instruction. It satisfies the Xtensa ABI while minizing argument - * shifting. - * - * The Xtensa ABI and software conventions require the system-call - * number in a2. If an argument exists in a2, we move it to the next - * available register. Note that for improved efficiency, we do NOT - * shift all parameters down one register to maintain the original - * order. - * - * At best case (zero arguments), we just write the syscall number to - * a2. At worst case (1 to 6 arguments), we move the argument in a2 - * to the next available register, then write the syscall number to - * a2. - * - * For clarity, the following truth table enumerates all possibilities. - * - * arguments syscall number arg0, arg1, arg2, arg3, arg4, arg5 - * --------- -------------- ---------------------------------- - * 0 a2 - * 1 a2 a3 - * 2 a2 a4, a3 - * 3 a2 a5, a3, a4 - * 4 a2 a6, a3, a4, a5 - * 5 a2 a7, a3, a4, a5, a6 - * 6 a2 a8, a3, a4, a5, a6, a7 - */ - -#define _syscall0(type,name) \ -type name(void) \ -{ \ -long __res; \ -__asm__ __volatile__ ( \ - " movi a2, %1 \n" \ - " syscall \n" \ - " mov %0, a2 \n" \ - : "=a" (__res) \ - : "i" (__NR_##name) \ - : "a2" \ - ); \ -__syscall_return(type,__res); \ -} - -#define _syscall1(type,name,type0,arg0) \ -type name(type0 arg0) \ -{ \ -long __res; \ -__asm__ __volatile__ ( \ - " mov a3, %2 \n" \ - " movi a2, %1 \n" \ - " syscall \n" \ - " mov %0, a2 \n" \ - : "=a" (__res) \ - : "i" (__NR_##name), "a" (arg0) \ - : "a2", "a3" \ - ); \ -__syscall_return(type,__res); \ -} - -#define _syscall2(type,name,type0,arg0,type1,arg1) \ -type name(type0 arg0,type1 arg1) \ -{ \ -long __res; \ -__asm__ __volatile__ ( \ - " mov a4, %2 \n" \ - " mov a3, %3 \n" \ - " movi a2, %1 \n" \ - " syscall \n" \ - " mov %0, a2 \n" \ - : "=a" (__res) \ - : "i" (__NR_##name), "a" (arg0), "a" (arg1) \ - : "a2", "a3", "a4" \ - ); \ -__syscall_return(type,__res); \ -} - -#define _syscall3(type,name,type0,arg0,type1,arg1,type2,arg2) \ -type name(type0 arg0,type1 arg1,type2 arg2) \ -{ \ -long __res; \ -__asm__ __volatile__ ( \ - " mov a5, %2 \n" \ - " mov a4, %4 \n" \ - " mov a3, %3 \n" \ - " movi a2, %1 \n" \ - " syscall \n" \ - " mov %0, a2 \n" \ - : "=a" (__res) \ - : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2) \ - : "a2", "a3", "a4", "a5" \ - ); \ -__syscall_return(type,__res); \ -} - -#define _syscall4(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3) \ -type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3) \ -{ \ -long __res; \ -__asm__ __volatile__ ( \ - " mov a6, %2 \n" \ - " mov a5, %5 \n" \ - " mov a4, %4 \n" \ - " mov a3, %3 \n" \ - " movi a2, %1 \n" \ - " syscall \n" \ - " mov %0, a2 \n" \ - : "=a" (__res) \ - : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), "a" (arg3) \ - : "a2", "a3", "a4", "a5", "a6" \ - ); \ -__syscall_return(type,__res); \ -} - -/* Note that we save and restore the a7 frame pointer. - * Including a7 in the clobber list doesn't do what you'd expect. - */ -#define _syscall5(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3,type4 arg4) \ -{ \ -long __res; \ -__asm__ __volatile__ ( \ - " mov a9, a7 \n" \ - " mov a7, %2 \n" \ - " mov a6, %6 \n" \ - " mov a5, %5 \n" \ - " mov a4, %4 \n" \ - " mov a3, %3 \n" \ - " movi a2, %1 \n" \ - " syscall \n" \ - " mov a7, a9 \n" \ - " mov %0, a2 \n" \ - : "=a" (__res) \ - : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), \ - "a" (arg3), "a" (arg4) \ - : "a2", "a3", "a4", "a5", "a6", "a9" \ - ); \ -__syscall_return(type,__res); \ -} - -/* Note that we save and restore the a7 frame pointer. - * Including a7 in the clobber list doesn't do what you'd expect. - */ -#define _syscall6(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ -type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ -long __res; \ -__asm__ __volatile__ ( \ - " mov a9, a7 \n" \ - " mov a8, %2 \n" \ - " mov a7, %7 \n" \ - " mov a6, %6 \n" \ - " mov a5, %5 \n" \ - " mov a4, %4 \n" \ - " mov a3, %3 \n" \ - " movi a2, %1 \n" \ - " syscall \n" \ - " mov a7, a9 \n" \ - " mov %0, a2 \n" \ - : "=a" (__res) \ - : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), \ - "a" (arg3), "a" (arg4), "a" (arg5) \ - : "a2", "a3", "a4", "a5", "a6", "a8", "a9" \ - ); \ -__syscall_return(type,__res); \ -} - /* * "Conditional" syscalls * -- cgit v1.2.3-70-g09d2 From 386d9a7edd9f3492c99124b0a659e9ed7abb30f9 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 6 Dec 2006 20:37:53 -0800 Subject: [PATCH] elf: Always define elf_addr_t in linux/elf.h Define elf_addr_t in linux/elf.h. The size of the type is determined using ELF_CLASS. This allows us to remove the defines that today are spread all over .c and .h files. Signed-off-by: Magnus Damm Cc: Daniel Jacobowitz Cc: Roland McGrath Cc: Jakub Jelinek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/ia32/ia32priv.h | 2 -- arch/mips/kernel/binfmt_elfn32.c | 1 - arch/mips/kernel/binfmt_elfo32.c | 1 - arch/mips/kernel/irixelf.c | 4 ---- arch/parisc/kernel/binfmt_elf32.c | 1 - arch/s390/kernel/binfmt_elf32.c | 1 - arch/sparc64/kernel/binfmt_elf32.c | 1 - arch/x86_64/ia32/ia32_binfmt.c | 2 -- fs/binfmt_elf.c | 4 ---- fs/binfmt_elf_fdpic.c | 3 --- include/asm-powerpc/elf.h | 2 -- include/linux/elf.h | 2 ++ 12 files changed, 2 insertions(+), 22 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h index 703a67c934f..cfa0bc0026b 100644 --- a/arch/ia64/ia32/ia32priv.h +++ b/arch/ia64/ia32/ia32priv.h @@ -330,8 +330,6 @@ struct old_linux32_dirent { void ia64_elf32_init(struct pt_regs *regs); #define ELF_PLAT_INIT(_r, load_addr) ia64_elf32_init(_r) -#define elf_addr_t u32 - /* This macro yields a bitmask that programs can use to figure out what instruction set this CPU supports. */ #define ELF_HWCAP 0 diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c index 4a9f1ecefaf..9b34238d41c 100644 --- a/arch/mips/kernel/binfmt_elfn32.c +++ b/arch/mips/kernel/binfmt_elfn32.c @@ -90,7 +90,6 @@ struct elf_prpsinfo32 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ }; -#define elf_addr_t u32 #define elf_caddr_t u32 #define init_elf_binfmt init_elfn32_binfmt diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index e3181377989..993f7ec70f3 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -92,7 +92,6 @@ struct elf_prpsinfo32 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ }; -#define elf_addr_t u32 #define elf_caddr_t u32 #define init_elf_binfmt init_elf32_binfmt diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index ab12c8f0151..a82fae221ce 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -52,10 +52,6 @@ static struct linux_binfmt irix_format = { irix_core_dump, PAGE_SIZE }; -#ifndef elf_addr_t -#define elf_addr_t unsigned long -#endif - #ifdef DEBUG /* Debugging routines. */ static char *get_elf_p_type(Elf32_Word p_type) diff --git a/arch/parisc/kernel/binfmt_elf32.c b/arch/parisc/kernel/binfmt_elf32.c index 1e64e7b8811..ecb10a4f63c 100644 --- a/arch/parisc/kernel/binfmt_elf32.c +++ b/arch/parisc/kernel/binfmt_elf32.c @@ -75,7 +75,6 @@ struct elf_prpsinfo32 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ }; -#define elf_addr_t unsigned int #define init_elf_binfmt init_elf32_binfmt #define ELF_PLATFORM ("PARISC32\0") diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c index 9565a2dcfad..5c46054195c 100644 --- a/arch/s390/kernel/binfmt_elf32.c +++ b/arch/s390/kernel/binfmt_elf32.c @@ -176,7 +176,6 @@ struct elf_prpsinfo32 #include -#define elf_addr_t u32 /* #define init_elf_binfmt init_elf32_binfmt */ diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c index a98f3ae175a..9ad84ff10a1 100644 --- a/arch/sparc64/kernel/binfmt_elf32.c +++ b/arch/sparc64/kernel/binfmt_elf32.c @@ -141,7 +141,6 @@ cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) value->tv_sec = jiffies / HZ; } -#define elf_addr_t u32 #undef start_thread #define start_thread start_thread32 #define init_elf_binfmt init_elf32_binfmt diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 932a62ad6c8..543ef4f405e 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -305,8 +305,6 @@ MODULE_AUTHOR("Eric Youngdale, Andi Kleen"); #undef MODULE_DESCRIPTION #undef MODULE_AUTHOR -#define elf_addr_t __u32 - static void elf32_init(struct pt_regs *); #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 68e20d5bfe1..14ea630a857 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -47,10 +47,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); static int load_elf_library(struct file *); static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); -#ifndef elf_addr_t -#define elf_addr_t unsigned long -#endif - /* * If we don't support core dumping, then supply a NULL so we * don't even try. diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index f86d5c9ce5e..ed9a61c6beb 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -40,9 +40,6 @@ #include typedef char *elf_caddr_t; -#ifndef elf_addr_t -#define elf_addr_t unsigned long -#endif #if 0 #define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ ) diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index b5436642a10..d36426c01b6 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -124,12 +124,10 @@ typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG]; # define ELF_DATA ELFDATA2MSB typedef elf_greg_t64 elf_greg_t; typedef elf_gregset_t64 elf_gregset_t; -# define elf_addr_t unsigned long #else /* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */ typedef elf_greg_t32 elf_greg_t; typedef elf_gregset_t32 elf_gregset_t; -# define elf_addr_t __u32 #endif /* ELF_ARCH */ /* Floating point registers */ diff --git a/include/linux/elf.h b/include/linux/elf.h index 743d5c8e6d3..b403516d5c3 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -358,6 +358,7 @@ extern Elf32_Dyn _DYNAMIC []; #define elfhdr elf32_hdr #define elf_phdr elf32_phdr #define elf_note elf32_note +#define elf_addr_t Elf32_Off #else @@ -365,6 +366,7 @@ extern Elf64_Dyn _DYNAMIC []; #define elfhdr elf64_hdr #define elf_phdr elf64_phdr #define elf_note elf64_note +#define elf_addr_t Elf64_Off #endif -- cgit v1.2.3-70-g09d2 From f67637ee4b5d90d41160d755b9a8cca18c394586 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 6 Dec 2006 20:38:54 -0800 Subject: [PATCH] Add struct dev pointer to dma_is_consistent() dma_is_consistent() is ill-designed in that it does not have a struct device pointer argument which makes proper support for systems that consist of a mix of coherent and non-coherent DMA devices hard. Change dma_is_consistent to take a struct device pointer as first argument and fix the sole caller to pass it. Signed-off-by: Ralf Baechle Cc: James Bottomley Cc: "David S. Miller" Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DMA-API.txt | 6 +++--- arch/mips/mm/dma-coherent.c | 2 +- arch/mips/mm/dma-ip27.c | 2 +- arch/mips/mm/dma-ip32.c | 2 +- arch/mips/mm/dma-noncoherent.c | 2 +- drivers/scsi/53c700.c | 2 +- include/asm-alpha/dma-mapping.h | 2 +- include/asm-arm/dma-mapping.h | 2 +- include/asm-avr32/dma-mapping.h | 2 +- include/asm-cris/dma-mapping.h | 2 +- include/asm-frv/dma-mapping.h | 2 +- include/asm-generic/dma-mapping.h | 2 +- include/asm-i386/dma-mapping.h | 2 +- include/asm-ia64/dma-mapping.h | 2 +- include/asm-m68k/dma-mapping.h | 2 +- include/asm-mips/dma-mapping.h | 2 +- include/asm-parisc/dma-mapping.h | 2 +- include/asm-powerpc/dma-mapping.h | 4 ++-- include/asm-sparc64/dma-mapping.h | 2 +- include/asm-um/dma-mapping.h | 2 +- include/asm-x86_64/dma-mapping.h | 2 +- include/asm-xtensa/dma-mapping.h | 2 +- 22 files changed, 25 insertions(+), 25 deletions(-) (limited to 'include/asm-powerpc') diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index 8621a064f7e..3dc1f9125ca 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -431,10 +431,10 @@ be identical to those passed in (and returned by dma_alloc_noncoherent()). int -dma_is_consistent(dma_addr_t dma_handle) +dma_is_consistent(struct device *dev, dma_addr_t dma_handle) -returns true if the memory pointed to by the dma_handle is actually -consistent. +returns true if the device dev is performing consistent DMA on the memory +area pointed to by the dma_handle. int dma_get_cache_alignment(void) diff --git a/arch/mips/mm/dma-coherent.c b/arch/mips/mm/dma-coherent.c index 7fa5fd16e46..18bc83e577c 100644 --- a/arch/mips/mm/dma-coherent.c +++ b/arch/mips/mm/dma-coherent.c @@ -190,7 +190,7 @@ int dma_supported(struct device *dev, u64 mask) EXPORT_SYMBOL(dma_supported); -int dma_is_consistent(dma_addr_t dma_addr) +int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return 1; } diff --git a/arch/mips/mm/dma-ip27.c b/arch/mips/mm/dma-ip27.c index 8da19fd22ac..8e9a5a8f5d6 100644 --- a/arch/mips/mm/dma-ip27.c +++ b/arch/mips/mm/dma-ip27.c @@ -197,7 +197,7 @@ int dma_supported(struct device *dev, u64 mask) EXPORT_SYMBOL(dma_supported); -int dma_is_consistent(dma_addr_t dma_addr) +int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return 1; } diff --git a/arch/mips/mm/dma-ip32.c b/arch/mips/mm/dma-ip32.c index ec54ed0d26f..08720a42100 100644 --- a/arch/mips/mm/dma-ip32.c +++ b/arch/mips/mm/dma-ip32.c @@ -363,7 +363,7 @@ int dma_supported(struct device *dev, u64 mask) EXPORT_SYMBOL(dma_supported); -int dma_is_consistent(dma_addr_t dma_addr) +int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return 1; } diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c index 2eeffe5c2a3..4a3efc63337 100644 --- a/arch/mips/mm/dma-noncoherent.c +++ b/arch/mips/mm/dma-noncoherent.c @@ -299,7 +299,7 @@ int dma_supported(struct device *dev, u64 mask) EXPORT_SYMBOL(dma_supported); -int dma_is_consistent(dma_addr_t dma_addr) +int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return 1; } diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 335a25540c0..acee062cd6f 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -313,7 +313,7 @@ NCR_700_detect(struct scsi_host_template *tpnt, hostdata->status = memory + STATUS_OFFSET; /* all of these offsets are L1_CACHE_BYTES separated. It is fatal * if this isn't sufficient separation to avoid dma flushing issues */ - BUG_ON(!dma_is_consistent(pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); + BUG_ON(!dma_is_consistent(hostdata->dev, pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); hostdata->dev = dev; diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h index b9ff4d8cb33..b274bf6317c 100644 --- a/include/asm-alpha/dma-mapping.h +++ b/include/asm-alpha/dma-mapping.h @@ -51,7 +51,7 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -#define dma_is_consistent(dev) (1) +#define dma_is_consistent(d, h) (1) int dma_set_mask(struct device *dev, u64 mask); diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h index 666617711c8..9bc46b486af 100644 --- a/include/asm-arm/dma-mapping.h +++ b/include/asm-arm/dma-mapping.h @@ -48,7 +48,7 @@ static inline int dma_get_cache_alignment(void) return 32; } -static inline int dma_is_consistent(dma_addr_t handle) +static inline int dma_is_consistent(struct device *dev, dma_addr_t handle) { return !!arch_is_coherent(); } diff --git a/include/asm-avr32/dma-mapping.h b/include/asm-avr32/dma-mapping.h index 4c40cb41cdf..44630be2ee2 100644 --- a/include/asm-avr32/dma-mapping.h +++ b/include/asm-avr32/dma-mapping.h @@ -307,7 +307,7 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -static inline int dma_is_consistent(dma_addr_t dma_addr) +static inline int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return 1; } diff --git a/include/asm-cris/dma-mapping.h b/include/asm-cris/dma-mapping.h index cbf1a98f012..af704fdd3d0 100644 --- a/include/asm-cris/dma-mapping.h +++ b/include/asm-cris/dma-mapping.h @@ -156,7 +156,7 @@ dma_get_cache_alignment(void) return (1 << INTERNODE_CACHE_SHIFT); } -#define dma_is_consistent(d) (1) +#define dma_is_consistent(d, h) (1) static inline void dma_cache_sync(void *vaddr, size_t size, diff --git a/include/asm-frv/dma-mapping.h b/include/asm-frv/dma-mapping.h index e9fc1d47797..7b97fc785f7 100644 --- a/include/asm-frv/dma-mapping.h +++ b/include/asm-frv/dma-mapping.h @@ -172,7 +172,7 @@ int dma_get_cache_alignment(void) return 1 << L1_CACHE_SHIFT; } -#define dma_is_consistent(d) (1) +#define dma_is_consistent(d, h) (1) static inline void dma_cache_sync(void *vaddr, size_t size, diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h index b541e48cc54..b9be3fc344c 100644 --- a/include/asm-generic/dma-mapping.h +++ b/include/asm-generic/dma-mapping.h @@ -266,7 +266,7 @@ dma_error(dma_addr_t dma_addr) #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -#define dma_is_consistent(d) (1) +#define dma_is_consistent(d, h) (1) static inline int dma_get_cache_alignment(void) diff --git a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h index 81999a3ebe7..7da64c9f173 100644 --- a/include/asm-i386/dma-mapping.h +++ b/include/asm-i386/dma-mapping.h @@ -156,7 +156,7 @@ dma_get_cache_alignment(void) return (1 << INTERNODE_CACHE_SHIFT); } -#define dma_is_consistent(d) (1) +#define dma_is_consistent(d, h) (1) static inline void dma_cache_sync(void *vaddr, size_t size, diff --git a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h index 99a8f8e1218..4b075bc032e 100644 --- a/include/asm-ia64/dma-mapping.h +++ b/include/asm-ia64/dma-mapping.h @@ -59,6 +59,6 @@ dma_cache_sync (void *vaddr, size_t size, enum dma_data_direction dir) mb(); } -#define dma_is_consistent(dma_handle) (1) /* all we do is coherent memory... */ +#define dma_is_consistent(d, h) (1) /* all we do is coherent memory... */ #endif /* _ASM_IA64_DMA_MAPPING_H */ diff --git a/include/asm-m68k/dma-mapping.h b/include/asm-m68k/dma-mapping.h index d90d841d3df..efc89c12f83 100644 --- a/include/asm-m68k/dma-mapping.h +++ b/include/asm-m68k/dma-mapping.h @@ -21,7 +21,7 @@ static inline int dma_get_cache_alignment(void) return 1 << L1_CACHE_SHIFT; } -static inline int dma_is_consistent(dma_addr_t dma_addr) +static inline int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return 0; } diff --git a/include/asm-mips/dma-mapping.h b/include/asm-mips/dma-mapping.h index 43288634c38..e17f70d7b70 100644 --- a/include/asm-mips/dma-mapping.h +++ b/include/asm-mips/dma-mapping.h @@ -63,7 +63,7 @@ dma_get_cache_alignment(void) return 128; } -extern int dma_is_consistent(dma_addr_t dma_addr); +extern int dma_is_consistent(struct device *dev, dma_addr_t dma_addr); extern void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction); diff --git a/include/asm-parisc/dma-mapping.h b/include/asm-parisc/dma-mapping.h index 1e387e1dad3..c40d48afdc5 100644 --- a/include/asm-parisc/dma-mapping.h +++ b/include/asm-parisc/dma-mapping.h @@ -191,7 +191,7 @@ dma_get_cache_alignment(void) } static inline int -dma_is_consistent(dma_addr_t dma_addr) +dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return (hppa_dma_ops->dma_sync_single_for_cpu == NULL); } diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h index 7e38b5fddad..3cf635b53b8 100644 --- a/include/asm-powerpc/dma-mapping.h +++ b/include/asm-powerpc/dma-mapping.h @@ -342,9 +342,9 @@ static inline int dma_mapping_error(dma_addr_t dma_addr) #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) #ifdef CONFIG_NOT_COHERENT_CACHE -#define dma_is_consistent(d) (0) +#define dma_is_consistent(d, h) (0) #else -#define dma_is_consistent(d) (1) +#define dma_is_consistent(d, h) (1) #endif static inline int dma_get_cache_alignment(void) diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h index 27c46fbeebd..5fe0072f3f8 100644 --- a/include/asm-sparc64/dma-mapping.h +++ b/include/asm-sparc64/dma-mapping.h @@ -181,7 +181,7 @@ dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t siz #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -#define dma_is_consistent(d) (1) +#define dma_is_consistent(d, h) (1) static inline int dma_get_cache_alignment(void) diff --git a/include/asm-um/dma-mapping.h b/include/asm-um/dma-mapping.h index babd2989511..defb5b8307d 100644 --- a/include/asm-um/dma-mapping.h +++ b/include/asm-um/dma-mapping.h @@ -94,7 +94,7 @@ dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems, #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -#define dma_is_consistent(d) (1) +#define dma_is_consistent(d, h) (1) static inline int dma_get_cache_alignment(void) diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h index 10174b110a5..c8cc4887fba 100644 --- a/include/asm-x86_64/dma-mapping.h +++ b/include/asm-x86_64/dma-mapping.h @@ -180,7 +180,7 @@ static inline int dma_get_cache_alignment(void) return boot_cpu_data.x86_clflush_size; } -#define dma_is_consistent(h) 1 +#define dma_is_consistent(d, h) 1 extern int dma_set_mask(struct device *dev, u64 mask); diff --git a/include/asm-xtensa/dma-mapping.h b/include/asm-xtensa/dma-mapping.h index c39c91dfcc6..827d1dfd9e1 100644 --- a/include/asm-xtensa/dma-mapping.h +++ b/include/asm-xtensa/dma-mapping.h @@ -170,7 +170,7 @@ dma_get_cache_alignment(void) return L1_CACHE_BYTES; } -#define dma_is_consistent(d) (1) +#define dma_is_consistent(d, h) (1) static inline void dma_cache_sync(void *vaddr, size_t size, -- cgit v1.2.3-70-g09d2 From d3fa72e4556ec1f04e46a0d561d9e785ecaa173d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 6 Dec 2006 20:38:56 -0800 Subject: [PATCH] Pass struct dev pointer to dma_cache_sync() Pass struct dev pointer to dma_cache_sync() dma_cache_sync() is ill-designed in that it does not have a struct device pointer argument which makes proper support for systems that consist of a mix of coherent and non-coherent DMA devices hard. Change dma_cache_sync to take a struct device pointer as first argument and fix all its callers to pass it. Signed-off-by: Ralf Baechle Cc: James Bottomley Cc: "David S. Miller" Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DMA-API.txt | 2 +- arch/avr32/mm/dma-coherent.c | 2 +- arch/mips/mm/dma-coherent.c | 2 +- arch/mips/mm/dma-ip27.c | 2 +- arch/mips/mm/dma-ip32.c | 3 +- arch/mips/mm/dma-noncoherent.c | 3 +- drivers/net/lasi_82596.c | 94 +++++++++++++++++++-------------------- drivers/scsi/53c700.c | 80 ++++++++++++++++++--------------- drivers/scsi/53c700.h | 16 +++---- drivers/serial/mpsc.c | 22 ++++----- include/asm-alpha/dma-mapping.h | 2 +- include/asm-avr32/dma-mapping.h | 3 +- include/asm-cris/dma-mapping.h | 2 +- include/asm-frv/dma-mapping.h | 2 +- include/asm-generic/dma-mapping.h | 2 +- include/asm-i386/dma-mapping.h | 2 +- include/asm-ia64/dma-mapping.h | 3 +- include/asm-m68k/dma-mapping.h | 2 +- include/asm-mips/dma-mapping.h | 2 +- include/asm-parisc/dma-mapping.h | 2 +- include/asm-powerpc/dma-mapping.h | 2 +- include/asm-sh/dma-mapping.h | 2 +- include/asm-sh64/dma-mapping.h | 2 +- include/asm-sparc64/dma-mapping.h | 2 +- include/asm-um/dma-mapping.h | 2 +- include/asm-x86_64/dma-mapping.h | 3 +- include/asm-xtensa/dma-mapping.h | 2 +- 27 files changed, 137 insertions(+), 126 deletions(-) (limited to 'include/asm-powerpc') diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index 3dc1f9125ca..805db4b2cba 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -459,7 +459,7 @@ anything like this. You must also be extra careful about accessing memory you intend to sync partially. void -dma_cache_sync(void *vaddr, size_t size, +dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) Do a partial sync of memory that was allocated by diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c index 44ab8a7bdae..b68d669f823 100644 --- a/arch/avr32/mm/dma-coherent.c +++ b/arch/avr32/mm/dma-coherent.c @@ -11,7 +11,7 @@ #include #include -void dma_cache_sync(void *vaddr, size_t size, int direction) +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int direction) { /* * No need to sync an uncached area diff --git a/arch/mips/mm/dma-coherent.c b/arch/mips/mm/dma-coherent.c index 18bc83e577c..5697c6e250a 100644 --- a/arch/mips/mm/dma-coherent.c +++ b/arch/mips/mm/dma-coherent.c @@ -197,7 +197,7 @@ int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) EXPORT_SYMBOL(dma_is_consistent); -void dma_cache_sync(void *vaddr, size_t size, +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); diff --git a/arch/mips/mm/dma-ip27.c b/arch/mips/mm/dma-ip27.c index 8e9a5a8f5d6..f088344db46 100644 --- a/arch/mips/mm/dma-ip27.c +++ b/arch/mips/mm/dma-ip27.c @@ -204,7 +204,7 @@ int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) EXPORT_SYMBOL(dma_is_consistent); -void dma_cache_sync(void *vaddr, size_t size, +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); diff --git a/arch/mips/mm/dma-ip32.c b/arch/mips/mm/dma-ip32.c index 08720a42100..b42b6f7456e 100644 --- a/arch/mips/mm/dma-ip32.c +++ b/arch/mips/mm/dma-ip32.c @@ -370,7 +370,8 @@ int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) EXPORT_SYMBOL(dma_is_consistent); -void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction) +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction) { if (direction == DMA_NONE) return; diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c index 4a3efc63337..8cecef0957c 100644 --- a/arch/mips/mm/dma-noncoherent.c +++ b/arch/mips/mm/dma-noncoherent.c @@ -306,7 +306,8 @@ int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) EXPORT_SYMBOL(dma_is_consistent); -void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction) +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction) { if (direction == DMA_NONE) return; diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index f4d815bca64..ea392f2a5aa 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -119,14 +119,14 @@ #define DEB(x,y) if (i596_debug & (x)) { y; } -#define CHECK_WBACK(addr,len) \ - do { dma_cache_sync((void *)addr, len, DMA_TO_DEVICE); } while (0) +#define CHECK_WBACK(priv, addr,len) \ + do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_TO_DEVICE); } while (0) -#define CHECK_INV(addr,len) \ - do { dma_cache_sync((void *)addr, len, DMA_FROM_DEVICE); } while(0) +#define CHECK_INV(priv, addr,len) \ + do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_FROM_DEVICE); } while(0) -#define CHECK_WBACK_INV(addr,len) \ - do { dma_cache_sync((void *)addr, len, DMA_BIDIRECTIONAL); } while (0) +#define CHECK_WBACK_INV(priv, addr,len) \ + do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0) #define PA_I82596_RESET 0 /* Offsets relative to LASI-LAN-Addr.*/ @@ -449,10 +449,10 @@ static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x) static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str) { - CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp)); + CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp)); while (--delcnt && lp->iscp.stat) { udelay(10); - CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp)); + CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp)); } if (!delcnt) { printk("%s: %s, iscp.stat %04x, didn't clear\n", @@ -466,10 +466,10 @@ static inline int wait_istat(struct net_device *dev, struct i596_private *lp, in static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str) { - CHECK_INV(&(lp->scb), sizeof(struct i596_scb)); + CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); while (--delcnt && lp->scb.command) { udelay(10); - CHECK_INV(&(lp->scb), sizeof(struct i596_scb)); + CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); } if (!delcnt) { printk("%s: %s, status %4.4x, cmd %4.4x.\n", @@ -522,7 +522,7 @@ static void i596_display_data(struct net_device *dev) rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size); rbd = rbd->v_next; } while (rbd != lp->rbd_head); - CHECK_INV(lp, sizeof(struct i596_private)); + CHECK_INV(lp, lp, sizeof(struct i596_private)); } @@ -592,7 +592,7 @@ static inline void init_rx_bufs(struct net_device *dev) rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds)); rfd->cmd = CMD_EOL|CMD_FLEX; - CHECK_WBACK_INV(lp, sizeof(struct i596_private)); + CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private)); } static inline void remove_rx_bufs(struct net_device *dev) @@ -629,7 +629,7 @@ static void rebuild_rx_bufs(struct net_device *dev) lp->rbd_head = lp->rbds; lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds)); - CHECK_WBACK_INV(lp, sizeof(struct i596_private)); + CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private)); } @@ -663,8 +663,8 @@ static int init_i596_mem(struct net_device *dev) DEB(DEB_INIT, printk("%s: starting i82596.\n", dev->name)); - CHECK_WBACK(&(lp->scp), sizeof(struct i596_scp)); - CHECK_WBACK(&(lp->iscp), sizeof(struct i596_iscp)); + CHECK_WBACK(lp, &(lp->scp), sizeof(struct i596_scp)); + CHECK_WBACK(lp, &(lp->iscp), sizeof(struct i596_iscp)); MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp)); @@ -678,25 +678,25 @@ static int init_i596_mem(struct net_device *dev) rebuild_rx_bufs(dev); lp->scb.command = 0; - CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); enable_irq(dev->irq); /* enable IRQs from LAN */ DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name)); memcpy(lp->cf_cmd.i596_config, init_setup, 14); lp->cf_cmd.cmd.command = CmdConfigure; - CHECK_WBACK(&(lp->cf_cmd), sizeof(struct cf_cmd)); + CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd)); i596_add_cmd(dev, &lp->cf_cmd.cmd); DEB(DEB_INIT, printk("%s: queuing CmdSASetup\n", dev->name)); memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6); lp->sa_cmd.cmd.command = CmdSASetup; - CHECK_WBACK(&(lp->sa_cmd), sizeof(struct sa_cmd)); + CHECK_WBACK(lp, &(lp->sa_cmd), sizeof(struct sa_cmd)); i596_add_cmd(dev, &lp->sa_cmd.cmd); DEB(DEB_INIT, printk("%s: queuing CmdTDR\n", dev->name)); lp->tdr_cmd.cmd.command = CmdTDR; - CHECK_WBACK(&(lp->tdr_cmd), sizeof(struct tdr_cmd)); + CHECK_WBACK(lp, &(lp->tdr_cmd), sizeof(struct tdr_cmd)); i596_add_cmd(dev, &lp->tdr_cmd.cmd); spin_lock_irqsave (&lp->lock, flags); @@ -708,7 +708,7 @@ static int init_i596_mem(struct net_device *dev) DEB(DEB_INIT, printk("%s: Issuing RX_START\n", dev->name)); lp->scb.command = RX_START; lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); - CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); CA(dev); @@ -740,13 +740,13 @@ static inline int i596_rx(struct net_device *dev) rfd = lp->rfd_head; /* Ref next frame to check */ - CHECK_INV(rfd, sizeof(struct i596_rfd)); + CHECK_INV(lp, rfd, sizeof(struct i596_rfd)); while ((rfd->stat) & STAT_C) { /* Loop while complete frames */ if (rfd->rbd == I596_NULL) rbd = NULL; else if (rfd->rbd == lp->rbd_head->b_addr) { rbd = lp->rbd_head; - CHECK_INV(rbd, sizeof(struct i596_rbd)); + CHECK_INV(lp, rbd, sizeof(struct i596_rbd)); } else { printk("%s: rbd chain broken!\n", dev->name); @@ -790,7 +790,7 @@ static inline int i596_rx(struct net_device *dev) dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE); rbd->v_data = newskb->data; rbd->b_data = WSWAPchar(dma_addr); - CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd)); + CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd)); } else skb = dev_alloc_skb(pkt_len + 2); @@ -842,7 +842,7 @@ memory_squeeze: if (rbd != NULL && (rbd->count & 0x4000)) { rbd->count = 0; lp->rbd_head = rbd->v_next; - CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd)); + CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd)); } /* Tidy the frame descriptor, marking it as end of list */ @@ -860,10 +860,10 @@ memory_squeeze: lp->scb.rfd = rfd->b_next; lp->rfd_head = rfd->v_next; - CHECK_WBACK_INV(rfd->v_prev, sizeof(struct i596_rfd)); - CHECK_WBACK_INV(rfd, sizeof(struct i596_rfd)); + CHECK_WBACK_INV(lp, rfd->v_prev, sizeof(struct i596_rfd)); + CHECK_WBACK_INV(lp, rfd, sizeof(struct i596_rfd)); rfd = lp->rfd_head; - CHECK_INV(rfd, sizeof(struct i596_rfd)); + CHECK_INV(lp, rfd, sizeof(struct i596_rfd)); } DEB(DEB_RXFRAME, printk("frames %d\n", frames)); @@ -902,12 +902,12 @@ static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private ptr->v_next = NULL; ptr->b_next = I596_NULL; } - CHECK_WBACK_INV(ptr, sizeof(struct i596_cmd)); + CHECK_WBACK_INV(lp, ptr, sizeof(struct i596_cmd)); } wait_cmd(dev, lp, 100, "i596_cleanup_cmd timed out"); lp->scb.cmd = I596_NULL; - CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); } @@ -925,7 +925,7 @@ static inline void i596_reset(struct net_device *dev, struct i596_private *lp) /* FIXME: this command might cause an lpmc */ lp->scb.command = CUC_ABORT | RX_ABORT; - CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); CA(dev); /* wait for shutdown */ @@ -951,20 +951,20 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) cmd->command |= (CMD_EOL | CMD_INTR); cmd->v_next = NULL; cmd->b_next = I596_NULL; - CHECK_WBACK(cmd, sizeof(struct i596_cmd)); + CHECK_WBACK(lp, cmd, sizeof(struct i596_cmd)); spin_lock_irqsave (&lp->lock, flags); if (lp->cmd_head != NULL) { lp->cmd_tail->v_next = cmd; lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status)); - CHECK_WBACK(lp->cmd_tail, sizeof(struct i596_cmd)); + CHECK_WBACK(lp, lp->cmd_tail, sizeof(struct i596_cmd)); } else { lp->cmd_head = cmd; wait_cmd(dev, lp, 100, "i596_add_cmd timed out"); lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status)); lp->scb.command = CUC_START; - CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); CA(dev); } lp->cmd_tail = cmd; @@ -998,12 +998,12 @@ static int i596_test(struct net_device *dev) data = virt_to_dma(lp,tint); tint[1] = -1; - CHECK_WBACK(tint,PAGE_SIZE); + CHECK_WBACK(lp, tint, PAGE_SIZE); MPU_PORT(dev, 1, data); for(data = 1000000; data; data--) { - CHECK_INV(tint,PAGE_SIZE); + CHECK_INV(lp, tint, PAGE_SIZE); if(tint[1] != -1) break; @@ -1061,7 +1061,7 @@ static void i596_tx_timeout (struct net_device *dev) /* Issue a channel attention signal */ DEB(DEB_ERRORS, printk("Kicking board.\n")); lp->scb.command = CUC_START | RX_START; - CHECK_WBACK_INV(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); CA (dev); lp->last_restart = lp->stats.tx_packets; } @@ -1118,8 +1118,8 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) tbd->data = WSWAPchar(tx_cmd->dma_addr); DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued")); - CHECK_WBACK_INV(tx_cmd, sizeof(struct tx_cmd)); - CHECK_WBACK_INV(tbd, sizeof(struct i596_tbd)); + CHECK_WBACK_INV(lp, tx_cmd, sizeof(struct tx_cmd)); + CHECK_WBACK_INV(lp, tbd, sizeof(struct i596_tbd)); i596_add_cmd(dev, &tx_cmd->cmd); lp->stats.tx_packets++; @@ -1228,7 +1228,7 @@ static int __devinit i82596_probe(struct net_device *dev, lp->dma_addr = dma_addr; lp->dev = gen_dev; - CHECK_WBACK_INV(dev->mem_start, sizeof(struct i596_private)); + CHECK_WBACK_INV(lp, dev->mem_start, sizeof(struct i596_private)); i = register_netdev(dev); if (i) { @@ -1295,7 +1295,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id) DEB(DEB_INTS, printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700)); while (lp->cmd_head != NULL) { - CHECK_INV(lp->cmd_head, sizeof(struct i596_cmd)); + CHECK_INV(lp, lp->cmd_head, sizeof(struct i596_cmd)); if (!(lp->cmd_head->status & STAT_C)) break; @@ -1358,7 +1358,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id) } ptr->v_next = NULL; ptr->b_next = I596_NULL; - CHECK_WBACK(ptr, sizeof(struct i596_cmd)); + CHECK_WBACK(lp, ptr, sizeof(struct i596_cmd)); lp->last_cmd = jiffies; } @@ -1372,13 +1372,13 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id) ptr->command &= 0x1fff; ptr = ptr->v_next; - CHECK_WBACK_INV(prev, sizeof(struct i596_cmd)); + CHECK_WBACK_INV(lp, prev, sizeof(struct i596_cmd)); } if ((lp->cmd_head != NULL)) ack_cmd |= CUC_START; lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status)); - CHECK_WBACK_INV(&lp->scb, sizeof(struct i596_scb)); + CHECK_WBACK_INV(lp, &lp->scb, sizeof(struct i596_scb)); } if ((status & 0x1000) || (status & 0x4000)) { if ((status & 0x4000)) @@ -1397,7 +1397,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id) } wait_cmd(dev, lp, 100, "i596 interrupt, timeout"); lp->scb.command = ack_cmd; - CHECK_WBACK(&lp->scb, sizeof(struct i596_scb)); + CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb)); /* DANGER: I suspect that some kind of interrupt acknowledgement aside from acking the 82596 might be needed @@ -1426,7 +1426,7 @@ static int i596_close(struct net_device *dev) wait_cmd(dev, lp, 100, "close1 timed out"); lp->scb.command = CUC_ABORT | RX_ABORT; - CHECK_WBACK(&lp->scb, sizeof(struct i596_scb)); + CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb)); CA(dev); @@ -1486,7 +1486,7 @@ static void set_multicast_list(struct net_device *dev) dev->name); else { lp->cf_cmd.cmd.command = CmdConfigure; - CHECK_WBACK_INV(&lp->cf_cmd, sizeof(struct cf_cmd)); + CHECK_WBACK_INV(lp, &lp->cf_cmd, sizeof(struct cf_cmd)); i596_add_cmd(dev, &lp->cf_cmd.cmd); } } @@ -1514,7 +1514,7 @@ static void set_multicast_list(struct net_device *dev) DEB(DEB_MULTI, printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5])); } - CHECK_WBACK_INV(&lp->mc_cmd, sizeof(struct mc_cmd)); + CHECK_WBACK_INV(lp, &lp->mc_cmd, sizeof(struct mc_cmd)); i596_add_cmd(dev, &cmd->cmd); } } diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index acee062cd6f..68103e508db 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -362,11 +362,11 @@ NCR_700_detect(struct scsi_host_template *tpnt, for (j = 0; j < PATCHES; j++) script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]); /* now patch up fixed addresses. */ - script_patch_32(script, MessageLocation, + script_patch_32(hostdata->dev, script, MessageLocation, pScript + MSGOUT_OFFSET); - script_patch_32(script, StatusAddress, + script_patch_32(hostdata->dev, script, StatusAddress, pScript + STATUS_OFFSET); - script_patch_32(script, ReceiveMsgAddress, + script_patch_32(hostdata->dev, script, ReceiveMsgAddress, pScript + MSGIN_OFFSET); hostdata->script = script; @@ -821,8 +821,9 @@ process_extended_message(struct Scsi_Host *host, shost_printk(KERN_WARNING, host, "Unexpected SDTR msg\n"); hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, + MessageCount, 1); /* SendMsgOut returns, so set up the return * address */ resume_offset = hostdata->pScript + Ent_SendMessageWithATN; @@ -833,8 +834,9 @@ process_extended_message(struct Scsi_Host *host, printk(KERN_INFO "scsi%d: (%d:%d), Unsolicited WDTR after CMD, Rejecting\n", host->host_no, pun, lun); hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, + 1); resume_offset = hostdata->pScript + Ent_SendMessageWithATN; break; @@ -847,8 +849,9 @@ process_extended_message(struct Scsi_Host *host, printk("\n"); /* just reject it */ hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, + 1); /* SendMsgOut returns, so set up the return * address */ resume_offset = hostdata->pScript + Ent_SendMessageWithATN; @@ -929,8 +932,9 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata printk("\n"); /* just reject it */ hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, + 1); /* SendMsgOut returns, so set up the return * address */ resume_offset = hostdata->pScript + Ent_SendMessageWithATN; @@ -939,7 +943,7 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata } NCR_700_writel(temp, host, TEMP_REG); /* set us up to receive another message */ - dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); return resume_offset; } @@ -1019,9 +1023,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, slot->SG[1].ins = bS_to_host(SCRIPT_RETURN); slot->SG[1].pAddr = 0; slot->resume_offset = hostdata->pScript; - dma_cache_sync(slot->SG, sizeof(slot->SG[0])*2, DMA_TO_DEVICE); - dma_cache_sync(SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); - + dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG[0])*2, DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); + /* queue the command for reissue */ slot->state = NCR_700_SLOT_QUEUED; slot->flags = NCR_700_FLAG_AUTOSENSE; @@ -1136,11 +1140,12 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, hostdata->cmd = slot->cmnd; /* re-patch for this command */ - script_patch_32_abs(hostdata->script, CommandAddress, - slot->pCmd); - script_patch_16(hostdata->script, + script_patch_32_abs(hostdata->dev, hostdata->script, + CommandAddress, slot->pCmd); + script_patch_16(hostdata->dev, hostdata->script, CommandCount, slot->cmnd->cmd_len); - script_patch_32_abs(hostdata->script, SGScriptStartAddress, + script_patch_32_abs(hostdata->dev, hostdata->script, + SGScriptStartAddress, to32bit(&slot->pSG[0].ins)); /* Note: setting SXFER only works if we're @@ -1150,13 +1155,13 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, * should therefore always clear ACK */ NCR_700_writeb(NCR_700_get_SXFER(hostdata->cmd->device), host, SXFER_REG); - dma_cache_sync(hostdata->msgin, + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); - dma_cache_sync(hostdata->msgout, + dma_cache_sync(hostdata->dev, hostdata->msgout, MSG_ARRAY_SIZE, DMA_TO_DEVICE); /* I'm just being paranoid here, the command should * already have been flushed from the cache */ - dma_cache_sync(slot->cmnd->cmnd, + dma_cache_sync(hostdata->dev, slot->cmnd->cmnd, slot->cmnd->cmd_len, DMA_TO_DEVICE); @@ -1220,7 +1225,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, hostdata->reselection_id = reselection_id; /* just in case we have a stale simple tag message, clear it */ hostdata->msgin[1] = 0; - dma_cache_sync(hostdata->msgin, + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_BIDIRECTIONAL); if(hostdata->tag_negotiated & (1<pScript + Ent_GetReselectionWithTag; @@ -1336,7 +1341,7 @@ process_selection(struct Scsi_Host *host, __u32 dsp) hostdata->cmd = NULL; /* clear any stale simple tag message */ hostdata->msgin[1] = 0; - dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE, + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_BIDIRECTIONAL); if(id == 0xff) { @@ -1433,29 +1438,30 @@ NCR_700_start_command(struct scsi_cmnd *SCp) NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } - script_patch_16(hostdata->script, MessageCount, count); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, count); - script_patch_ID(hostdata->script, + script_patch_ID(hostdata->dev, hostdata->script, Device_ID, 1<script, CommandAddress, + script_patch_32_abs(hostdata->dev, hostdata->script, CommandAddress, slot->pCmd); - script_patch_16(hostdata->script, CommandCount, SCp->cmd_len); + script_patch_16(hostdata->dev, hostdata->script, CommandCount, + SCp->cmd_len); /* finally plumb the beginning of the SG list into the script * */ - script_patch_32_abs(hostdata->script, SGScriptStartAddress, - to32bit(&slot->pSG[0].ins)); + script_patch_32_abs(hostdata->dev, hostdata->script, + SGScriptStartAddress, to32bit(&slot->pSG[0].ins)); NCR_700_clear_fifo(SCp->device->host); if(slot->resume_offset == 0) slot->resume_offset = hostdata->pScript; /* now perform all the writebacks and invalidates */ - dma_cache_sync(hostdata->msgout, count, DMA_TO_DEVICE); - dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE, + dma_cache_sync(hostdata->dev, hostdata->msgout, count, DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); - dma_cache_sync(SCp->cmnd, SCp->cmd_len, DMA_TO_DEVICE); - dma_cache_sync(hostdata->status, 1, DMA_FROM_DEVICE); + dma_cache_sync(hostdata->dev, SCp->cmnd, SCp->cmd_len, DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, hostdata->status, 1, DMA_FROM_DEVICE); /* set the synchronous period/offset */ NCR_700_writeb(NCR_700_get_SXFER(SCp->device), @@ -1631,7 +1637,7 @@ NCR_700_intr(int irq, void *dev_id) slot->SG[i].ins = bS_to_host(SCRIPT_NOP); slot->SG[i].pAddr = 0; } - dma_cache_sync(slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); /* and pretend we disconnected after * the command phase */ resume_offset = hostdata->pScript + Ent_MsgInDuringData; @@ -1897,9 +1903,9 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) } slot->SG[i].ins = bS_to_host(SCRIPT_RETURN); slot->SG[i].pAddr = 0; - dma_cache_sync(slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); DEBUG((" SETTING %08lx to %x\n", - (&slot->pSG[i].ins), + (&slot->pSG[i].ins), slot->SG[i].ins)); } slot->resume_offset = 0; diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h index f5c3caf344a..f38822db421 100644 --- a/drivers/scsi/53c700.h +++ b/drivers/scsi/53c700.h @@ -415,31 +415,31 @@ struct NCR_700_Host_Parameters { #define NCR_710_MIN_XFERP 0 #define NCR_700_MIN_PERIOD 25 /* for SDTR message, 100ns */ -#define script_patch_32(script, symbol, value) \ +#define script_patch_32(dev, script, symbol, value) \ { \ int i; \ for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ __u32 val = bS_to_cpu((script)[A_##symbol##_used[i]]) + value; \ (script)[A_##symbol##_used[i]] = bS_to_host(val); \ - dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ + dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ DEBUG((" script, patching %s at %d to 0x%lx\n", \ #symbol, A_##symbol##_used[i], (value))); \ } \ } -#define script_patch_32_abs(script, symbol, value) \ +#define script_patch_32_abs(dev, script, symbol, value) \ { \ int i; \ for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ (script)[A_##symbol##_used[i]] = bS_to_host(value); \ - dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ + dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ DEBUG((" script, patching %s at %d to 0x%lx\n", \ #symbol, A_##symbol##_used[i], (value))); \ } \ } /* Used for patching the SCSI ID in the SELECT instruction */ -#define script_patch_ID(script, symbol, value) \ +#define script_patch_ID(dev, script, symbol, value) \ { \ int i; \ for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ @@ -447,13 +447,13 @@ struct NCR_700_Host_Parameters { val &= 0xff00ffff; \ val |= ((value) & 0xff) << 16; \ (script)[A_##symbol##_used[i]] = bS_to_host(val); \ - dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ + dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ DEBUG((" script, patching ID field %s at %d to 0x%x\n", \ #symbol, A_##symbol##_used[i], val)); \ } \ } -#define script_patch_16(script, symbol, value) \ +#define script_patch_16(dev, script, symbol, value) \ { \ int i; \ for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ @@ -461,7 +461,7 @@ struct NCR_700_Host_Parameters { val &= 0xffff0000; \ val |= ((value) & 0xffff); \ (script)[A_##symbol##_used[i]] = bS_to_host(val); \ - dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ + dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ DEBUG((" script, patching short field %s at %d to 0x%x\n", \ #symbol, A_##symbol##_used[i], val)); \ } \ diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index 8eea69f2998..29823bd60fb 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -555,7 +555,7 @@ mpsc_sdma_start_tx(struct mpsc_port_info *pi) if (!mpsc_sdma_tx_active(pi)) { txre = (struct mpsc_tx_desc *)(pi->txr + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)txre, @@ -931,7 +931,7 @@ mpsc_init_rings(struct mpsc_port_info *pi) } txre->link = cpu_to_be32(pi->txr_p); /* Wrap last back to first */ - dma_cache_sync((void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE, + dma_cache_sync(pi->port.dev, (void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ @@ -1005,7 +1005,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi) rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn*MPSC_RXRE_SIZE)); - dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)rxre, @@ -1029,7 +1029,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi) } bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE); - dma_cache_sync((void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)bp, @@ -1098,7 +1098,7 @@ next_frame: SDMA_DESC_CMDSTAT_F | SDMA_DESC_CMDSTAT_L); wmb(); - dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)rxre, @@ -1109,7 +1109,7 @@ next_frame: pi->rxr_posn = (pi->rxr_posn + 1) & (MPSC_RXR_ENTRIES - 1); rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn * MPSC_RXRE_SIZE)); - dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)rxre, @@ -1143,7 +1143,7 @@ mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr) SDMA_DESC_CMDSTAT_EI : 0)); wmb(); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)txre, @@ -1192,7 +1192,7 @@ mpsc_copy_tx_data(struct mpsc_port_info *pi) else /* All tx data copied into ring bufs */ return; - dma_cache_sync((void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)bp, @@ -1217,7 +1217,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi) txre = (struct mpsc_tx_desc *)(pi->txr + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)txre, @@ -1235,7 +1235,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi) txre = (struct mpsc_tx_desc *)(pi->txr + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ @@ -1652,7 +1652,7 @@ mpsc_console_write(struct console *co, const char *s, uint count) count--; } - dma_cache_sync((void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)bp, diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h index b274bf6317c..57e09f5e342 100644 --- a/include/asm-alpha/dma-mapping.h +++ b/include/asm-alpha/dma-mapping.h @@ -60,7 +60,7 @@ int dma_set_mask(struct device *dev, u64 mask); #define dma_sync_single_range(dev, addr, off, size, dir) do { } while (0) #define dma_sync_sg_for_cpu(dev, sg, nents, dir) do { } while (0) #define dma_sync_sg_for_device(dev, sg, nents, dir) do { } while (0) -#define dma_cache_sync(va, size, dir) do { } while (0) +#define dma_cache_sync(dev, va, size, dir) do { } while (0) #define dma_get_cache_alignment() L1_CACHE_BYTES diff --git a/include/asm-avr32/dma-mapping.h b/include/asm-avr32/dma-mapping.h index 44630be2ee2..0580b5d62bb 100644 --- a/include/asm-avr32/dma-mapping.h +++ b/include/asm-avr32/dma-mapping.h @@ -8,7 +8,8 @@ #include #include -extern void dma_cache_sync(void *vaddr, size_t size, int direction); +extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, + int direction); /* * Return whether the given device DMA address mask can be supported diff --git a/include/asm-cris/dma-mapping.h b/include/asm-cris/dma-mapping.h index af704fdd3d0..662cea70152 100644 --- a/include/asm-cris/dma-mapping.h +++ b/include/asm-cris/dma-mapping.h @@ -159,7 +159,7 @@ dma_get_cache_alignment(void) #define dma_is_consistent(d, h) (1) static inline void -dma_cache_sync(void *vaddr, size_t size, +dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { } diff --git a/include/asm-frv/dma-mapping.h b/include/asm-frv/dma-mapping.h index 7b97fc785f7..bcb2df68496 100644 --- a/include/asm-frv/dma-mapping.h +++ b/include/asm-frv/dma-mapping.h @@ -175,7 +175,7 @@ int dma_get_cache_alignment(void) #define dma_is_consistent(d, h) (1) static inline -void dma_cache_sync(void *vaddr, size_t size, +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { flush_write_buffers(); diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h index b9be3fc344c..783ab9944d7 100644 --- a/include/asm-generic/dma-mapping.h +++ b/include/asm-generic/dma-mapping.h @@ -295,7 +295,7 @@ dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, } static inline void -dma_cache_sync(void *vaddr, size_t size, +dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { /* could define this in terms of the dma_cache ... operations, diff --git a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h index 7da64c9f173..183eebeebbd 100644 --- a/include/asm-i386/dma-mapping.h +++ b/include/asm-i386/dma-mapping.h @@ -159,7 +159,7 @@ dma_get_cache_alignment(void) #define dma_is_consistent(d, h) (1) static inline void -dma_cache_sync(void *vaddr, size_t size, +dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { flush_write_buffers(); diff --git a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h index 4b075bc032e..ebd5887f4b1 100644 --- a/include/asm-ia64/dma-mapping.h +++ b/include/asm-ia64/dma-mapping.h @@ -50,7 +50,8 @@ dma_set_mask (struct device *dev, u64 mask) extern int dma_get_cache_alignment(void); static inline void -dma_cache_sync (void *vaddr, size_t size, enum dma_data_direction dir) +dma_cache_sync (struct device *dev, void *vaddr, size_t size, + enum dma_data_direction dir) { /* * IA-64 is cache-coherent, so this is mostly a no-op. However, we do need to diff --git a/include/asm-m68k/dma-mapping.h b/include/asm-m68k/dma-mapping.h index efc89c12f83..00259ed6fc9 100644 --- a/include/asm-m68k/dma-mapping.h +++ b/include/asm-m68k/dma-mapping.h @@ -41,7 +41,7 @@ static inline void dma_free_noncoherent(struct device *dev, size_t size, { dma_free_coherent(dev, size, addr, handle); } -static inline void dma_cache_sync(void *vaddr, size_t size, +static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction dir) { /* we use coherent allocation, so not much to do here. */ diff --git a/include/asm-mips/dma-mapping.h b/include/asm-mips/dma-mapping.h index e17f70d7b70..236d1a467cc 100644 --- a/include/asm-mips/dma-mapping.h +++ b/include/asm-mips/dma-mapping.h @@ -65,7 +65,7 @@ dma_get_cache_alignment(void) extern int dma_is_consistent(struct device *dev, dma_addr_t dma_addr); -extern void dma_cache_sync(void *vaddr, size_t size, +extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction); #define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY diff --git a/include/asm-parisc/dma-mapping.h b/include/asm-parisc/dma-mapping.h index c40d48afdc5..66f0b408c66 100644 --- a/include/asm-parisc/dma-mapping.h +++ b/include/asm-parisc/dma-mapping.h @@ -197,7 +197,7 @@ dma_is_consistent(struct device *dev, dma_addr_t dma_addr) } static inline void -dma_cache_sync(void *vaddr, size_t size, +dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { if(hppa_dma_ops->dma_sync_single_for_cpu) diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h index 3cf635b53b8..7c7de87bd8a 100644 --- a/include/asm-powerpc/dma-mapping.h +++ b/include/asm-powerpc/dma-mapping.h @@ -378,7 +378,7 @@ static inline void dma_sync_single_range_for_device(struct device *dev, dma_sync_single_for_device(dev, dma_handle, offset + size, direction); } -static inline void dma_cache_sync(void *vaddr, size_t size, +static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h index 56cd4b97723..37ab0c131a4 100644 --- a/include/asm-sh/dma-mapping.h +++ b/include/asm-sh/dma-mapping.h @@ -53,7 +53,7 @@ static inline void dma_free_coherent(struct device *dev, size_t size, consistent_free(vaddr, size); } -static inline void dma_cache_sync(void *vaddr, size_t size, +static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction dir) { consistent_sync(vaddr, size, (int)dir); diff --git a/include/asm-sh64/dma-mapping.h b/include/asm-sh64/dma-mapping.h index 68e27a8fca3..5efe906c59f 100644 --- a/include/asm-sh64/dma-mapping.h +++ b/include/asm-sh64/dma-mapping.h @@ -35,7 +35,7 @@ static inline void dma_free_coherent(struct device *dev, size_t size, consistent_free(NULL, size, vaddr, dma_handle); } -static inline void dma_cache_sync(void *vaddr, size_t size, +static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction dir) { dma_cache_wback_inv((unsigned long)vaddr, size); diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h index 5fe0072f3f8..2f858a2df94 100644 --- a/include/asm-sparc64/dma-mapping.h +++ b/include/asm-sparc64/dma-mapping.h @@ -210,7 +210,7 @@ dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, } static inline void -dma_cache_sync(void *vaddr, size_t size, +dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { /* could define this in terms of the dma_cache ... operations, diff --git a/include/asm-um/dma-mapping.h b/include/asm-um/dma-mapping.h index defb5b8307d..f0ee4fb5591 100644 --- a/include/asm-um/dma-mapping.h +++ b/include/asm-um/dma-mapping.h @@ -112,7 +112,7 @@ dma_sync_single_range(struct device *dev, dma_addr_t dma_handle, } static inline void -dma_cache_sync(void *vaddr, size_t size, +dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { BUG(); diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h index c8cc4887fba..be9ec689072 100644 --- a/include/asm-x86_64/dma-mapping.h +++ b/include/asm-x86_64/dma-mapping.h @@ -185,7 +185,8 @@ static inline int dma_get_cache_alignment(void) extern int dma_set_mask(struct device *dev, u64 mask); static inline void -dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction dir) +dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction dir) { flush_write_buffers(); } diff --git a/include/asm-xtensa/dma-mapping.h b/include/asm-xtensa/dma-mapping.h index 827d1dfd9e1..82b03b3a2ee 100644 --- a/include/asm-xtensa/dma-mapping.h +++ b/include/asm-xtensa/dma-mapping.h @@ -173,7 +173,7 @@ dma_get_cache_alignment(void) #define dma_is_consistent(d, h) (1) static inline void -dma_cache_sync(void *vaddr, size_t size, +dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { consistent_sync(vaddr, size, direction); -- cgit v1.2.3-70-g09d2 From 7d1362c0d05b8543807ab403ac8ce813cab41fa4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 6 Dec 2006 20:40:38 -0800 Subject: [PATCH] cleanup asm/setup.h userspace visibility Make the contents of the userspace asm/setup.h header consistent on all architectures: - export setup.h to userspace on all architectures - export only COMMAND_LINE_SIZE to userspace - frv: move COMMAND_LINE_SIZE from param.h - i386: remove duplicate COMMAND_LINE_SIZE from param.h - arm: - export ATAGs to userspace - change u8/u16/u32 to __u8/__u16/__u32 Signed-off-by: Adrian Bunk Acked-by: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-arm/setup.h | 104 ++++++++++++++++++++++------------------- include/asm-arm26/setup.h | 4 ++ include/asm-avr32/setup.h | 4 ++ include/asm-frv/param.h | 1 - include/asm-frv/setup.h | 6 +++ include/asm-generic/Kbuild.asm | 1 + include/asm-i386/Kbuild | 1 - include/asm-i386/param.h | 1 - include/asm-i386/setup.h | 6 ++- include/asm-ia64/Kbuild | 1 - include/asm-m32r/setup.h | 9 +++- include/asm-m68k/setup.h | 6 ++- include/asm-m68knommu/setup.h | 5 ++ include/asm-mips/setup.h | 2 - include/asm-powerpc/setup.h | 3 -- include/asm-s390/setup.h | 3 +- include/asm-sh/setup.h | 6 ++- include/asm-sh64/setup.h | 6 +++ include/asm-x86_64/Kbuild | 1 - 19 files changed, 102 insertions(+), 68 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-arm/setup.h b/include/asm-arm/setup.h index aa4b5782f0c..e5407392afc 100644 --- a/include/asm-arm/setup.h +++ b/include/asm-arm/setup.h @@ -14,55 +14,57 @@ #ifndef __ASMARM_SETUP_H #define __ASMARM_SETUP_H +#include + #define COMMAND_LINE_SIZE 1024 /* The list ends with an ATAG_NONE node. */ #define ATAG_NONE 0x00000000 struct tag_header { - u32 size; - u32 tag; + __u32 size; + __u32 tag; }; /* The list must start with an ATAG_CORE node */ #define ATAG_CORE 0x54410001 struct tag_core { - u32 flags; /* bit 0 = read-only */ - u32 pagesize; - u32 rootdev; + __u32 flags; /* bit 0 = read-only */ + __u32 pagesize; + __u32 rootdev; }; /* it is allowed to have multiple ATAG_MEM nodes */ #define ATAG_MEM 0x54410002 struct tag_mem32 { - u32 size; - u32 start; /* physical start address */ + __u32 size; + __u32 start; /* physical start address */ }; /* VGA text type displays */ #define ATAG_VIDEOTEXT 0x54410003 struct tag_videotext { - u8 x; - u8 y; - u16 video_page; - u8 video_mode; - u8 video_cols; - u16 video_ega_bx; - u8 video_lines; - u8 video_isvga; - u16 video_points; + __u8 x; + __u8 y; + __u16 video_page; + __u8 video_mode; + __u8 video_cols; + __u16 video_ega_bx; + __u8 video_lines; + __u8 video_isvga; + __u16 video_points; }; /* describes how the ramdisk will be used in kernel */ #define ATAG_RAMDISK 0x54410004 struct tag_ramdisk { - u32 flags; /* bit 0 = load, bit 1 = prompt */ - u32 size; /* decompressed ramdisk size in _kilo_ bytes */ - u32 start; /* starting block of floppy-based RAM disk image */ + __u32 flags; /* bit 0 = load, bit 1 = prompt */ + __u32 size; /* decompressed ramdisk size in _kilo_ bytes */ + __u32 start; /* starting block of floppy-based RAM disk image */ }; /* describes where the compressed ramdisk image lives (virtual address) */ @@ -76,23 +78,23 @@ struct tag_ramdisk { #define ATAG_INITRD2 0x54420005 struct tag_initrd { - u32 start; /* physical start address */ - u32 size; /* size of compressed ramdisk image in bytes */ + __u32 start; /* physical start address */ + __u32 size; /* size of compressed ramdisk image in bytes */ }; /* board serial number. "64 bits should be enough for everybody" */ #define ATAG_SERIAL 0x54410006 struct tag_serialnr { - u32 low; - u32 high; + __u32 low; + __u32 high; }; /* board revision */ #define ATAG_REVISION 0x54410007 struct tag_revision { - u32 rev; + __u32 rev; }; /* initial values for vesafb-type framebuffers. see struct screen_info @@ -101,20 +103,20 @@ struct tag_revision { #define ATAG_VIDEOLFB 0x54410008 struct tag_videolfb { - u16 lfb_width; - u16 lfb_height; - u16 lfb_depth; - u16 lfb_linelength; - u32 lfb_base; - u32 lfb_size; - u8 red_size; - u8 red_pos; - u8 green_size; - u8 green_pos; - u8 blue_size; - u8 blue_pos; - u8 rsvd_size; - u8 rsvd_pos; + __u16 lfb_width; + __u16 lfb_height; + __u16 lfb_depth; + __u16 lfb_linelength; + __u32 lfb_base; + __u32 lfb_size; + __u8 red_size; + __u8 red_pos; + __u8 green_size; + __u8 green_pos; + __u8 blue_size; + __u8 blue_pos; + __u8 rsvd_size; + __u8 rsvd_pos; }; /* command line: \0 terminated string */ @@ -128,17 +130,17 @@ struct tag_cmdline { #define ATAG_ACORN 0x41000101 struct tag_acorn { - u32 memc_control_reg; - u32 vram_pages; - u8 sounddefault; - u8 adfsdrives; + __u32 memc_control_reg; + __u32 vram_pages; + __u8 sounddefault; + __u8 adfsdrives; }; /* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */ #define ATAG_MEMCLK 0x41000402 struct tag_memclk { - u32 fmemclk; + __u32 fmemclk; }; struct tag { @@ -167,24 +169,26 @@ struct tag { }; struct tagtable { - u32 tag; + __u32 tag; int (*parse)(const struct tag *); }; -#define __tag __attribute_used__ __attribute__((__section__(".taglist.init"))) -#define __tagtable(tag, fn) \ -static struct tagtable __tagtable_##fn __tag = { tag, fn } - #define tag_member_present(tag,member) \ ((unsigned long)(&((struct tag *)0L)->member + 1) \ <= (tag)->hdr.size * 4) -#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size)) +#define tag_next(t) ((struct tag *)((__u32 *)(t) + (t)->hdr.size)) #define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2) #define for_each_tag(t,base) \ for (t = base; t->hdr.size; t = tag_next(t)) +#ifdef __KERNEL__ + +#define __tag __attribute_used__ __attribute__((__section__(".taglist.init"))) +#define __tagtable(tag, fn) \ +static struct tagtable __tagtable_##fn __tag = { tag, fn } + /* * Memory map description */ @@ -217,4 +221,6 @@ struct early_params { static struct early_params __early_##fn __attribute_used__ \ __attribute__((__section__(".early_param.init"))) = { name, fn } +#endif /* __KERNEL__ */ + #endif diff --git a/include/asm-arm26/setup.h b/include/asm-arm26/setup.h index 6348931be65..1a867b4e8d5 100644 --- a/include/asm-arm26/setup.h +++ b/include/asm-arm26/setup.h @@ -16,6 +16,8 @@ #define COMMAND_LINE_SIZE 1024 +#ifdef __KERNEL__ + /* The list ends with an ATAG_NONE node. */ #define ATAG_NONE 0x00000000 @@ -202,4 +204,6 @@ struct meminfo { extern struct meminfo meminfo; +#endif /* __KERNEL__ */ + #endif diff --git a/include/asm-avr32/setup.h b/include/asm-avr32/setup.h index 10193da4113..0a5224245e4 100644 --- a/include/asm-avr32/setup.h +++ b/include/asm-avr32/setup.h @@ -13,6 +13,8 @@ #define COMMAND_LINE_SIZE 256 +#ifdef __KERNEL__ + /* Magic number indicating that a tag table is present */ #define ATAG_MAGIC 0xa2a25441 @@ -138,4 +140,6 @@ void chip_enable_sdram(void); #endif /* !__ASSEMBLY__ */ +#endif /* __KERNEL__ */ + #endif /* __ASM_AVR32_SETUP_H__ */ diff --git a/include/asm-frv/param.h b/include/asm-frv/param.h index 168381ebb41..365653b1726 100644 --- a/include/asm-frv/param.h +++ b/include/asm-frv/param.h @@ -18,6 +18,5 @@ #endif #define MAXHOSTNAMELEN 64 /* max length of hostname */ -#define COMMAND_LINE_SIZE 512 #endif /* _ASM_PARAM_H */ diff --git a/include/asm-frv/setup.h b/include/asm-frv/setup.h index 0d293b9a585..afd787ceede 100644 --- a/include/asm-frv/setup.h +++ b/include/asm-frv/setup.h @@ -12,6 +12,10 @@ #ifndef _ASM_SETUP_H #define _ASM_SETUP_H +#define COMMAND_LINE_SIZE 512 + +#ifdef __KERNEL__ + #include #ifndef __ASSEMBLY__ @@ -22,4 +26,6 @@ extern unsigned long __initdata num_mappedpages; #endif /* !__ASSEMBLY__ */ +#endif /* __KERNEL__ */ + #endif /* _ASM_SETUP_H */ diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm index a84c3d88a18..a37e95fe58d 100644 --- a/include/asm-generic/Kbuild.asm +++ b/include/asm-generic/Kbuild.asm @@ -14,6 +14,7 @@ unifdef-y += posix_types.h unifdef-y += ptrace.h unifdef-y += resource.h unifdef-y += sembuf.h +unifdef-y += setup.h unifdef-y += shmbuf.h unifdef-y += sigcontext.h unifdef-y += siginfo.h diff --git a/include/asm-i386/Kbuild b/include/asm-i386/Kbuild index 147e4ac1ebf..5ae93afc67e 100644 --- a/include/asm-i386/Kbuild +++ b/include/asm-i386/Kbuild @@ -7,5 +7,4 @@ header-y += ptrace-abi.h header-y += ucontext.h unifdef-y += mtrr.h -unifdef-y += setup.h unifdef-y += vm86.h diff --git a/include/asm-i386/param.h b/include/asm-i386/param.h index 745dc5bd0fb..21b32466fcd 100644 --- a/include/asm-i386/param.h +++ b/include/asm-i386/param.h @@ -18,6 +18,5 @@ #endif #define MAXHOSTNAMELEN 64 /* max length of hostname */ -#define COMMAND_LINE_SIZE 256 #endif diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h index 2734909eff8..c5b504bfbaa 100644 --- a/include/asm-i386/setup.h +++ b/include/asm-i386/setup.h @@ -6,6 +6,8 @@ #ifndef _i386_SETUP_H #define _i386_SETUP_H +#define COMMAND_LINE_SIZE 256 + #ifdef __KERNEL__ #include @@ -14,10 +16,8 @@ */ #define MAXMEM_PFN PFN_DOWN(MAXMEM) #define MAX_NONPAE_PFN (1 << 20) -#endif #define PARAM_SIZE 4096 -#define COMMAND_LINE_SIZE 256 #define OLD_CL_MAGIC_ADDR 0x90020 #define OLD_CL_MAGIC 0xA33F @@ -78,4 +78,6 @@ void __init add_memory_region(unsigned long long start, #endif /* __ASSEMBLY__ */ +#endif /* __KERNEL__ */ + #endif /* _i386_SETUP_H */ diff --git a/include/asm-ia64/Kbuild b/include/asm-ia64/Kbuild index 15818a18bc5..4a1e48b9f40 100644 --- a/include/asm-ia64/Kbuild +++ b/include/asm-ia64/Kbuild @@ -10,7 +10,6 @@ header-y += intrinsics.h header-y += perfmon_default_smpl.h header-y += ptrace_offsets.h header-y += rse.h -header-y += setup.h header-y += ucontext.h unifdef-y += perfmon.h diff --git a/include/asm-m32r/setup.h b/include/asm-m32r/setup.h index 52f4fa29abf..6a0b32202d4 100644 --- a/include/asm-m32r/setup.h +++ b/include/asm-m32r/setup.h @@ -1,6 +1,11 @@ /* * This is set up by the setup-routine at boot-time */ + +#define COMMAND_LINE_SIZE 512 + +#ifdef __KERNEL__ + #define PARAM ((unsigned char *)empty_zero_page) #define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000)) @@ -18,8 +23,6 @@ #define SCREEN_INFO (*(struct screen_info *) (PARAM+0x200)) -#define COMMAND_LINE_SIZE (512) - #define RAMDISK_IMAGE_START_MASK (0x07FF) #define RAMDISK_PROMPT_FLAG (0x8000) #define RAMDISK_LOAD_FLAG (0x4000) @@ -27,3 +30,5 @@ extern unsigned long memory_start; extern unsigned long memory_end; +#endif /* __KERNEL__ */ + diff --git a/include/asm-m68k/setup.h b/include/asm-m68k/setup.h index 7facc9a46e7..2a8853cd655 100644 --- a/include/asm-m68k/setup.h +++ b/include/asm-m68k/setup.h @@ -41,8 +41,12 @@ #define MACH_Q40 10 #define MACH_SUN3X 11 +#define COMMAND_LINE_SIZE 256 + #ifdef __KERNEL__ +#define CL_SIZE COMMAND_LINE_SIZE + #ifndef __ASSEMBLY__ extern unsigned long m68k_machtype; #endif /* !__ASSEMBLY__ */ @@ -355,8 +359,6 @@ extern int m68k_is040or060; */ #define NUM_MEMINFO 4 -#define CL_SIZE 256 -#define COMMAND_LINE_SIZE CL_SIZE #ifndef __ASSEMBLY__ struct mem_info { diff --git a/include/asm-m68knommu/setup.h b/include/asm-m68knommu/setup.h index d2b0fcce41b..fb86bb2a607 100644 --- a/include/asm-m68knommu/setup.h +++ b/include/asm-m68knommu/setup.h @@ -1,5 +1,10 @@ +#ifdef __KERNEL__ + #include /* We have a bigger command line buffer. */ #undef COMMAND_LINE_SIZE + +#endif /* __KERNEL__ */ + #define COMMAND_LINE_SIZE 512 diff --git a/include/asm-mips/setup.h b/include/asm-mips/setup.h index 737fa4a6912..70009a90263 100644 --- a/include/asm-mips/setup.h +++ b/include/asm-mips/setup.h @@ -1,8 +1,6 @@ -#ifdef __KERNEL__ #ifndef _MIPS_SETUP_H #define _MIPS_SETUP_H #define COMMAND_LINE_SIZE 256 #endif /* __SETUP_H */ -#endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/setup.h b/include/asm-powerpc/setup.h index 3d9740aae01..817fac0a071 100644 --- a/include/asm-powerpc/setup.h +++ b/include/asm-powerpc/setup.h @@ -1,9 +1,6 @@ #ifndef _ASM_POWERPC_SETUP_H #define _ASM_POWERPC_SETUP_H -#ifdef __KERNEL__ - #define COMMAND_LINE_SIZE 512 -#endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_SETUP_H */ diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h index 7664bacdd83..9574fe80a04 100644 --- a/include/asm-s390/setup.h +++ b/include/asm-s390/setup.h @@ -8,12 +8,13 @@ #ifndef _ASM_S390_SETUP_H #define _ASM_S390_SETUP_H +#define COMMAND_LINE_SIZE 896 + #ifdef __KERNEL__ #include #define PARMAREA 0x10400 -#define COMMAND_LINE_SIZE 896 #define MEMORY_CHUNKS 16 /* max 0x7fff */ #define IPL_PARMBLOCK_ORIGIN 0x2000 diff --git a/include/asm-sh/setup.h b/include/asm-sh/setup.h index 34ca8a7f06b..1583c6b7bda 100644 --- a/include/asm-sh/setup.h +++ b/include/asm-sh/setup.h @@ -1,10 +1,12 @@ -#ifdef __KERNEL__ #ifndef _SH_SETUP_H #define _SH_SETUP_H #define COMMAND_LINE_SIZE 256 +#ifdef __KERNEL__ + int setup_early_printk(char *); -#endif /* _SH_SETUP_H */ #endif /* __KERNEL__ */ + +#endif /* _SH_SETUP_H */ diff --git a/include/asm-sh64/setup.h b/include/asm-sh64/setup.h index ebd42eb1b70..5b07b14c292 100644 --- a/include/asm-sh64/setup.h +++ b/include/asm-sh64/setup.h @@ -1,6 +1,10 @@ #ifndef __ASM_SH64_SETUP_H #define __ASM_SH64_SETUP_H +#define COMMAND_LINE_SIZE 256 + +#ifdef __KERNEL__ + #define PARAM ((unsigned char *)empty_zero_page) #define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000)) #define RAMDISK_FLAGS (*(unsigned long *) (PARAM+0x004)) @@ -12,5 +16,7 @@ #define COMMAND_LINE ((char *) (PARAM+256)) #define COMMAND_LINE_SIZE 256 +#endif /* __KERNEL__ */ + #endif /* __ASM_SH64_SETUP_H */ diff --git a/include/asm-x86_64/Kbuild b/include/asm-x86_64/Kbuild index 1ee9b07f3fe..763521358fb 100644 --- a/include/asm-x86_64/Kbuild +++ b/include/asm-x86_64/Kbuild @@ -12,7 +12,6 @@ header-y += ldt.h header-y += msr.h header-y += prctl.h header-y += ptrace-abi.h -header-y += setup.h header-y += sigcontext32.h header-y += ucontext.h header-y += vsyscall32.h -- cgit v1.2.3-70-g09d2 From 04da6af960194ecdee4c29cd3f86e766903418ca Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 5 Dec 2006 17:52:37 +1100 Subject: [POWERPC] Move pSeries_mach_cpu_die() into platforms/pseries/hotplug-cpu.c Move pSeries_mach_cpu_die() into platforms/pseries/hotplug-cpu.c, this allows rtas_stop_self() to be static so remove the prototype. Wire up pSeries_mach_cpu_die() in the initcall, rather than statically in setup.c, the initcall will still run prior to the cpu hotplug code being callable, so there should be no change in behaviour. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/hotplug-cpu.c | 18 ++++++++++++++++-- arch/powerpc/platforms/pseries/setup.c | 16 ---------------- include/asm-powerpc/rtas.h | 2 -- 3 files changed, 16 insertions(+), 20 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 6e21ebdfcef..9e9b6b159fa 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -1,7 +1,8 @@ /* * pseries CPU Hotplug infrastructure. * - * Split out from arch/powerpc/kernel/rtas.c + * Split out from arch/powerpc/platforms/pseries/setup.c and + * arch/powerpc/kernel/rtas.c * * Peter Bergner, IBM March 2001. * Copyright (C) 2001 IBM. @@ -34,7 +35,7 @@ static struct rtas_args rtas_stop_self_args = { .rets = &rtas_stop_self_args.args[0], }; -void rtas_stop_self(void) +static void rtas_stop_self(void) { struct rtas_args *args = &rtas_stop_self_args; @@ -49,10 +50,23 @@ void rtas_stop_self(void) panic("Alas, I survived.\n"); } +static void pSeries_mach_cpu_die(void) +{ + local_irq_disable(); + idle_task_exit(); + xics_teardown_cpu(0); + rtas_stop_self(); + /* Should never get here... */ + BUG(); + for(;;); +} + static int __init pseries_cpu_hotplug_init(void) { rtas_stop_self_args.token = rtas_token("stop-self"); + ppc_md.cpu_die = pSeries_mach_cpu_die; + return 0; } arch_initcall(pseries_cpu_hotplug_init); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 0dc2548ca9b..6090d753c44 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -347,21 +347,6 @@ static int __init pSeries_init_panel(void) } arch_initcall(pSeries_init_panel); -#ifdef CONFIG_HOTPLUG_CPU -static void pSeries_mach_cpu_die(void) -{ - local_irq_disable(); - idle_task_exit(); - xics_teardown_cpu(0); - rtas_stop_self(); - /* Should never get here... */ - BUG(); - for(;;); -} -#else -#define pSeries_mach_cpu_die NULL -#endif - static int pseries_set_dabr(unsigned long dabr) { return plpar_hcall_norets(H_SET_DABR, dabr); @@ -561,7 +546,6 @@ define_machine(pseries) { .power_off = rtas_power_off, .halt = rtas_halt, .panic = rtas_os_term, - .cpu_die = pSeries_mach_cpu_die, .get_boot_time = rtas_get_boot_time, .get_rtc_time = rtas_get_rtc_time, .set_rtc_time = rtas_set_rtc_time, diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index 5a0c136c041..031ef57fb19 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h @@ -221,8 +221,6 @@ extern int rtas_get_error_log_max(void); extern spinlock_t rtas_data_buf_lock; extern char rtas_data_buf[RTAS_DATA_BUF_SIZE]; -extern void rtas_stop_self(void); - /* RMO buffer reserved for user-space RTAS use */ extern unsigned long rtas_rmo_buf; -- cgit v1.2.3-70-g09d2 From be9575af7e8ec9040330f57b974e52d6921c08bb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 5 Dec 2006 23:30:16 +0100 Subject: [POWERPC] cell: Fix spu_info.h header export It uses #ifdef __KERNEL__, so needs to be processed with unifdef. Signed-off-by: Arnd Bergann Acked-by: Geoff Levand Signed-off-by: Paul Mackerras --- include/asm-powerpc/Kbuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild index 1e637381c11..703970fb0ec 100644 --- a/include/asm-powerpc/Kbuild +++ b/include/asm-powerpc/Kbuild @@ -17,7 +17,6 @@ header-y += ipc.h header-y += poll.h header-y += shmparam.h header-y += sockios.h -header-y += spu_info.h header-y += ucontext.h header-y += ioctl.h header-y += linkage.h @@ -37,6 +36,7 @@ unifdef-y += posix_types.h unifdef-y += ptrace.h unifdef-y += seccomp.h unifdef-y += signal.h +unifdef-y += spu_info.h unifdef-y += termios.h unifdef-y += types.h unifdef-y += unistd.h -- cgit v1.2.3-70-g09d2 From 1d4454e7ce30239e67b154ae08f6d906b9737334 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 6 Dec 2006 15:15:38 -0800 Subject: [POWERPC] Define pci_unmap_addr() et al. when CONFIG_NOT_COHERENT_CACHE=y The current PowerPC code makes pci_unmap_addr(), pci_unmap_addr_set(), and friends trivial for all 32-bit kernels. This is reasonable, since for those kernels it is true that pci_unmap_single() does not need the DMA address from the original DMA mapping -- in fact, it is a NOP. However, I recently tried the tg3 driver on a PowerPC 440SPe machine, which runs a 32-bit kernel and has non-cache-coherent PCI DMA. I found that the tg3 driver crashed in pci_dma_sync_single_for_cpu(), since for non-coherent systems, that function must invalidate the cache for the DMA address range requested, and therefore it does use the address passed in. tg3 uses a DMA address it stashes away with pci_unmap_addr_set() and retrieves with pci_unmap_addr(). Of course, since pci_unmap_addr() is defined to (0) right now, this doesn't work. It seems to me that the tg3 driver is using pci_unmap_addr() in a legitimate way -- I wouldn't want to have to teach all drivers that they should use pci_unmap_addr() if they only need the address for unmapping functions, but if they want the pci_dma_sync functions, then they have to store the DMA address without the helper macros. The right fix therefore seems to be in the definition of the macros in -- we should use the trivial versions only for 32-bit kernels for coherent systems, and the real versions for both 64-bit kernels and non-coherent systems. Signed-off-by: Roland Dreier Signed-off-by: Paul Mackerras --- include/asm-powerpc/pci.h | 33 ++++++++++++++++++++++----------- include/asm-ppc/pci.h | 23 +++++++++++++++++++++++ 2 files changed, 45 insertions(+), 11 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index 16f13319c76..ac656ee6bb1 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h @@ -143,8 +143,13 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ #define HAVE_PCI_MMAP 1 -#ifdef CONFIG_PPC64 -/* pci_unmap_{single,page} is not a nop, thus... */ +#if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE) +/* + * For 64-bit kernels, pci_unmap_{single,page} is not a nop. + * For 32-bit non-coherent kernels, pci_dma_sync_single_for_cpu() and + * so on are not nops. + * and thus... + */ #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ dma_addr_t ADDR_NAME; #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ @@ -158,6 +163,20 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ (((PTR)->LEN_NAME) = (VAL)) +#else /* 32-bit && coherent */ + +/* pci_unmap_{page,single} is a nop so... */ +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) +#define pci_unmap_addr(PTR, ADDR_NAME) (0) +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) +#define pci_unmap_len(PTR, LEN_NAME) (0) +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) + +#endif /* CONFIG_PPC64 || CONFIG_NOT_COHERENT_CACHE */ + +#ifdef CONFIG_PPC64 + /* The PCI address space does not equal the physical memory address * space (we have an IOMMU). The IDE and SCSI device layers use * this boolean for bounce buffer decisions. @@ -172,16 +191,8 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, */ #define PCI_DMA_BUS_IS_PHYS (1) -/* pci_unmap_{page,single} is a nop so... */ -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) -#define pci_unmap_addr(PTR, ADDR_NAME) (0) -#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) -#define pci_unmap_len(PTR, LEN_NAME) (0) -#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) - #endif /* CONFIG_PPC64 */ - + extern void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res); diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h index 11ffaaa5da1..9d162028dab 100644 --- a/include/asm-ppc/pci.h +++ b/include/asm-ppc/pci.h @@ -61,6 +61,27 @@ extern unsigned long pci_bus_to_phys(unsigned int ba, int busnr); */ #define PCI_DMA_BUS_IS_PHYS (1) +#ifdef CONFIG_NOT_COHERENT_CACHE +/* + * pci_unmap_{page,single} are NOPs but pci_dma_sync_single_for_cpu() + * and so on are not, so... + */ + +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ + dma_addr_t ADDR_NAME; +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ + __u32 LEN_NAME; +#define pci_unmap_addr(PTR, ADDR_NAME) \ + ((PTR)->ADDR_NAME) +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ + (((PTR)->ADDR_NAME) = (VAL)) +#define pci_unmap_len(PTR, LEN_NAME) \ + ((PTR)->LEN_NAME) +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ + (((PTR)->LEN_NAME) = (VAL)) + +#else /* coherent */ + /* pci_unmap_{page,single} is a nop so... */ #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) @@ -69,6 +90,8 @@ extern unsigned long pci_bus_to_phys(unsigned int ba, int busnr); #define pci_unmap_len(PTR, LEN_NAME) (0) #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) +#endif /* CONFIG_NOT_COHERENT_CACHE */ + #ifdef CONFIG_PCI static inline void pci_dma_burst_advice(struct pci_dev *pdev, enum pci_dma_burst_strategy *strat, -- cgit v1.2.3-70-g09d2 From 3a1d1ac279fac16ab1b41b2868478f3085f9223c Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 5 Dec 2006 22:15:05 -0700 Subject: [POWERPC] Delete unused irq functions on powerpc The ack_irq macro is unused and conflicts with James' work to template the generic irq code. mask_irq and unmask_irq are also unused, so delete those macros too. Signed-off-by: Matthew Wilcox Signed-off-by: Paul Mackerras --- include/asm-powerpc/hw_irq.h | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h index d604863d72f..9e4dd98eb22 100644 --- a/include/asm-powerpc/hw_irq.h +++ b/include/asm-powerpc/hw_irq.h @@ -107,25 +107,6 @@ static inline void local_irq_save_ptr(unsigned long *flags) #endif /* CONFIG_PPC64 */ -#define mask_irq(irq) \ - ({ \ - irq_desc_t *desc = get_irq_desc(irq); \ - if (desc->chip && desc->chip->disable) \ - desc->chip->disable(irq); \ - }) -#define unmask_irq(irq) \ - ({ \ - irq_desc_t *desc = get_irq_desc(irq); \ - if (desc->chip && desc->chip->enable) \ - desc->chip->enable(irq); \ - }) -#define ack_irq(irq) \ - ({ \ - irq_desc_t *desc = get_irq_desc(irq); \ - if (desc->chip && desc->chip->ack) \ - desc->chip->ack(irq); \ - }) - /* * interrupt-retrigger: should we handle this via lost interrupts and IPIs * or should we not care like we do now ? --BenH. -- cgit v1.2.3-70-g09d2 From f2d6d2d8bb4e9bb4aef225c149e42cac3ac3d4d0 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Wed, 6 Dec 2006 18:50:45 -0600 Subject: [POWERPC] Add rtas_service_present() helper To test for the existence of an RTAS function, we typically do: foo_token = rtas_token("foo"); if (foo_token == RTAS_UNKNOWN_SERVICE) return; Add a rtas_service_present method, which provides a more conventional boolean interface for testing the existence of an RTAS method. Signed-off-by: Nathan Lynch Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 6 ++++++ include/asm-powerpc/rtas.h | 1 + 2 files changed, 7 insertions(+) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 952f4c2fc1e..76b5d7ebdcc 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -303,6 +303,12 @@ int rtas_token(const char *service) } EXPORT_SYMBOL(rtas_token); +int rtas_service_present(const char *service) +{ + return rtas_token(service) != RTAS_UNKNOWN_SERVICE; +} +EXPORT_SYMBOL(rtas_service_present); + #ifdef CONFIG_RTAS_ERROR_LOGGING /* * Return the firmware-specified size of the error log buffer diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index 031ef57fb19..8eaa7b28d9d 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h @@ -159,6 +159,7 @@ extern struct rtas_t rtas; extern void enter_rtas(unsigned long); extern int rtas_token(const char *service); +extern int rtas_service_present(const char *service); extern int rtas_call(int token, int, int, int *, ...); extern void rtas_restart(char *cmd); extern void rtas_power_off(void); -- cgit v1.2.3-70-g09d2 From 396a1a5832ae28ce2c4150f98827873cbef554f5 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 8 Dec 2006 17:14:33 +1100 Subject: [POWERPC] Fix mmap of PCI resource with hack for X The powerpc version of pci_resource_to_user() and associated hooks used by /proc/bus/pci and /sys/bus/pci mmap have been broken for some time on machines that don't have a 1:1 mapping of devices (basically on non-PowerMacs) and have PCI devices above 32 bits. This attempts to fix it as well as possible. The rule is supposed to be that pci_resource_to_user() always converts the resources back into a BAR values since that's what the /proc interface was supposed to deal with. However, for X to work on platforms where PCI MMIO is not mapped 1:1, it became a habit of platforms like powerpc to pass "fixed up" values there since X expects to be able to use values from /proc/bus/pci/devices as offsets to mmap of /dev/mem... So we keep that contraption here, causing also /sys/*/resource to expose fully absolute MMIO addresses instead of BAR values, which is ugly, but should still work as long as those are only used to calculate alignment within a page. X is still broken when built 32 bits on machines where PCI MMIO can be above 32-bit space unfortunately. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_32.c | 45 ++++++++++++++++++++++++++++------------ arch/powerpc/kernel/pci_64.c | 42 +++++++++++++++++++++++++++---------- arch/ppc/kernel/pci.c | 41 ++++++++++++++++++++++++++++-------- include/asm-powerpc/pci-bridge.h | 4 ++-- include/asm-ppc/pci-bridge.h | 8 +++---- 5 files changed, 101 insertions(+), 39 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 2f54cd81dea..ab5887bff02 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -1544,7 +1544,7 @@ pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, - unsigned long *offset, + resource_size_t *offset, enum pci_mmap_state mmap_state) { struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); @@ -1556,7 +1556,9 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, /* If memory, add on the PCI bridge address offset */ if (mmap_state == pci_mmap_mem) { +#if 0 /* See comment in pci_resource_to_user() for why this is disabled */ *offset += hose->pci_mem_offset; +#endif res_bit = IORESOURCE_MEM; } else { io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE; @@ -1624,9 +1626,6 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, else prot |= _PAGE_GUARDED; - printk("PCI map for %s:%llx, prot: %lx\n", pci_name(dev), - (unsigned long long)rp->start, prot); - return __pgprot(prot); } @@ -1695,7 +1694,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine) { - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; struct resource *rp; int ret; @@ -1808,22 +1807,42 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar, resource_size_t *start, resource_size_t *end) { struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); - unsigned long offset = 0; + resource_size_t offset = 0; if (hose == NULL) return; if (rsrc->flags & IORESOURCE_IO) - offset = (void __iomem *)_IO_BASE - hose->io_base_virt - + hose->io_base_phys; + offset = (unsigned long)hose->io_base_virt - _IO_BASE; + + /* We pass a fully fixed up address to userland for MMIO instead of + * a BAR value because X is lame and expects to be able to use that + * to pass to /dev/mem ! + * + * That means that we'll have potentially 64 bits values where some + * userland apps only expect 32 (like X itself since it thinks only + * Sparc has 64 bits MMIO) but if we don't do that, we break it on + * 32 bits CHRPs :-( + * + * Hopefully, the sysfs insterface is immune to that gunk. Once X + * has been fixed (and the fix spread enough), we can re-enable the + * 2 lines below and pass down a BAR value to userland. In that case + * we'll also have to re-enable the matching code in + * __pci_mmap_make_offset(). + * + * BenH. + */ +#if 0 + else if (rsrc->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; +#endif - *start = rsrc->start + offset; - *end = rsrc->end + offset; + *start = rsrc->start - offset; + *end = rsrc->end - offset; } -void __init -pci_init_resource(struct resource *res, unsigned long start, unsigned long end, - int flags, char *name) +void __init pci_init_resource(struct resource *res, resource_size_t start, + resource_size_t end, int flags, char *name) { res->start = start; res->end = end; diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 6fa9a0a5c8d..a6b7692c726 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -682,7 +682,7 @@ int pci_proc_domain(struct pci_bus *bus) * Returns negative error code on failure, zero on success. */ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, - unsigned long *offset, + resource_size_t *offset, enum pci_mmap_state mmap_state) { struct pci_controller *hose = pci_bus_to_host(dev->bus); @@ -694,7 +694,9 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, /* If memory, add on the PCI bridge address offset */ if (mmap_state == pci_mmap_mem) { +#if 0 /* See comment in pci_resource_to_user() for why this is disabled */ *offset += hose->pci_mem_offset; +#endif res_bit = IORESOURCE_MEM; } else { io_offset = (unsigned long)hose->io_base_virt - pci_io_base; @@ -762,9 +764,6 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, else prot |= _PAGE_GUARDED; - printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, - prot); - return __pgprot(prot); } @@ -832,7 +831,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file, int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine) { - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; struct resource *rp; int ret; @@ -1333,20 +1332,41 @@ EXPORT_SYMBOL(pci_read_irq_line); void pci_resource_to_user(const struct pci_dev *dev, int bar, const struct resource *rsrc, - u64 *start, u64 *end) + resource_size_t *start, resource_size_t *end) { struct pci_controller *hose = pci_bus_to_host(dev->bus); - unsigned long offset = 0; + resource_size_t offset = 0; if (hose == NULL) return; if (rsrc->flags & IORESOURCE_IO) - offset = pci_io_base - (unsigned long)hose->io_base_virt + - hose->io_base_phys; + offset = (unsigned long)hose->io_base_virt - pci_io_base; + + /* We pass a fully fixed up address to userland for MMIO instead of + * a BAR value because X is lame and expects to be able to use that + * to pass to /dev/mem ! + * + * That means that we'll have potentially 64 bits values where some + * userland apps only expect 32 (like X itself since it thinks only + * Sparc has 64 bits MMIO) but if we don't do that, we break it on + * 32 bits CHRPs :-( + * + * Hopefully, the sysfs insterface is immune to that gunk. Once X + * has been fixed (and the fix spread enough), we can re-enable the + * 2 lines below and pass down a BAR value to userland. In that case + * we'll also have to re-enable the matching code in + * __pci_mmap_make_offset(). + * + * BenH. + */ +#if 0 + else if (rsrc->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; +#endif - *start = rsrc->start + offset; - *end = rsrc->end + offset; + *start = rsrc->start - offset; + *end = rsrc->end - offset; } struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 63808e01cb0..5e723c4c257 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -879,7 +879,7 @@ pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, - unsigned long *offset, + resource_size_t *offset, enum pci_mmap_state mmap_state) { struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); @@ -891,7 +891,9 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, /* If memory, add on the PCI bridge address offset */ if (mmap_state == pci_mmap_mem) { +#if 0 /* See comment in pci_resource_to_user() for why this is disabled */ *offset += hose->pci_mem_offset; +#endif res_bit = IORESOURCE_MEM; } else { io_offset = hose->io_base_virt - ___IO_BASE; @@ -1030,7 +1032,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine) { - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; struct resource *rp; int ret; @@ -1132,21 +1134,42 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar, resource_size_t *start, resource_size_t *end) { struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); - unsigned long offset = 0; + resource_size_t offset = 0; if (hose == NULL) return; if (rsrc->flags & IORESOURCE_IO) - offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys; + offset = (unsigned long)hose->io_base_virt - _IO_BASE; + + /* We pass a fully fixed up address to userland for MMIO instead of + * a BAR value because X is lame and expects to be able to use that + * to pass to /dev/mem ! + * + * That means that we'll have potentially 64 bits values where some + * userland apps only expect 32 (like X itself since it thinks only + * Sparc has 64 bits MMIO) but if we don't do that, we break it on + * 32 bits CHRPs :-( + * + * Hopefully, the sysfs insterface is immune to that gunk. Once X + * has been fixed (and the fix spread enough), we can re-enable the + * 2 lines below and pass down a BAR value to userland. In that case + * we'll also have to re-enable the matching code in + * __pci_mmap_make_offset(). + * + * BenH. + */ +#if 0 + else if (rsrc->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; +#endif - *start = rsrc->start + offset; - *end = rsrc->end + offset; + *start = rsrc->start - offset; + *end = rsrc->end - offset; } -void __init -pci_init_resource(struct resource *res, unsigned long start, unsigned long end, - int flags, char *name) +void __init pci_init_resource(struct resource *res, resource_size_t start, + resource_size_t end, int flags, char *name) { res->start = start; res->end = end; diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index 7bb7f900980..cb02c9d1ef9 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h @@ -31,12 +31,12 @@ struct pci_controller { int last_busno; void __iomem *io_base_virt; - unsigned long io_base_phys; + resource_size_t io_base_phys; /* Some machines have a non 1:1 mapping of * the PCI memory space in the CPU bus space */ - unsigned long pci_mem_offset; + resource_size_t pci_mem_offset; unsigned long pci_io_size; struct pci_ops *ops; diff --git a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h index 6c955d0c1ef..4d35b844bc5 100644 --- a/include/asm-ppc/pci-bridge.h +++ b/include/asm-ppc/pci-bridge.h @@ -20,8 +20,8 @@ extern unsigned long pci_bus_mem_base_phys(unsigned int bus); extern struct pci_controller* pcibios_alloc_controller(void); /* Helper function for setting up resources */ -extern void pci_init_resource(struct resource *res, unsigned long start, - unsigned long end, int flags, char *name); +extern void pci_init_resource(struct resource *res, resource_size_t start, + resource_size_t end, int flags, char *name); /* Get the PCI host controller for a bus */ extern struct pci_controller* pci_bus_to_hose(int bus); @@ -50,12 +50,12 @@ struct pci_controller { int bus_offset; void __iomem *io_base_virt; - unsigned long io_base_phys; + resource_size_t io_base_phys; /* Some machines (PReP) have a non 1:1 mapping of * the PCI memory space in the CPU bus space */ - unsigned long pci_mem_offset; + resource_size_t pci_mem_offset; struct pci_ops *ops; volatile unsigned int __iomem *cfg_addr; -- cgit v1.2.3-70-g09d2 From aa42c69c67f82e88f0726258efe7306708e1cf14 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Fri, 8 Dec 2006 02:43:30 -0600 Subject: [POWERPC] Add support for FP emulation for the e300c2 core The e300c2 has no FPU. Its MSR[FP] is grounded to zero. If an attempt is made to execute a floating point instruction (including floating-point load, store, or move instructions), the e300c2 takes a floating-point unavailable interrupt. This patch adds support for FP emulation on the e300c2 by declaring a new CPU_FTR_FP_TAKES_FPUNAVAIL, where FP unavail interrupts are intercepted and redirected to the ProgramCheck exception path for correct emulation handling. (If we run out of CPU_FTR bits we could look to reclaim this bit by adding support to test the cpu_user_features for PPC_FEATURE_HAS_FPU instead) It adds a nop to the exception path for 32-bit processors with a FPU. Signed-off-by: Kim Phillips Signed-off-by: Kumar Gala --- arch/powerpc/Kconfig | 2 +- arch/powerpc/kernel/cputable.c | 2 +- arch/powerpc/kernel/head_32.S | 7 +++++++ arch/powerpc/kernel/traps.c | 2 ++ include/asm-powerpc/cputable.h | 10 ++++++++-- 5 files changed, 19 insertions(+), 4 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 291c95ac4b3..0b2d05da89d 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -706,7 +706,7 @@ config FORCE_MAX_ZONEORDER config MATH_EMULATION bool "Math emulation" - depends on 4xx || 8xx || E200 || E500 + depends on 4xx || 8xx || E200 || PPC_83xx || E500 ---help--- Some PowerPC chips designed for embedded applications do not have a floating-point unit and therefore do not implement the diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 9d1614c3ce6..11bfbaf655b 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -833,7 +833,7 @@ static struct cpu_spec cpu_specs[] = { .pvr_mask = 0x7fff0000, .pvr_value = 0x00840000, .cpu_name = "e300c2", - .cpu_features = CPU_FTRS_E300, + .cpu_features = CPU_FTRS_E300C2, .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index d88e182e40b..9417cf5b4b7 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S @@ -437,6 +437,13 @@ Alignment: /* Floating-point unavailable */ . = 0x800 FPUnavailable: +BEGIN_FTR_SECTION +/* + * Certain Freescale cores don't have a FPU and treat fp instructions + * as a FP Unavailable exception. Redirect to illegal/emulation handling. + */ + b ProgramCheck +END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE) EXCEPTION_PROLOG bne load_up_fpu /* if from user, just load it up */ addi r3,r1,STACK_FRAME_OVERHEAD diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 0d4e203fa7a..fde820e52d0 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -782,6 +782,8 @@ void __kprobes program_check_exception(struct pt_regs *regs) unsigned int reason = get_reason(regs); extern int do_mathemu(struct pt_regs *regs); + /* We can now get here via a FP Unavailable exception if the core + * has no FPU, in that case no reason flags will be set */ #ifdef CONFIG_MATH_EMULATION /* (reason & REASON_ILLEGAL) would be the obvious thing here, * but there seems to be a hardware bug on the 405GP (RevD) diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 6fe5c9d4ca3..aca72f90849 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -126,6 +126,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000) #define CPU_FTR_PPC_LE ASM_CONST(0x0000000000200000) #define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000) +#define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000) /* * Add the 64-bit processor unique features in the top half of the word; @@ -295,6 +296,9 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTRS_E300 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \ CPU_FTR_COMMON) +#define CPU_FTRS_E300C2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ + CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \ + CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE) #define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE) #define CPU_FTRS_8XX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB) @@ -364,7 +368,8 @@ enum { CPU_FTRS_7450_21 | CPU_FTRS_7450_23 | CPU_FTRS_7455_1 | CPU_FTRS_7455_20 | CPU_FTRS_7455 | CPU_FTRS_7447_10 | CPU_FTRS_7447 | CPU_FTRS_7447A | CPU_FTRS_82XX | - CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_CLASSIC32 | + CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_E300C2 | + CPU_FTRS_CLASSIC32 | #else CPU_FTRS_GENERIC_32 | #endif @@ -403,7 +408,8 @@ enum { CPU_FTRS_7450_21 & CPU_FTRS_7450_23 & CPU_FTRS_7455_1 & CPU_FTRS_7455_20 & CPU_FTRS_7455 & CPU_FTRS_7447_10 & CPU_FTRS_7447 & CPU_FTRS_7447A & CPU_FTRS_82XX & - CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_CLASSIC32 & + CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_E300C2 & + CPU_FTRS_CLASSIC32 & #else CPU_FTRS_GENERIC_32 & #endif -- cgit v1.2.3-70-g09d2 From ef55d53caa055aedee13e77da82740987dd64f2d Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 8 Dec 2006 02:37:53 -0800 Subject: [PATCH] LOG2: Provide ilog2() fallbacks for powerpc Provide ilog2() fallbacks for powerpc for 32-bit numbers and 64-bit numbers on ppc64. Signed-off-by: David Howells Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/Kconfig | 4 ++-- include/asm-powerpc/bitops.h | 21 ++++++++++++++++++++- include/asm-powerpc/page_32.h | 10 +--------- 3 files changed, 23 insertions(+), 12 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 97c7a212cdd..56c3c4065eb 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -43,11 +43,11 @@ config RWSEM_XCHGADD_ALGORITHM config ARCH_HAS_ILOG2_U32 bool - default n + default y config ARCH_HAS_ILOG2_U64 bool - default n + default y if 64BIT config GENERIC_HWEIGHT bool diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h index c341063d080..0288144ea02 100644 --- a/include/asm-powerpc/bitops.h +++ b/include/asm-powerpc/bitops.h @@ -190,7 +190,8 @@ static __inline__ void set_bits(unsigned long mask, unsigned long *addr) * Return the zero-based bit position (LE, not IBM bit numbering) of * the most significant 1-bit in a double word. */ -static __inline__ int __ilog2(unsigned long x) +static __inline__ __attribute__((const)) +int __ilog2(unsigned long x) { int lz; @@ -198,6 +199,24 @@ static __inline__ int __ilog2(unsigned long x) return BITS_PER_LONG - 1 - lz; } +static inline __attribute__((const)) +int __ilog2_u32(u32 n) +{ + int bit; + asm ("cntlzw %0,%1" : "=r" (bit) : "r" (n)); + return 31 - bit; +} + +#ifdef __powerpc64__ +static inline __attribute__((const)) +int __ilog2_u64(u32 n) +{ + int bit; + asm ("cntlzd %0,%1" : "=r" (bit) : "r" (n)); + return 63 - bit; +} +#endif + /* * Determines the bit position of the least significant 0 bit in the * specified double word. The returned bit position will be diff --git a/include/asm-powerpc/page_32.h b/include/asm-powerpc/page_32.h index 2677bad70f4..07f6d3cf5e5 100644 --- a/include/asm-powerpc/page_32.h +++ b/include/asm-powerpc/page_32.h @@ -26,15 +26,7 @@ extern void clear_pages(void *page, int order); static inline void clear_page(void *page) { clear_pages(page, 0); } extern void copy_page(void *to, void *from); -/* Pure 2^n version of get_order */ -extern __inline__ int get_order(unsigned long size) -{ - int lz; - - size = (size-1) >> PAGE_SHIFT; - asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size)); - return 32 - lz; -} +#include #endif /* __ASSEMBLY__ */ -- cgit v1.2.3-70-g09d2 From be90038a24c814dc98bc5a813f41855779000018 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 8 Dec 2006 02:38:43 -0800 Subject: [PATCH] tty: preparatory structures for termios revamp In order to sort out our struct termios and add proper speed control we need to separate the kernel and user termios structures. Glibc is fine but the other libraries rely on the kernel exported struct termios and we need to extend this without breaking the ABI/API To do so we add a struct ktermios which is the kernel view of a termios structure and overlaps the struct termios with extra fields on the end for now. (That limitation will go away in later patches). Some platforms (eg alpha) planned ahead and thus use the same struct for both, others did not. This just adds the structures but does not use them, it seems a sensible splitting point for bisect if there are compile failures (not that I expect them) Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/wireless/strip.c | 2 +- include/asm-alpha/termbits.h | 13 +++++++++++++ include/asm-arm/termbits.h | 12 ++++++++++++ include/asm-arm26/termbits.h | 12 ++++++++++++ include/asm-avr32/termbits.h | 11 +++++++++++ include/asm-cris/termbits.h | 11 +++++++++++ include/asm-frv/termbits.h | 11 +++++++++++ include/asm-h8300/termbits.h | 11 +++++++++++ include/asm-i386/termbits.h | 11 +++++++++++ include/asm-ia64/termbits.h | 11 +++++++++++ include/asm-m32r/termbits.h | 11 +++++++++++ include/asm-m68k/termbits.h | 11 +++++++++++ include/asm-mips/termbits.h | 11 +++++++++++ include/asm-parisc/termbits.h | 11 +++++++++++ include/asm-powerpc/termbits.h | 13 +++++++++++++ include/asm-s390/termbits.h | 11 +++++++++++ include/asm-sh/termbits.h | 11 +++++++++++ include/asm-sparc/termbits.h | 12 ++++++++++++ include/asm-sparc64/termbits.h | 12 ++++++++++++ include/asm-v850/termbits.h | 11 +++++++++++ include/asm-x86_64/termbits.h | 11 +++++++++++ 21 files changed, 229 insertions(+), 1 deletion(-) (limited to 'include/asm-powerpc') diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 337c692f6fd..ce3a8bac66f 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -798,7 +798,7 @@ static unsigned int get_baud(struct tty_struct *tty) */ static void set_baud(struct tty_struct *tty, unsigned int baudcode) { - struct termios old_termios = *(tty->termios); + struct ktermios old_termios = *(tty->termios); tty->termios->c_cflag &= ~CBAUD; /* Clear the old baud setting */ tty->termios->c_cflag |= baudcode; /* Set the new baud setting */ tty->driver->set_termios(tty, &old_termios); diff --git a/include/asm-alpha/termbits.h b/include/asm-alpha/termbits.h index 5541101b58a..ad854a4a3af 100644 --- a/include/asm-alpha/termbits.h +++ b/include/asm-alpha/termbits.h @@ -25,6 +25,19 @@ struct termios { speed_t c_ospeed; /* output speed */ }; +/* Alpha has matching termios and ktermios */ + +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t c_line; /* line discipline (== c_cc[19]) */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VEOF 0 #define VEOL 1 diff --git a/include/asm-arm/termbits.h b/include/asm-arm/termbits.h index bbc6e1d24d3..a3f4fe1742d 100644 --- a/include/asm-arm/termbits.h +++ b/include/asm-arm/termbits.h @@ -15,6 +15,18 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-arm26/termbits.h b/include/asm-arm26/termbits.h index bbc6e1d24d3..a3f4fe1742d 100644 --- a/include/asm-arm26/termbits.h +++ b/include/asm-arm26/termbits.h @@ -15,6 +15,18 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-avr32/termbits.h b/include/asm-avr32/termbits.h index 9dc6eacafa3..c215fafdae4 100644 --- a/include/asm-avr32/termbits.h +++ b/include/asm-avr32/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h index be0836d2f28..8d8cec225fe 100644 --- a/include/asm-cris/termbits.h +++ b/include/asm-cris/termbits.h @@ -19,6 +19,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-frv/termbits.h b/include/asm-frv/termbits.h index 74f20d6e292..2d6d389cff4 100644 --- a/include/asm-frv/termbits.h +++ b/include/asm-frv/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-h8300/termbits.h b/include/asm-h8300/termbits.h index fa69ae00eda..6a1f4d3807b 100644 --- a/include/asm-h8300/termbits.h +++ b/include/asm-h8300/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-i386/termbits.h b/include/asm-i386/termbits.h index 72c10e3190f..12baf1d6343 100644 --- a/include/asm-i386/termbits.h +++ b/include/asm-i386/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-ia64/termbits.h b/include/asm-ia64/termbits.h index b9e843f7dc4..4531a511bde 100644 --- a/include/asm-ia64/termbits.h +++ b/include/asm-ia64/termbits.h @@ -26,6 +26,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h index 5ace3702df7..faf2bd0504c 100644 --- a/include/asm-m32r/termbits.h +++ b/include/asm-m32r/termbits.h @@ -19,6 +19,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-m68k/termbits.h b/include/asm-m68k/termbits.h index e9eec3eb071..a194092240f 100644 --- a/include/asm-m68k/termbits.h +++ b/include/asm-m68k/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-mips/termbits.h b/include/asm-mips/termbits.h index b62ec7c521c..0bbe07b42a0 100644 --- a/include/asm-mips/termbits.h +++ b/include/asm-mips/termbits.h @@ -30,6 +30,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 /* Interrupt character [ISIG]. */ #define VQUIT 1 /* Quit character [ISIG]. */ diff --git a/include/asm-parisc/termbits.h b/include/asm-parisc/termbits.h index 372b634892c..a46e299a939 100644 --- a/include/asm-parisc/termbits.h +++ b/include/asm-parisc/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h index 6d533b07aaf..b572f21b32c 100644 --- a/include/asm-powerpc/termbits.h +++ b/include/asm-powerpc/termbits.h @@ -30,6 +30,19 @@ struct termios { speed_t c_ospeed; /* output speed */ }; +/* For PowerPC the termios and ktermios are the same */ + +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-s390/termbits.h b/include/asm-s390/termbits.h index eb3f8bfabf6..585c78a6e40 100644 --- a/include/asm-s390/termbits.h +++ b/include/asm-s390/termbits.h @@ -25,6 +25,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-sh/termbits.h b/include/asm-sh/termbits.h index 4f9822a8e7b..f1b7b46f4e9 100644 --- a/include/asm-sh/termbits.h +++ b/include/asm-sh/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-sparc/termbits.h b/include/asm-sparc/termbits.h index 1794d71134b..5eb00a105d7 100644 --- a/include/asm-sparc/termbits.h +++ b/include/asm-sparc/termbits.h @@ -31,6 +31,18 @@ struct termios { #endif }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t _x_cc[2]; /* We need them to hold vmin/vtime */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-sparc64/termbits.h b/include/asm-sparc64/termbits.h index b07715273ed..705cd44b417 100644 --- a/include/asm-sparc64/termbits.h +++ b/include/asm-sparc64/termbits.h @@ -33,6 +33,18 @@ struct termios { #endif }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t _x_cc[2]; /* We need them to hold vmin/vtime */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-v850/termbits.h b/include/asm-v850/termbits.h index 212d4e27926..f3b43303208 100644 --- a/include/asm-v850/termbits.h +++ b/include/asm-v850/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 diff --git a/include/asm-x86_64/termbits.h b/include/asm-x86_64/termbits.h index bd950946e52..f31918cea51 100644 --- a/include/asm-x86_64/termbits.h +++ b/include/asm-x86_64/termbits.h @@ -17,6 +17,17 @@ struct termios { cc_t c_cc[NCCS]; /* control characters */ }; +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 -- cgit v1.2.3-70-g09d2 From 606d099cdd1080bbb50ea50dc52d98252f8f10a1 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 8 Dec 2006 02:38:45 -0800 Subject: [PATCH] tty: switch to ktermios This is the grungy swap all the occurrences in the right places patch that goes with the updates. At this point we have the same functionality as before (except that sgttyb() returns speeds not zero) and are ready to begin turning new stuff on providing nobody reports lots of bugs If you are a tty driver author converting an out of tree driver the only impact should be termios->ktermios name changes for the speed/property setting functions from your upper layers. If you are implementing your own TCGETS function before then your driver was broken already and its about to get a whole lot more painful for you so please fix it 8) Also fill in c_ispeed/ospeed on init for most devices, although the current code will do this for you anyway but I'd like eventually to lose that extra paranoia [akpm@osdl.org: bluetooth fix] [mp3@de.ibm.com: sclp fix] [mp3@de.ibm.com: warning fix for tty3270] [hugh@veritas.com: fix tty_ioctl powerpc build] [jdike@addtoit.com: uml: fix ->set_termios declaration] Signed-off-by: Alan Cox Signed-off-by: Martin Peschke Acked-by: Peter Oberparleiter Cc: Cornelia Huck Signed-off-by: Hugh Dickins Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/line.c | 2 +- arch/um/include/line.h | 2 +- drivers/char/amiserial.c | 6 +++--- drivers/char/cyclades.c | 2 +- drivers/char/epca.c | 16 +++++++++++----- drivers/char/esp.c | 2 +- drivers/char/generic_serial.c | 4 ++-- drivers/char/hvcs.c | 6 ++++-- drivers/char/hvsi.c | 2 ++ drivers/char/ip2/ip2main.c | 10 +++++----- drivers/char/isicom.c | 2 +- drivers/char/istallion.c | 14 ++++++++------ drivers/char/moxa.c | 18 ++++++++++-------- drivers/char/mxser.c | 18 ++++++++++-------- drivers/char/mxser_new.c | 8 ++++---- drivers/char/n_r3964.c | 4 ++-- drivers/char/n_tty.c | 2 +- drivers/char/pcmcia/synclink_cs.c | 2 +- drivers/char/pty.c | 10 +++++++++- drivers/char/riscom8.c | 4 +++- drivers/char/rocket.c | 8 +++++--- drivers/char/ser_a2232.c | 2 ++ drivers/char/serial167.c | 2 +- drivers/char/specialix.c | 9 +++++++-- drivers/char/stallion.c | 20 +++++++++++--------- drivers/char/sx.c | 2 ++ drivers/char/synclink.c | 4 +++- drivers/char/synclink_gt.c | 6 ++++-- drivers/char/synclinkmp.c | 6 ++++-- drivers/char/tty_ioctl.c | 4 ++-- drivers/char/vme_scc.c | 2 ++ drivers/isdn/capi/capi.c | 2 +- drivers/isdn/gigaset/interface.c | 4 ++-- drivers/isdn/i4l/isdn_tty.c | 2 +- drivers/net/irda/irtty-sir.c | 4 ++-- drivers/s390/char/sclp_tty.c | 2 -- drivers/s390/char/tty3270.c | 2 +- drivers/serial/21285.c | 4 ++-- drivers/serial/68328serial.c | 2 +- drivers/serial/68360serial.c | 2 +- drivers/serial/8250.c | 4 ++-- drivers/serial/amba-pl010.c | 4 ++-- drivers/serial/amba-pl011.c | 4 ++-- drivers/serial/atmel_serial.c | 2 +- drivers/serial/clps711x.c | 4 ++-- drivers/serial/crisv10.c | 8 +++++--- drivers/serial/crisv10.h | 4 ++-- drivers/serial/dz.c | 4 ++-- drivers/serial/icom.c | 4 ++-- drivers/serial/imx.c | 4 ++-- drivers/serial/ioc3_serial.c | 4 ++-- drivers/serial/ioc4_serial.c | 6 +++--- drivers/serial/ip22zilog.c | 4 ++-- drivers/serial/jsm/jsm_tty.c | 10 +++++----- drivers/serial/m32r_sio.c | 2 +- drivers/serial/mcfserial.c | 2 +- drivers/serial/mpc52xx_uart.c | 4 ++-- drivers/serial/mpsc.c | 4 ++-- drivers/serial/mux.c | 4 ++-- drivers/serial/netx-serial.c | 4 ++-- drivers/serial/pmac_zilog.c | 10 +++++----- drivers/serial/pmac_zilog.h | 2 +- drivers/serial/pxa.c | 4 ++-- drivers/serial/s3c2410.c | 4 ++-- drivers/serial/sa1100.c | 4 ++-- drivers/serial/serial_core.c | 21 +++++++++++---------- drivers/serial/serial_lh7a40x.c | 4 ++-- drivers/serial/serial_txx9.c | 4 ++-- drivers/serial/sh-sci.c | 4 ++-- drivers/serial/sn_console.c | 4 ++-- drivers/serial/sunhv.c | 4 ++-- drivers/serial/sunsab.c | 4 ++-- drivers/serial/sunsu.c | 4 ++-- drivers/serial/sunzilog.c | 4 ++-- drivers/serial/uartlite.c | 4 ++-- drivers/serial/v850e_uart.c | 4 ++-- drivers/serial/vr41xx_siu.c | 4 ++-- drivers/tc/zs.c | 2 +- drivers/usb/class/cdc-acm.c | 4 ++-- drivers/usb/gadget/serial.c | 4 ++-- drivers/usb/serial/ark3116.c | 4 ++-- drivers/usb/serial/belkin_sa.c | 4 ++-- drivers/usb/serial/console.c | 2 +- drivers/usb/serial/cp2101.c | 4 ++-- drivers/usb/serial/cypress_m8.c | 10 +++++----- drivers/usb/serial/digi_acceleport.c | 6 +++--- drivers/usb/serial/empeg.c | 4 ++-- drivers/usb/serial/ftdi_sio.c | 4 ++-- drivers/usb/serial/io_edgeport.c | 8 ++++---- drivers/usb/serial/io_ti.c | 6 +++--- drivers/usb/serial/ir-usb.c | 4 ++-- drivers/usb/serial/keyspan.c | 2 +- drivers/usb/serial/keyspan.h | 2 +- drivers/usb/serial/keyspan_pda.c | 2 +- drivers/usb/serial/kl5kusb105.c | 6 +++--- drivers/usb/serial/kobil_sct.c | 10 +++++----- drivers/usb/serial/mct_u232.c | 4 ++-- drivers/usb/serial/mos7720.c | 4 ++-- drivers/usb/serial/mos7840.c | 4 ++-- drivers/usb/serial/option.c | 4 ++-- drivers/usb/serial/pl2303.c | 4 ++-- drivers/usb/serial/sierra.c | 2 +- drivers/usb/serial/ti_usb_3410_5052.c | 4 ++-- drivers/usb/serial/usb-serial.c | 2 +- drivers/usb/serial/visor.c | 4 ++-- drivers/usb/serial/whiteheat.c | 6 +++--- include/asm-generic/termios.h | 4 ++-- include/asm-powerpc/termbits.h | 2 +- include/linux/generic_serial.h | 2 +- include/linux/isdn.h | 8 ++++---- include/linux/serial_core.h | 8 ++++---- include/linux/usb/serial.h | 2 +- net/bluetooth/rfcomm/tty.c | 4 ++-- 113 files changed, 301 insertions(+), 253 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index aa3090d05a8..83301e1ef67 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -246,7 +246,7 @@ out_up: return ret; } -void line_set_termios(struct tty_struct *tty, struct termios * old) +void line_set_termios(struct tty_struct *tty, struct ktermios * old) { /* nothing */ } diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 214ee76c40d..5f232ae89fb 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -76,7 +76,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines, extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); extern void line_put_char(struct tty_struct *tty, unsigned char ch); -extern void line_set_termios(struct tty_struct *tty, struct termios * old); +extern void line_set_termios(struct tty_struct *tty, struct ktermios * old); extern int line_chars_in_buffer(struct tty_struct *tty); extern void line_flush_buffer(struct tty_struct *tty); extern void line_flush_chars(struct tty_struct *tty); diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 66086fa2d59..feb4ac802a0 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -104,7 +104,7 @@ static struct async_struct *IRQ_ports; static unsigned char current_ctl_bits; -static void change_speed(struct async_struct *info, struct termios *old); +static void change_speed(struct async_struct *info, struct ktermios *old); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); @@ -694,7 +694,7 @@ static void shutdown(struct async_struct * info) * the specified baud rate for a serial port. */ static void change_speed(struct async_struct *info, - struct termios *old_termios) + struct ktermios *old_termios) { int quot = 0, baud_base, baud; unsigned cflag, cval = 0; @@ -1365,7 +1365,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct async_struct *info = (struct async_struct *)tty->driver_data; unsigned long flags; diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index acb2de5e3a9..3bb4e534c14 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -4101,7 +4101,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file, * where old == NULL, and try to do something rational. */ static void -cy_set_termios(struct tty_struct *tty, struct termios * old_termios) +cy_set_termios(struct tty_struct *tty, struct ktermios * old_termios) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 7c71eb77980..a0f822c9d74 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -199,7 +199,7 @@ static int pc_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static int info_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); -static void pc_set_termios(struct tty_struct *, struct termios *); +static void pc_set_termios(struct tty_struct *, struct ktermios *); static void do_softint(struct work_struct *work); static void pc_stop(struct tty_struct *); static void pc_start(struct tty_struct *); @@ -1236,6 +1236,8 @@ static int __init pc_init(void) pc_driver->init_termios.c_oflag = 0; pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; pc_driver->init_termios.c_lflag = 0; + pc_driver->init_termios.c_ispeed = 9600; + pc_driver->init_termios.c_ospeed = 9600; pc_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(pc_driver, &pc_ops); @@ -1250,6 +1252,8 @@ static int __init pc_init(void) pc_info->init_termios.c_oflag = 0; pc_info->init_termios.c_lflag = 0; pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; + pc_info->init_termios.c_ispeed = 9600; + pc_info->init_termios.c_ospeed = 9600; pc_info->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(pc_info, &info_ops); @@ -1999,7 +2003,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) { /* Begin epcaparam */ unsigned int cmdHead; - struct termios *ts; + struct ktermios *ts; struct board_chan __iomem *bc; unsigned mval, hflow, cflag, iflag; @@ -2114,7 +2118,7 @@ static void receive_data(struct channel *ch) { /* Begin receive_data */ unchar *rptr; - struct termios *ts = NULL; + struct ktermios *ts = NULL; struct tty_struct *tty; struct board_chan __iomem *bc; int dataToRead, wrapgap, bytesAvailable; @@ -2362,12 +2366,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, switch (cmd) { /* Begin switch cmd */ +#if 0 /* Handled by calling layer properly */ case TCGETS: - if (copy_to_user(argp, tty->termios, sizeof(struct termios))) + if (copy_to_user(argp, tty->termios, sizeof(struct ktermios))) return -EFAULT; return 0; case TCGETA: return get_termio(tty, argp); +#endif case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) @@ -2536,7 +2542,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, /* --------------------- Begin pc_set_termios ----------------------- */ -static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { /* Begin pc_set_termios */ struct channel *ch; diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 93b55196251..d1bfbaa2aa0 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -1915,7 +1915,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct esp_struct *info = (struct esp_struct *)tty->driver_data; unsigned long flags; diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 87127e49c0d..e769811e741 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -718,11 +718,11 @@ static unsigned int gs_baudrates[] = { void gs_set_termios (struct tty_struct * tty, - struct termios * old_termios) + struct ktermios * old_termios) { struct gs_port *port; int baudrate, tmp, rv; - struct termios *tiosp; + struct ktermios *tiosp; func_enter(); diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index d090622f1de..207f7343ba6 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -192,11 +192,13 @@ MODULE_VERSION(HVCS_DRIVER_VERSION); * that will cause echoing or we'll go into recursive loop echoing chars back * and forth with the console drivers. */ -static struct termios hvcs_tty_termios = { +static struct ktermios hvcs_tty_termios = { .c_iflag = IGNBRK | IGNPAR, .c_oflag = OPOST, .c_cflag = B38400 | CS8 | CREAD | HUPCL, - .c_cc = INIT_C_CC + .c_cc = INIT_C_CC, + .c_ispeed = 38400, + .c_ospeed = 38400 }; /* diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 82a41d5b4ed..d7806834fc1 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -1161,6 +1161,8 @@ static int __init hvsi_init(void) hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM; hvsi_driver->init_termios = tty_std_termios; hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; + hvsi_driver->init_termios.c_ispeed = 9600; + hvsi_driver->init_termios.c_ospeed = 9600; hvsi_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(hvsi_driver, &hvsi_ops); diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 6810b7bbcbb..7c70310a49b 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -177,7 +177,7 @@ static int ip2_write_room(PTTY); static int ip2_chars_in_buf(PTTY); static void ip2_flush_buffer(PTTY); static int ip2_ioctl(PTTY, struct file *, UINT, ULONG); -static void ip2_set_termios(PTTY, struct termios *); +static void ip2_set_termios(PTTY, struct ktermios *); static void ip2_set_line_discipline(PTTY); static void ip2_throttle(PTTY); static void ip2_unthrottle(PTTY); @@ -198,7 +198,7 @@ static void do_status(struct work_struct *); static void ip2_wait_until_sent(PTTY,int); -static void set_params (i2ChanStrPtr, struct termios *); +static void set_params (i2ChanStrPtr, struct ktermios *); static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *); static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); @@ -2398,7 +2398,7 @@ set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info ) /* */ /******************************************************************************/ static void -ip2_set_termios( PTTY tty, struct termios *old_termios ) +ip2_set_termios( PTTY tty, struct ktermios *old_termios ) { i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data; @@ -2440,11 +2440,11 @@ ip2_set_line_discipline ( PTTY tty ) /* change. */ /******************************************************************************/ static void -set_params( i2ChanStrPtr pCh, struct termios *o_tios ) +set_params( i2ChanStrPtr pCh, struct ktermios *o_tios ) { tcflag_t cflag, iflag, lflag; char stop_char, start_char; - struct termios dummy; + struct ktermios dummy; lflag = pCh->pTTY->termios->c_lflag; cflag = pCh->pTTY->termios->c_cflag; diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 1637c1d9a4b..29e28b75633 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1399,7 +1399,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp, /* set_termios et all */ static void isicom_set_termios(struct tty_struct *tty, - struct termios *old_termios) + struct ktermios *old_termios) { struct isi_port *port = tty->driver_data; diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index b6f0d036a76..0ef2523733e 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -194,9 +194,11 @@ static struct tty_struct *stli_txcooktty; * with this termios initially. Basically all it defines is a raw port * at 9600 baud, 8 data bits, no parity, 1 stop bit. */ -static struct termios stli_deftermios = { +static struct ktermios stli_deftermios = { .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), .c_cc = INIT_C_CC, + .c_ispeed = 9600, + .c_ospeed = 9600, }; /* @@ -639,7 +641,7 @@ static void stli_flushchars(struct tty_struct *tty); static int stli_writeroom(struct tty_struct *tty); static int stli_charsinbuffer(struct tty_struct *tty); static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void stli_settermios(struct tty_struct *tty, struct termios *old); +static void stli_settermios(struct tty_struct *tty, struct ktermios *old); static void stli_throttle(struct tty_struct *tty); static void stli_unthrottle(struct tty_struct *tty); static void stli_stop(struct tty_struct *tty); @@ -669,7 +671,7 @@ static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, v static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp); -static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp); +static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct ktermios *tiosp); static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts); static long stli_mktiocm(unsigned long sigvalue); static void stli_read(stlibrd_t *brdp, stliport_t *portp); @@ -1889,11 +1891,11 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm * Looks like it is true for the current ttys implementation..!! */ -static void stli_settermios(struct tty_struct *tty, struct termios *old) +static void stli_settermios(struct tty_struct *tty, struct ktermios *old) { stliport_t *portp; stlibrd_t *brdp; - struct termios *tiosp; + struct ktermios *tiosp; asyport_t aport; if (tty == NULL) @@ -2730,7 +2732,7 @@ static void stli_poll(unsigned long arg) * the slave. */ -static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp) +static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct ktermios *tiosp) { memset(pp, 0, sizeof(asyport_t)); diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 8b316953173..f391a24a1b4 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -234,7 +234,7 @@ static void moxa_put_char(struct tty_struct *, unsigned char); static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static void moxa_throttle(struct tty_struct *); static void moxa_unthrottle(struct tty_struct *); -static void moxa_set_termios(struct tty_struct *, struct termios *); +static void moxa_set_termios(struct tty_struct *, struct ktermios *); static void moxa_stop(struct tty_struct *); static void moxa_start(struct tty_struct *); static void moxa_hangup(struct tty_struct *); @@ -261,7 +261,7 @@ static void MoxaPortEnable(int); static void MoxaPortDisable(int); static long MoxaPortGetMaxBaud(int); static long MoxaPortSetBaud(int, long); -static int MoxaPortSetTermio(int, struct termios *, speed_t); +static int MoxaPortSetTermio(int, struct ktermios *, speed_t); static int MoxaPortGetLineOut(int, int *, int *); static void MoxaPortLineCtrl(int, int, int); static void MoxaPortFlowCtrl(int, int, int, int, int, int); @@ -355,6 +355,8 @@ static int __init moxa_init(void) moxaDriver->init_termios.c_oflag = 0; moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; moxaDriver->init_termios.c_lflag = 0; + moxaDriver->init_termios.c_ispeed = 9600; + moxaDriver->init_termios.c_ospeed = 9600; moxaDriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(moxaDriver, &moxa_ops); @@ -864,7 +866,7 @@ static void moxa_unthrottle(struct tty_struct *tty) } static void moxa_set_termios(struct tty_struct *tty, - struct termios *old_termios) + struct ktermios *old_termios) { struct moxa_str *ch = (struct moxa_str *) tty->driver_data; @@ -978,7 +980,7 @@ static void moxa_poll(unsigned long ignored) static void set_tty_param(struct tty_struct *tty) { - register struct termios *ts; + register struct ktermios *ts; struct moxa_str *ch; int rts, cts, txflow, rxflow, xany; @@ -1149,7 +1151,7 @@ static void shut_down(struct moxa_str *ch) static void receive_data(struct moxa_str *ch) { struct tty_struct *tp; - struct termios *ts; + struct ktermios *ts; unsigned long flags; ts = NULL; @@ -1912,9 +1914,9 @@ int MoxaPortsOfCard(int cardno) * * Function 12: Configure the port. * Syntax: - * int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud); + * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); * int port : port number (0 - 127) - * struct termios * termio : termio structure pointer + * struct ktermios * termio : termio structure pointer * speed_t baud : baud rate * * return: -1 : this port is invalid or termio == NULL @@ -2195,7 +2197,7 @@ long MoxaPortSetBaud(int port, long baud) return (baud); } -int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud) +int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud) { void __iomem *ofsAddr; tcflag_t cflag; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 2dc49be144e..c063359baf7 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -328,8 +328,8 @@ struct mxser_struct { int xmit_tail; int xmit_cnt; struct work_struct tqueue; - struct termios normal_termios; - struct termios callout_termios; + struct ktermios normal_termios; + struct ktermios callout_termios; wait_queue_head_t open_wait; wait_queue_head_t close_wait; wait_queue_head_t delta_msr_wait; @@ -364,8 +364,8 @@ static int mxserBoardCAP[MXSER_BOARDS] = { static struct tty_driver *mxvar_sdriver; static struct mxser_struct mxvar_table[MXSER_PORTS]; static struct tty_struct *mxvar_tty[MXSER_PORTS + 1]; -static struct termios *mxvar_termios[MXSER_PORTS + 1]; -static struct termios *mxvar_termios_locked[MXSER_PORTS + 1]; +static struct ktermios *mxvar_termios[MXSER_PORTS + 1]; +static struct ktermios *mxvar_termios_locked[MXSER_PORTS + 1]; static struct mxser_log mxvar_log; static int mxvar_diagflag; static unsigned char mxser_msr[MXSER_PORTS + 1]; @@ -402,7 +402,7 @@ static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong); static int mxser_ioctl_special(unsigned int, void __user *); static void mxser_throttle(struct tty_struct *); static void mxser_unthrottle(struct tty_struct *); -static void mxser_set_termios(struct tty_struct *, struct termios *); +static void mxser_set_termios(struct tty_struct *, struct ktermios *); static void mxser_stop(struct tty_struct *); static void mxser_start(struct tty_struct *); static void mxser_hangup(struct tty_struct *); @@ -414,7 +414,7 @@ static void mxser_check_modem_status(struct mxser_struct *, int); static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *); static int mxser_startup(struct mxser_struct *); static void mxser_shutdown(struct mxser_struct *); -static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios); +static int mxser_change_speed(struct mxser_struct *, struct ktermios *old_termios); static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct __user *); static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct __user *); static int mxser_get_lsr_info(struct mxser_struct *, unsigned int __user *); @@ -726,6 +726,8 @@ static int mxser_init(void) mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; mxvar_sdriver->init_termios = tty_std_termios; mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; + mxvar_sdriver->init_termios.c_ispeed = 9600; + mxvar_sdriver->init_termios.c_ospeed = 9600; mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(mxvar_sdriver, &mxser_ops); mxvar_sdriver->ttys = mxvar_tty; @@ -1749,7 +1751,7 @@ static void mxser_unthrottle(struct tty_struct *tty) /* MX_UNLOCK(&info->slock); */ } -static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mxser_struct *info = tty->driver_data; unsigned long flags; @@ -2541,7 +2543,7 @@ static void mxser_shutdown(struct mxser_struct *info) * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ -static int mxser_change_speed(struct mxser_struct *info, struct termios *old_termios) +static int mxser_change_speed(struct mxser_struct *info, struct ktermios *old_termios) { unsigned cflag, cval, fcr; int ret = 0; diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c index 369d2742d6b..efa8076c33e 100644 --- a/drivers/char/mxser_new.c +++ b/drivers/char/mxser_new.c @@ -266,8 +266,8 @@ struct mxser_port { int xmit_tail; int xmit_cnt; - struct termios normal_termios; - struct termios callout_termios; + struct ktermios normal_termios; + struct ktermios callout_termios; struct mxser_mon mon_data; @@ -512,7 +512,7 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) * the specified baud rate for a serial port. */ static int mxser_change_speed(struct mxser_port *info, - struct termios *old_termios) + struct ktermios *old_termios) { unsigned cflag, cval, fcr; int ret = 0; @@ -1966,7 +1966,7 @@ static void mxser_start(struct tty_struct *tty) spin_unlock_irqrestore(&info->slock, flags); } -static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mxser_port *info = tty->driver_data; unsigned long flags; diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 203dc2b661d..103d338f21e 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -142,7 +142,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, const unsigned char * buf, size_t nr); static int r3964_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); -static void r3964_set_termios(struct tty_struct *tty, struct termios * old); +static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old); static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, struct poll_table_struct *wait); static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, @@ -1347,7 +1347,7 @@ static int r3964_ioctl(struct tty_struct * tty, struct file * file, } } -static void r3964_set_termios(struct tty_struct *tty, struct termios * old) +static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old) { TRACE_L("set_termios"); } diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 603b9ade5eb..e96a00fe138 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -994,7 +994,7 @@ int is_ignored(int sig) * when the ldisc is closed. */ -static void n_tty_set_termios(struct tty_struct *tty, struct termios * old) +static void n_tty_set_termios(struct tty_struct *tty, struct ktermios * old) { if (!tty) return; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 74d21c1c104..5152cedd887 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -2375,7 +2375,7 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) * tty pointer to tty structure * termios pointer to buffer to hold returned old termios */ -static void mgslpc_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 80d3eedd7f9..c07a1b5cd05 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -218,7 +218,7 @@ out: return retval; } -static void pty_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { tty->termios->c_cflag &= ~(CSIZE | PARENB); tty->termios->c_cflag |= (CS8 | CREAD); @@ -272,6 +272,8 @@ static void __init legacy_pty_init(void) pty_driver->init_termios.c_oflag = 0; pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; pty_driver->init_termios.c_lflag = 0; + pty_driver->init_termios.c_ispeed = 38400; + pty_driver->init_termios.c_ospeed = 38400; pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW; pty_driver->other = pty_slave_driver; tty_set_operations(pty_driver, &pty_ops); @@ -286,6 +288,8 @@ static void __init legacy_pty_init(void) pty_slave_driver->subtype = PTY_TYPE_SLAVE; pty_slave_driver->init_termios = tty_std_termios; pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; + pty_slave_driver->init_termios.c_ispeed = 38400; + pty_slave_driver->init_termios.c_ospeed = 38400; pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW; pty_slave_driver->other = pty_driver; @@ -366,6 +370,8 @@ static void __init unix98_pty_init(void) ptm_driver->init_termios.c_oflag = 0; ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; ptm_driver->init_termios.c_lflag = 0; + ptm_driver->init_termios.c_ispeed = 38400; + ptm_driver->init_termios.c_ospeed = 38400; ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; ptm_driver->other = pts_driver; @@ -381,6 +387,8 @@ static void __init unix98_pty_init(void) pts_driver->subtype = PTY_TYPE_SLAVE; pts_driver->init_termios = tty_std_termios; pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; + pts_driver->init_termios.c_ispeed = 38400; + pts_driver->init_termios.c_ospeed = 38400; pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; pts_driver->other = ptm_driver; diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 0a77bfcd5b5..e2a94bfb2a4 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1539,7 +1539,7 @@ static void rc_hangup(struct tty_struct * tty) wake_up_interruptible(&port->open_wait); } -static void rc_set_termios(struct tty_struct * tty, struct termios * old_termios) +static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termios) { struct riscom_port *port = (struct riscom_port *)tty->driver_data; unsigned long flags; @@ -1614,6 +1614,8 @@ static inline int rc_init_drivers(void) riscom_driver->init_termios = tty_std_termios; riscom_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + riscom_driver->init_termios.c_ispeed = 9600; + riscom_driver->init_termios.c_ospeed = 9600; riscom_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(riscom_driver, &riscom_ops); if ((error = tty_register_driver(riscom_driver))) { diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 4fdf52e9f3b..e94a62e30fc 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -712,7 +712,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) * user mode into the driver (exception handler). *info CD manipulation is spinlock protected. */ static void configure_r_port(struct r_port *info, - struct termios *old_termios) + struct ktermios *old_termios) { unsigned cflag; unsigned long flags; @@ -1194,7 +1194,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) } static void rp_set_termios(struct tty_struct *tty, - struct termios *old_termios) + struct ktermios *old_termios) { struct r_port *info = (struct r_port *) tty->driver_data; CHANNEL_t *cp; @@ -2214,7 +2214,7 @@ static int __init init_PCI(int boards_found) int count = 0; /* Work through the PCI device list, pulling out ours */ - while ((dev = pci_find_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) { + while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) { if (register_PCI(count + boards_found, dev)) count++; } @@ -2436,6 +2436,8 @@ static int __init rp_init(void) rocket_driver->init_termios = tty_std_termios; rocket_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + rocket_driver->init_termios.c_ispeed = 9600; + rocket_driver->init_termios.c_ospeed = 9600; #ifdef ROCKET_SOFT_FLOW rocket_driver->flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; #endif diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 4217d38caef..75de5f66517 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c @@ -695,6 +695,8 @@ static int a2232_init_drivers(void) a2232_driver->init_termios = tty_std_termios; a2232_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + a2232_driver->init_termios.c_ispeed = 9600; + a2232_driver->init_termios.c_ospeed = 9600; a2232_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(a2232_driver, &a2232_ops); if ((error = tty_register_driver(a2232_driver))) { diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 9ba13af234b..af50d32ae2c 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1695,7 +1695,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file, static void -cy_set_termios(struct tty_struct *tty, struct termios * old_termios) +cy_set_termios(struct tty_struct *tty, struct ktermios * old_termios) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 99137ab66b6..20946f5127e 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -2311,7 +2311,7 @@ static void sx_hangup(struct tty_struct * tty) } -static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios) +static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; unsigned long flags; @@ -2400,6 +2400,8 @@ static int sx_init_drivers(void) specialix_driver->init_termios = tty_std_termios; specialix_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + specialix_driver->init_termios.c_ispeed = 9600; + specialix_driver->init_termios.c_ospeed = 9600; specialix_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(specialix_driver, &sx_ops); @@ -2475,7 +2477,7 @@ static int __init specialix_init(void) i++; continue; } - pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, + pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8, pdev); if (!pdev) break; @@ -2491,6 +2493,9 @@ static int __init specialix_init(void) if (!sx_probe(&sx_board[i])) found ++; } + /* May exit pci_get sequence early with lots of boards */ + if (pdev != NULL) + pci_dev_put(pdev); } #endif diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index a547c0c8fb2..71bfdccfb42 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -141,9 +141,11 @@ static struct tty_driver *stl_serial; * with this termios initially. Basically all it defines is a raw port * at 9600, 8 data bits, 1 stop bit. */ -static struct termios stl_deftermios = { +static struct ktermios stl_deftermios = { .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), .c_cc = INIT_C_CC, + .c_ispeed = 9600, + .c_ospeed = 9600, }; /* @@ -464,7 +466,7 @@ static int stl_cd1400getreg(struct stlport *portp, int regnr); static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value); static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp); static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); -static void stl_cd1400setport(struct stlport *portp, struct termios *tiosp); +static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp); static int stl_cd1400getsignals(struct stlport *portp); static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts); static void stl_cd1400ccrwait(struct stlport *portp); @@ -493,7 +495,7 @@ static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value); static int stl_sc26198getglobreg(struct stlport *portp, int regnr); static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp); static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); -static void stl_sc26198setport(struct stlport *portp, struct termios *tiosp); +static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp); static int stl_sc26198getsignals(struct stlport *portp); static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts); static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx); @@ -521,7 +523,7 @@ static void stl_sc26198otherisr(struct stlport *port, unsigned int iack); typedef struct uart { int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp); void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); - void (*setport)(struct stlport *portp, struct termios *tiosp); + void (*setport)(struct stlport *portp, struct ktermios *tiosp); int (*getsignals)(struct stlport *portp); void (*setsignals)(struct stlport *portp, int dtr, int rts); void (*enablerxtx)(struct stlport *portp, int rx, int tx); @@ -1427,10 +1429,10 @@ static void stl_start(struct tty_struct *tty) /*****************************************************************************/ -static void stl_settermios(struct tty_struct *tty, struct termios *old) +static void stl_settermios(struct tty_struct *tty, struct ktermios *old) { struct stlport *portp; - struct termios *tiosp; + struct ktermios *tiosp; pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old); @@ -2468,7 +2470,7 @@ static int __init stl_findpcibrds(void) pr_debug("stl_findpcibrds()\n"); for (i = 0; (i < stl_nrpcibrds); i++) - while ((dev = pci_find_device(stl_pcibrds[i].vendid, + while ((dev = pci_get_device(stl_pcibrds[i].vendid, stl_pcibrds[i].devid, dev))) { /* @@ -2947,7 +2949,7 @@ static void stl_cd1400ccrwait(struct stlport *portp) * settings. */ -static void stl_cd1400setport(struct stlport *portp, struct termios *tiosp) +static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp) { struct stlbrd *brdp; unsigned long flags; @@ -3924,7 +3926,7 @@ static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, st * settings. */ -static void stl_sc26198setport(struct stlport *portp, struct termios *tiosp) +static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp) { struct stlbrd *brdp; unsigned long flags; diff --git a/drivers/char/sx.c b/drivers/char/sx.c index cc10af08cb0..e9bc147c32f 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -2263,6 +2263,8 @@ static int sx_init_drivers(void) sx_driver->init_termios = tty_std_termios; sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + sx_driver->init_termios.c_ispeed = 9600; + sx_driver->init_termios.c_ospeed = 9600; sx_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(sx_driver, &sx_ops); diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 645187b9141..acc6fab601c 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -3060,7 +3060,7 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne * * Return Value: None */ -static void mgsl_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; unsigned long flags; @@ -4405,6 +4405,8 @@ static int mgsl_init_tty(void) serial_driver->init_termios = tty_std_termios; serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &mgsl_ops); if ((rc = tty_register_driver(serial_driver)) < 0) { diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index e4730a7312b..792c79c315e 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -151,7 +151,7 @@ static struct tty_driver *serial_driver; static int open(struct tty_struct *tty, struct file * filp); static void close(struct tty_struct *tty, struct file * filp); static void hangup(struct tty_struct *tty); -static void set_termios(struct tty_struct *tty, struct termios *old_termios); +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); static int write(struct tty_struct *tty, const unsigned char *buf, int count); static void put_char(struct tty_struct *tty, unsigned char ch); @@ -816,7 +816,7 @@ static void hangup(struct tty_struct *tty) wake_up_interruptible(&info->open_wait); } -static void set_termios(struct tty_struct *tty, struct termios *old_termios) +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct slgt_info *info = tty->driver_data; unsigned long flags; @@ -3546,6 +3546,8 @@ static int __init slgt_init(void) serial_driver->init_termios = tty_std_termios; serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &ops); if ((rc = tty_register_driver(serial_driver)) < 0) { diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 20a96ef250b..53e8ccf94fe 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -519,7 +519,7 @@ static struct tty_driver *serial_driver; static int open(struct tty_struct *tty, struct file * filp); static void close(struct tty_struct *tty, struct file * filp); static void hangup(struct tty_struct *tty); -static void set_termios(struct tty_struct *tty, struct termios *old_termios); +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); static int write(struct tty_struct *tty, const unsigned char *buf, int count); static void put_char(struct tty_struct *tty, unsigned char ch); @@ -918,7 +918,7 @@ static void hangup(struct tty_struct *tty) /* Set new termios settings */ -static void set_termios(struct tty_struct *tty, struct termios *old_termios) +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) { SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; unsigned long flags; @@ -4034,6 +4034,8 @@ static int __init synclinkmp_init(void) serial_driver->init_termios = tty_std_termios; serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &ops); if ((rc = tty_register_driver(serial_driver)) < 0) { diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 0ffba4e911c..30486df9fd3 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -495,8 +495,8 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) struct sgttyb tmp; mutex_lock(&tty->termios_mutex); - tmp.sg_ispeed = tty->c_ispeed; - tmp.sg_ospeed = tty->c_ospeed; + tmp.sg_ispeed = tty->termios->c_ispeed; + tmp.sg_ospeed = tty->termios->c_ospeed; tmp.sg_erase = tty->termios->c_cc[VERASE]; tmp.sg_kill = tty->termios->c_cc[VKILL]; tmp.sg_flags = get_sgflags(tty); diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index d0b94dd1af6..e01317cb1a0 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c @@ -153,6 +153,8 @@ static int scc_init_drivers(void) scc_driver->init_termios = tty_std_termios; scc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + scc_driver->init_termios.c_ispeed = 9600; + scc_driver->init_termios.c_ospeed = 9600; scc_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(scc_driver, &scc_ops); diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 787a630a8e5..0475a54df83 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1203,7 +1203,7 @@ static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file, return error; } -static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old) +static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_set_termios\n"); diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 7edea015867..458b6462f93 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -127,7 +127,7 @@ static int if_write_room(struct tty_struct *tty); static int if_chars_in_buffer(struct tty_struct *tty); static void if_throttle(struct tty_struct *tty); static void if_unthrottle(struct tty_struct *tty); -static void if_set_termios(struct tty_struct *tty, struct termios *old); +static void if_set_termios(struct tty_struct *tty, struct ktermios *old); static int if_tiocmget(struct tty_struct *tty, struct file *file); static int if_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); @@ -490,7 +490,7 @@ static void if_unthrottle(struct tty_struct *tty) mutex_unlock(&cs->mutex); } -static void if_set_termios(struct tty_struct *tty, struct termios *old) +static void if_set_termios(struct tty_struct *tty, struct ktermios *old) { struct cardstate *cs; unsigned int iflag; diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2b91bb07fc7..fc80afe555b 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1464,7 +1464,7 @@ isdn_tty_ioctl(struct tty_struct *tty, struct file *file, } static void -isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios) +isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { modem_info *info = (modem_info *) tty->driver_data; diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 6a98b7ae497..ad1857364d5 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -117,7 +117,7 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed) { struct sirtty_cb *priv = dev->priv; struct tty_struct *tty; - struct termios old_termios; + struct ktermios old_termios; int cflag; IRDA_ASSERT(priv != NULL, return -1;); @@ -318,7 +318,7 @@ static void irtty_write_wakeup(struct tty_struct *tty) static inline void irtty_stop_receiver(struct tty_struct *tty, int stop) { - struct termios old_termios; + struct ktermios old_termios; int cflag; lock_kernel(); diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 6f43e04dbef..2d173e5c8a0 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -60,8 +60,6 @@ static unsigned short int sclp_tty_chars_count; struct tty_driver *sclp_tty_driver; -extern struct termios tty_std_termios; - static struct sclp_ioctls sclp_ioctls; static struct sclp_ioctls sclp_ioctls_init = { diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 4717c361160..09844621edc 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -1659,7 +1659,7 @@ tty3270_flush_buffer(struct tty_struct *tty) * Check for visible/invisible input switches */ static void -tty3270_set_termios(struct tty_struct *tty, struct termios *old) +tty3270_set_termios(struct tty_struct *tty, struct ktermios *old) { struct tty3270 *tp; int new; diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 6a1a568ca64..facb6785561 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -214,8 +214,8 @@ static void serial21285_shutdown(struct uart_port *port) } static void -serial21285_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial21285_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned long flags; unsigned int baud, quot, h_lcr; diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 9b8b585513e..cad426c9711 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -1061,7 +1061,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 634ecca36a7..68817a7d8c0 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -1523,7 +1523,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file, /* FIX UP modem control here someday...... */ -static void rs_360_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { ser_info_t *info = (ser_info_t *)tty->driver_data; diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index e34bd03cfce..51f3c739f7e 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1763,8 +1763,8 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int } static void -serial8250_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial8250_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned char cval, fcr = 0; diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 4d3626ef464..61db6973755 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -345,8 +345,8 @@ static void pl010_shutdown(struct uart_port *port) } static void -pl010_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +pl010_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int lcr_h, old_cr; unsigned long flags; diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index d503625730d..9a3b374b2a0 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -412,8 +412,8 @@ static void pl011_shutdown(struct uart_port *port) } static void -pl011_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +pl011_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int lcr_h, old_cr; unsigned long flags; diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 9217ee6c786..ed7f7209ea5 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -478,7 +478,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, unsigned /* * Change the port parameters */ -static void atmel_set_termios(struct uart_port *port, struct termios * termios, struct termios * old) +static void atmel_set_termios(struct uart_port *port, struct ktermios * termios, struct ktermios * old) { unsigned long flags; unsigned int mode, imr, quot, baud; diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 59801271488..23827189ec0 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -286,8 +286,8 @@ static void clps711xuart_shutdown(struct uart_port *port) } static void -clps711xuart_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int ubrlcr, baud, quot; unsigned long flags; diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 7a24e53546c..42b050c46ab 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -804,8 +804,8 @@ static struct e100_serial rs_table[] = { #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial)) -static struct termios *serial_termios[NR_PORTS]; -static struct termios *serial_termios_locked[NR_PORTS]; +static struct ktermios *serial_termios[NR_PORTS]; +static struct ktermios *serial_termios_locked[NR_PORTS]; #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER static struct fast_timer fast_timers[NR_PORTS]; #endif @@ -4223,7 +4223,7 @@ rs_ioctl(struct tty_struct *tty, struct file * file, } static void -rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; @@ -4877,6 +4877,8 @@ rs_init(void) driver->init_termios = tty_std_termios; driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ + driver->init_termios.c_ispeed = 115200; + driver->init_termios.c_ospeed = 115200; driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; driver->termios = serial_termios; driver->termios_locked = serial_termios_locked; diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h index f30b93d6ef7..4a23340663a 100644 --- a/drivers/serial/crisv10.h +++ b/drivers/serial/crisv10.h @@ -93,8 +93,8 @@ struct e100_serial { struct work_struct work; struct async_icount icount; /* error-statistics etc.*/ - struct termios normal_termios; - struct termios callout_termios; + struct ktermios normal_termios; + struct ktermios callout_termios; #ifdef DECLARE_WAITQUEUE wait_queue_head_t open_wait; wait_queue_head_t close_wait; diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index af1544f3356..587d87b9eb3 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -461,8 +461,8 @@ static void dz_break_ctl(struct uart_port *uport, int break_state) spin_unlock_irqrestore(&uport->lock, flags); } -static void dz_set_termios(struct uart_port *uport, struct termios *termios, - struct termios *old_termios) +static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, + struct ktermios *old_termios) { struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index 8aa0f641866..7d623003e65 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -1087,8 +1087,8 @@ static void icom_close(struct uart_port *port) } static void icom_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old_termios) + struct ktermios *termios, + struct ktermios *old_termios) { int baud; unsigned cflag, iflag; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index ee5c782597d..e216dcf2937 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -459,8 +459,8 @@ static void imx_shutdown(struct uart_port *port) } static void -imx_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +imx_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct imx_port *sport = (struct imx_port *)port; unsigned long flags; diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 2308d26c862..9cc0be93231 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c @@ -950,7 +950,7 @@ static void transmit_chars(struct uart_port *the_port) */ static void ioc3_change_speed(struct uart_port *the_port, - struct termios *new_termios, struct termios *old_termios) + struct ktermios *new_termios, struct ktermios *old_termios) { struct ioc3_port *port = get_ioc3_port(the_port); unsigned int cflag; @@ -1853,7 +1853,7 @@ static int ic3_startup(struct uart_port *the_port) */ static void ic3_set_termios(struct uart_port *the_port, - struct termios *termios, struct termios *old_termios) + struct ktermios *termios, struct ktermios *old_termios) { unsigned long port_flags; diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 711bd151143..c862f67c985 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -1681,7 +1681,7 @@ static void transmit_chars(struct uart_port *the_port) */ static void ioc4_change_speed(struct uart_port *the_port, - struct termios *new_termios, struct termios *old_termios) + struct ktermios *new_termios, struct ktermios *old_termios) { struct ioc4_port *port = get_ioc4_port(the_port, 0); int baud, bits; @@ -1802,7 +1802,7 @@ static inline int ic4_startup_local(struct uart_port *the_port) ioc4_set_proto(port, the_port->mapbase); /* set the speed of the serial port */ - ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); + ioc4_change_speed(the_port, info->tty->termios, (struct ktermios *)0); return 0; } @@ -2570,7 +2570,7 @@ static int ic4_startup(struct uart_port *the_port) */ static void ic4_set_termios(struct uart_port *the_port, - struct termios *termios, struct termios *old_termios) + struct ktermios *termios, struct ktermios *old_termios) { unsigned long port_flags; diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index dca6c1bde8f..0746c9446ae 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -840,8 +840,8 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag, /* The port lock is not held. */ static void -ip22zilog_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; unsigned long flags; diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index f8262e6ad8d..7cf1c60027f 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -142,7 +142,7 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch) { unsigned long lock_flags; struct jsm_channel *channel = (struct jsm_channel *)port; - struct termios *termios; + struct ktermios *termios; spin_lock_irqsave(&port->lock, lock_flags); termios = port->info->tty->termios; @@ -180,7 +180,7 @@ static int jsm_tty_open(struct uart_port *port) struct jsm_board *brd; int rc = 0; struct jsm_channel *channel = (struct jsm_channel *)port; - struct termios *termios; + struct ktermios *termios; /* Get board pointer from our array of majors we have allocated */ brd = channel->ch_bd; @@ -269,7 +269,7 @@ static int jsm_tty_open(struct uart_port *port) static void jsm_tty_close(struct uart_port *port) { struct jsm_board *bd; - struct termios *ts; + struct ktermios *ts; struct jsm_channel *channel = (struct jsm_channel *)port; jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n"); @@ -302,8 +302,8 @@ static void jsm_tty_close(struct uart_port *port) } static void jsm_tty_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old_termios) + struct ktermios *termios, + struct ktermios *old_termios) { unsigned long lock_flags; struct jsm_channel *channel = (struct jsm_channel *)port; diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 7656a35f5e2..6e09c8b395e 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -699,7 +699,7 @@ static unsigned int m32r_sio_get_divisor(struct uart_port *port, } static void m32r_sio_set_termios(struct uart_port *port, - struct termios *termios, struct termios *old) + struct ktermios *termios, struct ktermios *old) { struct uart_sio_port *up = (struct uart_sio_port *)port; unsigned char cval = 0; diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 3db206d29b3..08430961a89 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -1132,7 +1132,7 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void mcfrs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 6dd579ed977..9d11a75663e 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -270,8 +270,8 @@ mpc52xx_uart_shutdown(struct uart_port *port) } static void -mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, - struct termios *old) +mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, + struct ktermios *old) { struct mpc52xx_psc __iomem *psc = PSC(port); unsigned long flags; diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index 29823bd60fb..3d2fcc57b1c 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -1440,8 +1440,8 @@ mpsc_shutdown(struct uart_port *port) } static void -mpsc_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +mpsc_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; u32 baud; diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 8ad1b8c5ec5..ccb8fa1800a 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -273,8 +273,8 @@ static void mux_shutdown(struct uart_port *port) * The Serial Mux does not support this function. */ static void -mux_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +mux_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { } diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c index 062bad457b1..b56f7db4503 100644 --- a/drivers/serial/netx-serial.c +++ b/drivers/serial/netx-serial.c @@ -337,8 +337,8 @@ static void netx_shutdown(struct uart_port *port) } static void -netx_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +netx_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud, quot; unsigned char old_cr; diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index bf9809ed9c0..752ef07516b 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1262,8 +1262,8 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) } -static void __pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long baud; @@ -1273,7 +1273,7 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, if (ZS_IS_ASLEEP(uap)) return; - memcpy(&uap->termios_cache, termios, sizeof(struct termios)); + memcpy(&uap->termios_cache, termios, sizeof(struct ktermios)); /* XXX Check which revs of machines actually allow 1 and 4Mb speeds * on the IR dongle. Note that the IRTTY driver currently doesn't know @@ -1313,8 +1313,8 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, } /* The port lock is not held. */ -static void pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long flags; diff --git a/drivers/serial/pmac_zilog.h b/drivers/serial/pmac_zilog.h index c03f9bfacdd..570b0d925e8 100644 --- a/drivers/serial/pmac_zilog.h +++ b/drivers/serial/pmac_zilog.h @@ -60,7 +60,7 @@ struct uart_pmac_port { volatile struct dbdma_regs __iomem *tx_dma_regs; volatile struct dbdma_regs __iomem *rx_dma_regs; - struct termios termios_cache; + struct ktermios termios_cache; }; #define to_pmz(p) ((struct uart_pmac_port *)(p)) diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 415fe9633a9..d403aaa5509 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -433,8 +433,8 @@ static void serial_pxa_shutdown(struct uart_port *port) } static void -serial_pxa_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; unsigned char cval, fcr = 0; diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 8dfc2dd058c..3ba9208ebd0 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -738,8 +738,8 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port, } static void s3c24xx_serial_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old) + struct ktermios *termios, + struct ktermios *old) { struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); struct s3c24xx_uart_port *ourport = to_ourport(port); diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index d4065266b6f..58a83c27e14 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -408,8 +408,8 @@ static void sa1100_shutdown(struct uart_port *port) } static void -sa1100_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sa1100_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct sa1100_port *sport = (struct sa1100_port *)port; unsigned long flags; diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index c67b05e9a45..f84982e508c 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -65,7 +65,7 @@ static struct lock_class_key port_lock_key; #define uart_console(port) (0) #endif -static void uart_change_speed(struct uart_state *state, struct termios *old_termios); +static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); static void uart_change_pm(struct uart_state *state, int pm_state); @@ -338,8 +338,8 @@ EXPORT_SYMBOL(uart_update_timeout); * we're actually going to be using. */ unsigned int -uart_get_baud_rate(struct uart_port *port, struct termios *termios, - struct termios *old, unsigned int min, unsigned int max) +uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, + struct ktermios *old, unsigned int min, unsigned int max) { unsigned int try, baud, altbaud = 38400; upf_t flags = port->flags & UPF_SPD_MASK; @@ -421,11 +421,11 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) EXPORT_SYMBOL(uart_get_divisor); static void -uart_change_speed(struct uart_state *state, struct termios *old_termios) +uart_change_speed(struct uart_state *state, struct ktermios *old_termios) { struct tty_struct *tty = state->info->tty; struct uart_port *port = state->port; - struct termios *termios; + struct ktermios *termios; /* * If we have no tty, termios, or the port does not exist, @@ -1139,7 +1139,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, return ret; } -static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct uart_state *state = tty->driver_data; unsigned long flags; @@ -1866,7 +1866,7 @@ int __init uart_set_options(struct uart_port *port, struct console *co, int baud, int parity, int bits, int flow) { - struct termios termios; + struct ktermios termios; int i; /* @@ -1876,7 +1876,7 @@ uart_set_options(struct uart_port *port, struct console *co, spin_lock_init(&port->lock); lockdep_set_class(&port->lock, &port_lock_key); - memset(&termios, 0, sizeof(struct termios)); + memset(&termios, 0, sizeof(struct ktermios)); termios.c_cflag = CREAD | HUPCL | CLOCAL; @@ -1991,12 +1991,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) * Re-enable the console device after suspending. */ if (uart_console(port)) { - struct termios termios; + struct ktermios termios; /* * First try to use the console cflag setting. */ - memset(&termios, 0, sizeof(struct termios)); + memset(&termios, 0, sizeof(struct ktermios)); termios.c_cflag = port->cons->cflag; /* @@ -2189,6 +2189,7 @@ int uart_register_driver(struct uart_driver *drv) normal->subtype = SERIAL_TYPE_NORMAL; normal->init_termios = tty_std_termios; normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600; normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; normal->driver_state = drv; tty_set_operations(normal, &uart_ops); diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 5e1ac356bbb..eb18d429752 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -348,8 +348,8 @@ static void lh7a40xuart_shutdown (struct uart_port* port) } static void lh7a40xuart_set_termios (struct uart_port* port, - struct termios* termios, - struct termios* old) + struct ktermios* termios, + struct ktermios* old) { unsigned int con; unsigned int inten; diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 2a48289ac72..7186a82c475 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -556,8 +556,8 @@ static void serial_txx9_shutdown(struct uart_port *port) } static void -serial_txx9_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; unsigned int cval, fcr = 0; diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 3b5f19ec212..9031b57f12d 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -943,8 +943,8 @@ static void sci_shutdown(struct uart_port *port) s->disable(port); } -static void sci_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sci_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct sci_port *s = &sci_ports[port->line]; unsigned int status, baud, smr_val; diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 956b2cf08e1..253ceb895ca 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -361,8 +361,8 @@ static int snp_startup(struct uart_port *port) * */ static void -snp_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +snp_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { } diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 03941d27d15..40d48566215 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -281,8 +281,8 @@ static void sunhv_shutdown(struct uart_port *port) } /* port->lock is not held. */ -static void sunhv_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); unsigned int quot = uart_get_divisor(port, baud); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 08a7cd6a3a0..493d5bbb661 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -786,8 +786,8 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla } /* port->lock is not held. */ -static void sunsab_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sunsab_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; unsigned long flags; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index c577faea60e..564592b2b2b 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -893,8 +893,8 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag, } static void -sunsu_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sunsu_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud, quot; diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index b2cc703b2b9..75de919a947 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -922,8 +922,8 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag, /* The port lock is not held. */ static void -sunzilog_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; unsigned long flags; diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index 83690653b78..92eba893559 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -214,8 +214,8 @@ static void ulite_shutdown(struct uart_port *port) free_irq(port->irq, port); } -static void ulite_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void ulite_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned long flags; unsigned int baud; diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c index 28f3bbff87b..dd98aca6ed0 100644 --- a/drivers/serial/v850e_uart.c +++ b/drivers/serial/v850e_uart.c @@ -404,8 +404,8 @@ static void v850e_uart_shutdown (struct uart_port *port) } static void -v850e_uart_set_termios (struct uart_port *port, struct termios *termios, - struct termios *old) +v850e_uart_set_termios (struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned cflags = termios->c_cflag; diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index fd51f8182de..cf0e663b42e 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -562,8 +562,8 @@ static void siu_shutdown(struct uart_port *port) free_irq(port->irq, port); } -static void siu_set_termios(struct uart_port *port, struct termios *new, - struct termios *old) +static void siu_set_termios(struct uart_port *port, struct ktermios *new, + struct ktermios *old) { tcflag_t c_cflag, c_iflag; uint8_t lcr, fcr, ier; diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index 792becdfe6f..fc319727366 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c @@ -1238,7 +1238,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct dec_serial *info = (struct dec_serial *)tty->driver_data; int was_stopped; diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 7f1fa956dcd..98199628e39 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -677,10 +677,10 @@ static const __u8 acm_tty_size[] = { 5, 6, 7, 8 }; -static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old) +static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { struct acm *acm = tty->driver_data; - struct termios *termios = tty->termios; + struct ktermios *termios = tty->termios; struct usb_cdc_line_coding newline; int newctrl = acm->ctrlout; diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 208e55a667a..5516c59ed5e 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -200,7 +200,7 @@ static void gs_unthrottle(struct tty_struct * tty); static void gs_break(struct tty_struct *tty, int break_state); static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void gs_set_termios(struct tty_struct *tty, struct termios *old); +static void gs_set_termios(struct tty_struct *tty, struct ktermios *old); static int gs_send(struct gs_dev *dev); static int gs_send_packet(struct gs_dev *dev, char *packet, @@ -1077,7 +1077,7 @@ static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, /* * gs_set_termios */ -static void gs_set_termios(struct tty_struct *tty, struct termios *old) +static void gs_set_termios(struct tty_struct *tty, struct ktermios *old) { } diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 863966c1c5a..5261cd22ee6 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -156,7 +156,7 @@ cleanup: } static void ark3116_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct ark3116_private *priv = usb_get_serial_port_data(port); @@ -326,7 +326,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, static int ark3116_open(struct usb_serial_port *port, struct file *filp) { - struct termios tmp_termios; + struct ktermios tmp_termios; struct usb_serial *serial = port->serial; char *buf; int result = 0; diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 8835bb58ca9..38b4dae319e 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -92,7 +92,7 @@ static void belkin_sa_shutdown (struct usb_serial *serial); static int belkin_sa_open (struct usb_serial_port *port, struct file *filp); static void belkin_sa_close (struct usb_serial_port *port, struct file *filp); static void belkin_sa_read_int_callback (struct urb *urb); -static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios * old); +static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios * old); static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state ); static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file); @@ -333,7 +333,7 @@ exit: __FUNCTION__, retval); } -static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct belkin_sa_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 7167728d764..9386e216d68 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -65,7 +65,7 @@ static int usb_console_setup(struct console *co, char *options) struct usb_serial_port *port; int retval = 0; struct tty_struct *tty; - struct termios *termios; + struct ktermios *termios; dbg ("%s", __FUNCTION__); diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index f95d42c0d16..2f9b7ac3266 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -41,7 +41,7 @@ static int cp2101_open(struct usb_serial_port*, struct file*); static void cp2101_cleanup(struct usb_serial_port*); static void cp2101_close(struct usb_serial_port*, struct file*); static void cp2101_get_termios(struct usb_serial_port*); -static void cp2101_set_termios(struct usb_serial_port*, struct termios*); +static void cp2101_set_termios(struct usb_serial_port*, struct ktermios*); static int cp2101_tiocmget (struct usb_serial_port *, struct file *); static int cp2101_tiocmset (struct usb_serial_port *, struct file *, unsigned int, unsigned int); @@ -506,7 +506,7 @@ static void cp2101_get_termios (struct usb_serial_port *port) } static void cp2101_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { unsigned int cflag, old_cflag=0; int baud=0, bits; diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 093f303b318..a1fdb85b8c0 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -143,7 +143,7 @@ struct cypress_private { wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ char prev_status, diff_status; /* used for TIOCMIWAIT */ /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */ - struct termios tmp_termios; /* stores the old termios settings */ + struct ktermios tmp_termios; /* stores the old termios settings */ }; /* write buffer structure */ @@ -165,7 +165,7 @@ static int cypress_write (struct usb_serial_port *port, const unsigned char *b static void cypress_send (struct usb_serial_port *port); static int cypress_write_room (struct usb_serial_port *port); static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void cypress_set_termios (struct usb_serial_port *port, struct termios * old); +static void cypress_set_termios (struct usb_serial_port *port, struct ktermios * old); static int cypress_tiocmget (struct usb_serial_port *port, struct file *file); static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); static int cypress_chars_in_buffer (struct usb_serial_port *port); @@ -949,13 +949,13 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi switch (cmd) { case TIOCGSERIAL: - if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) { + if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct ktermios))) { return -EFAULT; } return (0); break; case TIOCSSERIAL: - if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) { + if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct ktermios))) { return -EFAULT; } /* here we need to call cypress_set_termios to invoke the new settings */ @@ -1019,7 +1019,7 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi static void cypress_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct cypress_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 83d0e21145b..9d9ea874639 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -449,7 +449,7 @@ static int digi_transmit_idle( struct usb_serial_port *port, static void digi_rx_throttle (struct usb_serial_port *port); static void digi_rx_unthrottle (struct usb_serial_port *port); static void digi_set_termios( struct usb_serial_port *port, - struct termios *old_termios ); + struct ktermios *old_termios ); static void digi_break_ctl( struct usb_serial_port *port, int break_state ); static int digi_ioctl( struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg ); @@ -976,7 +976,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); static void digi_set_termios( struct usb_serial_port *port, - struct termios *old_termios ) + struct ktermios *old_termios ) { struct digi_port *priv = usb_get_serial_port_data(port); @@ -1463,7 +1463,7 @@ static int digi_open( struct usb_serial_port *port, struct file *filp ) int ret; unsigned char buf[32]; struct digi_port *priv = usb_get_serial_port_data(port); - struct termios not_termios; + struct ktermios not_termios; unsigned long flags = 0; diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 4ce10a83195..92beeb19795 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -92,7 +92,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static void empeg_write_bulk_callback (struct urb *urb); static void empeg_read_bulk_callback (struct urb *urb); @@ -442,7 +442,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign } -static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s - port %d", __FUNCTION__, port->number); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 72e4d48f51e..41b0ad2d56a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -595,7 +595,7 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port); static void ftdi_write_bulk_callback (struct urb *urb); static void ftdi_read_bulk_callback (struct urb *urb); static void ftdi_process_read (struct work_struct *work); -static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old); +static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios * old); static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file); static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear); static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); @@ -1880,7 +1880,7 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) * WARNING: set_termios calls this with old_termios in kernel space */ -static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { /* ftdi_termios */ struct usb_device *dev = port->serial->dev; unsigned int cflag = port->tty->termios->c_cflag; diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index d06547a13f2..f623d58370a 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -229,7 +229,7 @@ static int edge_write_room (struct usb_serial_port *port); static int edge_chars_in_buffer (struct usb_serial_port *port); static void edge_throttle (struct usb_serial_port *port); static void edge_unthrottle (struct usb_serial_port *port); -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); static void edge_break (struct usb_serial_port *port, int break_state); static int edge_tiocmget (struct usb_serial_port *port, struct file *file); @@ -257,7 +257,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8 static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param); static int calc_baud_rate_divisor (int baud_rate, int *divisor); static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate); -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios); +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios); static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue); static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength); static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port); @@ -1431,7 +1431,7 @@ static void edge_unthrottle (struct usb_serial_port *port) * SerialSetTermios * this function is called by the tty driver when it wants to change the termios structure *****************************************************************************/ -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; @@ -2412,7 +2412,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r #ifndef CMSPAR #define CMSPAR 0 #endif -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) { struct tty_struct *tty; int baud; diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index ee0c921e152..2da2684e080 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -238,7 +238,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c static void stop_read(struct edgeport_port *edge_port); static int restart_read(struct edgeport_port *edge_port); -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static void edge_send(struct usb_serial_port *port); /* circular buffer */ @@ -2361,7 +2361,7 @@ static int restart_read(struct edgeport_port *edge_port) return status; } -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) { struct ump_uart_config *config; struct tty_struct *tty; @@ -2512,7 +2512,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio return; } -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 331bf81556f..8fdf486e346 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -107,7 +107,7 @@ static void ir_close (struct usb_serial_port *port, struct file *filep); static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count); static void ir_write_bulk_callback (struct urb *urb); static void ir_read_bulk_callback (struct urb *urb); -static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static u8 ir_baud = 0; static u8 ir_xbof = 0; @@ -497,7 +497,7 @@ static void ir_read_bulk_callback (struct urb *urb) return; } -static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { unsigned char *transfer_buffer; unsigned int cflag; diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 7639652cec4..9d2fdfd6865 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -264,7 +264,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state) static void keyspan_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { int baud_rate, device_port; struct keyspan_port_private *p_priv; diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 7472ed6bf62..6413d73c139 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -59,7 +59,7 @@ static int keyspan_ioctl (struct usb_serial_port *port, unsigned int cmd, unsigned long arg); static void keyspan_set_termios (struct usb_serial_port *port, - struct termios *old); + struct ktermios *old); static void keyspan_break_ctl (struct usb_serial_port *port, int break_state); static int keyspan_tiocmget (struct usb_serial_port *port, diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index e09a0bfe623..126b9703bba 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -365,7 +365,7 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state static void keyspan_pda_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; unsigned int cflag = port->tty->termios->c_cflag; diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 17e205699c2..73d755df484 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -86,7 +86,7 @@ static int klsi_105_write_room (struct usb_serial_port *port); static void klsi_105_read_bulk_callback (struct urb *urb); static void klsi_105_set_termios (struct usb_serial_port *port, - struct termios * old); + struct ktermios *old); static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, @@ -164,7 +164,7 @@ struct klsi_105_port_settings { #define URB_TRANSFER_BUFFER_SIZE 64 struct klsi_105_private { struct klsi_105_port_settings cfg; - struct termios termios; + struct ktermios termios; unsigned long line_state; /* modem line settings */ /* write pool */ struct urb * write_urb_pool[NUM_URBS]; @@ -688,7 +688,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb) static void klsi_105_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct klsi_105_private *priv = usb_get_serial_port_data(port); unsigned int iflag = port->tty->termios->c_iflag; diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 237289920f0..e284d6c0fd3 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -136,7 +136,7 @@ struct kobil_private { int cur_pos; // index of the next char to send in buf __u16 device_type; int line_state; - struct termios internal_termios; + struct ktermios internal_termios; }; @@ -624,11 +624,11 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, switch (cmd) { case TCGETS: // 0x5401 - if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios))) { + if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct ktermios))) { dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number); return -EFAULT; } - if (kernel_termios_to_user_termios((struct termios __user *)arg, + if (kernel_termios_to_user_termios((struct ktermios __user *)arg, &priv->internal_termios)) return -EFAULT; return 0; @@ -638,12 +638,12 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number); return -ENOTTY; } - if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios))) { + if (!access_ok(VERIFY_READ, user_arg, sizeof(struct ktermios))) { dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number); return -EFAULT; } if (user_termios_to_kernel_termios(&priv->internal_termios, - (struct termios __user *)arg)) + (struct ktermios __user *)arg)) return -EFAULT; settings = kzalloc(50, GFP_KERNEL); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index a906e500a02..38b1d17e06e 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -98,7 +98,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp); static void mct_u232_read_int_callback (struct urb *urb); static void mct_u232_set_termios (struct usb_serial_port *port, - struct termios * old); + struct ktermios * old); static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, @@ -556,7 +556,7 @@ exit: } /* mct_u232_read_int_callback */ static void mct_u232_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 70f93b18292..e55f4ed81d7 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1014,7 +1014,7 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, * the specified new settings. */ static void change_port_settings(struct moschip_port *mos7720_port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial_port *port; struct usb_serial *serial; @@ -1203,7 +1203,7 @@ static void change_port_settings(struct moschip_port *mos7720_port, * termios structure. */ static void mos7720_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { int status; unsigned int cflag; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 5432c634008..8cc728a49e4 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1931,7 +1931,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, *****************************************************************************/ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, - struct termios *old_termios) + struct ktermios *old_termios) { struct tty_struct *tty; int baud; @@ -2118,7 +2118,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, *****************************************************************************/ static void mos7840_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { int status; unsigned int cflag; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 130afbbd3fc..0ae4098718c 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -59,7 +59,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port); static int option_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); static void option_set_termios(struct usb_serial_port *port, - struct termios *old); + struct ktermios *old); static void option_break_ctl(struct usb_serial_port *port, int break_state); static int option_tiocmget(struct usb_serial_port *port, struct file *file); static int option_tiocmset(struct usb_serial_port *port, struct file *file, @@ -230,7 +230,7 @@ static void option_break_ctl(struct usb_serial_port *port, int break_state) } static void option_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { dbg("%s", __FUNCTION__); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index bc800c8787a..d124d780e42 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -455,7 +455,7 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port) } static void pl2303_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); @@ -687,7 +687,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp) static int pl2303_open(struct usb_serial_port *port, struct file *filp) { - struct termios tmp_termios; + struct ktermios tmp_termios; struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned char *buf; diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 4b5097fa48d..6d8e91e00ec 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -145,7 +145,7 @@ static void sierra_break_ctl(struct usb_serial_port *port, int break_state) } static void sierra_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { dbg("%s", __FUNCTION__); diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index ae98d8cbdbb..f42eb9ea640 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -161,7 +161,7 @@ static void ti_throttle(struct usb_serial_port *port); static void ti_unthrottle(struct usb_serial_port *port); static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); static void ti_set_termios(struct usb_serial_port *port, - struct termios *old_termios); + struct ktermios *old_termios); static int ti_tiocmget(struct usb_serial_port *port, struct file *file); static int ti_tiocmset(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); @@ -881,7 +881,7 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file, static void ti_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct ti_port *tport = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 3d5072f14b8..716f6806cc8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -397,7 +397,7 @@ exit: return retval; } -static void serial_set_termios (struct tty_struct *tty, struct termios * old) +static void serial_set_termios (struct tty_struct *tty, struct ktermios * old) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index eef5eaa5fa0..b09f0609605 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -46,7 +46,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id static int visor_calc_num_ports(struct usb_serial *serial); static void visor_shutdown (struct usb_serial *serial); static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static void visor_write_bulk_callback (struct urb *urb); static void visor_read_bulk_callback (struct urb *urb); static void visor_read_int_callback (struct urb *urb); @@ -916,7 +916,7 @@ static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsign /* This function is all nice and good, but we don't change anything based on it :) */ -static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag; diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 154c7d29059..dc45e58e2b8 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -145,7 +145,7 @@ static void whiteheat_close (struct usb_serial_port *port, struct file *filp); static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int whiteheat_write_room (struct usb_serial_port *port); static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old); +static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios * old); static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file); static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); static void whiteheat_break_ctl (struct usb_serial_port *port, int break_state); @@ -597,7 +597,7 @@ static void whiteheat_shutdown (struct usb_serial *serial) static int whiteheat_open (struct usb_serial_port *port, struct file *filp) { int retval = 0; - struct termios old_term; + struct ktermios old_term; dbg("%s - port %d", __FUNCTION__, port->number); @@ -870,7 +870,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un } -static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s -port %d", __FUNCTION__, port->number); diff --git a/include/asm-generic/termios.h b/include/asm-generic/termios.h index 1e58ca39592..3769e6bd63b 100644 --- a/include/asm-generic/termios.h +++ b/include/asm-generic/termios.h @@ -11,7 +11,7 @@ /* * Translate a "termio" structure into a "termios". Ugh. */ -static inline int user_termio_to_kernel_termios(struct termios *termios, +static inline int user_termio_to_kernel_termios(struct ktermios *termios, struct termio __user *termio) { unsigned short tmp; @@ -48,7 +48,7 @@ static inline int user_termio_to_kernel_termios(struct termios *termios, * Translate a "termios" structure into a "termio". Ugh. */ static inline int kernel_termios_to_user_termio(struct termio __user *termio, - struct termios *termios) + struct ktermios *termios) { if (put_user(termios->c_iflag, &termio->c_iflag) < 0 || put_user(termios->c_oflag, &termio->c_oflag) < 0 || diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h index b572f21b32c..5e79198f7d1 100644 --- a/include/asm-powerpc/termbits.h +++ b/include/asm-powerpc/termbits.h @@ -37,8 +37,8 @@ struct ktermios { tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ cc_t c_cc[NCCS]; /* control characters */ + cc_t c_line; /* line discipline (== c_cc[19]) */ speed_t c_ispeed; /* input speed */ speed_t c_ospeed; /* output speed */ }; diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h index e2538456195..5412da28fa4 100644 --- a/include/linux/generic_serial.h +++ b/include/linux/generic_serial.h @@ -91,7 +91,7 @@ void gs_hangup(struct tty_struct *tty); int gs_block_til_ready(void *port, struct file *filp); void gs_close(struct tty_struct *tty, struct file *filp); void gs_set_termios (struct tty_struct * tty, - struct termios * old_termios); + struct ktermios * old_termios); int gs_init_port(struct gs_port *port); int gs_setserial(struct gs_port *port, struct serial_struct __user *sp); int gs_getserial(struct gs_port *port, struct serial_struct __user *sp); diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 62991148d5a..3c7875b7ab5 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -511,8 +511,8 @@ typedef struct modem_info { #endif struct tty_struct *tty; /* Pointer to corresponding tty */ atemu emu; /* AT-emulator data */ - struct termios normal_termios; /* For saving termios structs */ - struct termios callout_termios; + struct ktermios normal_termios; /* For saving termios structs */ + struct ktermios callout_termios; wait_queue_head_t open_wait, close_wait; struct semaphore write_sem; spinlock_t readlock; @@ -525,8 +525,8 @@ typedef struct _isdn_modem { int refcount; /* Number of opens */ struct tty_driver *tty_modem; /* tty-device */ struct tty_struct *modem_table[ISDN_MAX_CHANNELS]; /* ?? copied from Orig */ - struct termios *modem_termios[ISDN_MAX_CHANNELS]; - struct termios *modem_termios_locked[ISDN_MAX_CHANNELS]; + struct ktermios *modem_termios[ISDN_MAX_CHANNELS]; + struct ktermios *modem_termios_locked[ISDN_MAX_CHANNELS]; modem_info info[ISDN_MAX_CHANNELS]; /* Private data */ } isdn_modem_t; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 82767213664..cf23813cbec 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -166,8 +166,8 @@ struct uart_ops { void (*break_ctl)(struct uart_port *, int ctl); int (*startup)(struct uart_port *); void (*shutdown)(struct uart_port *); - void (*set_termios)(struct uart_port *, struct termios *new, - struct termios *old); + void (*set_termios)(struct uart_port *, struct ktermios *new, + struct ktermios *old); void (*pm)(struct uart_port *, unsigned int state, unsigned int oldstate); int (*set_wake)(struct uart_port *, unsigned int state); @@ -361,8 +361,8 @@ void uart_write_wakeup(struct uart_port *port); */ void uart_update_timeout(struct uart_port *port, unsigned int cflag, unsigned int baud); -unsigned int uart_get_baud_rate(struct uart_port *port, struct termios *termios, - struct termios *old, unsigned int min, +unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, + struct ktermios *old, unsigned int min, unsigned int max); unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 91b3ea2bbb1..10f99e5f1a9 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -218,7 +218,7 @@ struct usb_serial_driver { int (*write) (struct usb_serial_port *port, const unsigned char *buf, int count); int (*write_room) (struct usb_serial_port *port); int (*ioctl) (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); - void (*set_termios) (struct usb_serial_port *port, struct termios * old); + void (*set_termios) (struct usb_serial_port *port, struct ktermios * old); void (*break_ctl) (struct usb_serial_port *port, int break_state); int (*chars_in_buffer) (struct usb_serial_port *port); void (*throttle) (struct usb_serial_port *port); diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 1fb5d42f37a..e0e0d09023b 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -752,9 +752,9 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned return -ENOIOCTLCMD; } -static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old) +static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) { - struct termios *new = (struct termios *) tty->termios; + struct ktermios *new = tty->termios; int old_baud_rate = tty_termios_baud_rate(old); int new_baud_rate = tty_termios_baud_rate(new); -- cgit v1.2.3-70-g09d2 From 4c198557c6b45956a6f54b958fb97a15b02a6a3b Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 8 Dec 2006 17:46:58 +1100 Subject: [POWERPC] Add DSCR SPR to sysfs POWER6 adds a new SPR, the data stream control register (DSCR). It can be used to adjust how agressive the prefetch mechanisms are. Its possible we may want to context switch this, but for now just export it to userspace via sysfs so we can adjust it. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/sysfs.c | 8 ++++++++ include/asm-powerpc/cputable.h | 6 ++++-- include/asm-powerpc/reg.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 63ed265b7f0..22daba56c86 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -181,6 +181,7 @@ SYSFS_PMCSETUP(pmc6, SPRN_PMC6); SYSFS_PMCSETUP(pmc7, SPRN_PMC7); SYSFS_PMCSETUP(pmc8, SPRN_PMC8); SYSFS_PMCSETUP(purr, SPRN_PURR); +SYSFS_PMCSETUP(dscr, SPRN_DSCR); static SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0); static SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1); @@ -194,6 +195,7 @@ static SYSDEV_ATTR(pmc6, 0600, show_pmc6, store_pmc6); static SYSDEV_ATTR(pmc7, 0600, show_pmc7, store_pmc7); static SYSDEV_ATTR(pmc8, 0600, show_pmc8, store_pmc8); static SYSDEV_ATTR(purr, 0600, show_purr, NULL); +static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr); static void register_cpu_online(unsigned int cpu) { @@ -231,6 +233,9 @@ static void register_cpu_online(unsigned int cpu) if (cpu_has_feature(CPU_FTR_PURR)) sysdev_create_file(s, &attr_purr); + + if (cpu_has_feature(CPU_FTR_DSCR)) + sysdev_create_file(s, &attr_dscr); } #ifdef CONFIG_HOTPLUG_CPU @@ -272,6 +277,9 @@ static void unregister_cpu_online(unsigned int cpu) if (cpu_has_feature(CPU_FTR_PURR)) sysdev_remove_file(s, &attr_purr); + + if (cpu_has_feature(CPU_FTR_DSCR)) + sysdev_remove_file(s, &attr_dscr); } #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 6fe5c9d4ca3..782adbf1f7a 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -152,6 +152,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000) #define CPU_FTR_CELL_TB_BUG LONG_ASM_CONST(0x0000800000000000) #define CPU_FTR_SPURR LONG_ASM_CONST(0x0001000000000000) +#define CPU_FTR_DSCR LONG_ASM_CONST(0x0002000000000000) #ifndef __ASSEMBLY__ @@ -330,13 +331,14 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ - CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE) + CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ + CPU_FTR_DSCR) #define CPU_FTRS_POWER6X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | \ - CPU_FTR_SPURR | CPU_FTR_REAL_LE) + CPU_FTR_SPURR | CPU_FTR_REAL_LE | CPU_FTR_DSCR) #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index 6faae7b14d5..cacdecca610 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -143,6 +143,7 @@ /* Special Purpose Registers (SPRNs)*/ #define SPRN_CTR 0x009 /* Count Register */ +#define SPRN_DSCR 0x11 #define SPRN_CTRLF 0x088 #define SPRN_CTRLT 0x098 #define CTRL_CT 0xc0000000 /* current thread */ -- cgit v1.2.3-70-g09d2 From f050982a9b7c4edc414f0d5543c3cb24504223c6 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 8 Dec 2006 17:51:13 +1100 Subject: [POWERPC] Add SPURR SPR to sysfs Now we have a SPURR cpu feature bit, we can export it to userspace in sysfs. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/sysfs.c | 8 ++++++++ include/asm-powerpc/reg.h | 1 + 2 files changed, 9 insertions(+) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 22daba56c86..400ab2b946e 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -181,6 +181,7 @@ SYSFS_PMCSETUP(pmc6, SPRN_PMC6); SYSFS_PMCSETUP(pmc7, SPRN_PMC7); SYSFS_PMCSETUP(pmc8, SPRN_PMC8); SYSFS_PMCSETUP(purr, SPRN_PURR); +SYSFS_PMCSETUP(spurr, SPRN_SPURR); SYSFS_PMCSETUP(dscr, SPRN_DSCR); static SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0); @@ -195,6 +196,7 @@ static SYSDEV_ATTR(pmc6, 0600, show_pmc6, store_pmc6); static SYSDEV_ATTR(pmc7, 0600, show_pmc7, store_pmc7); static SYSDEV_ATTR(pmc8, 0600, show_pmc8, store_pmc8); static SYSDEV_ATTR(purr, 0600, show_purr, NULL); +static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL); static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr); static void register_cpu_online(unsigned int cpu) @@ -234,6 +236,9 @@ static void register_cpu_online(unsigned int cpu) if (cpu_has_feature(CPU_FTR_PURR)) sysdev_create_file(s, &attr_purr); + if (cpu_has_feature(CPU_FTR_SPURR)) + sysdev_create_file(s, &attr_spurr); + if (cpu_has_feature(CPU_FTR_DSCR)) sysdev_create_file(s, &attr_dscr); } @@ -278,6 +283,9 @@ static void unregister_cpu_online(unsigned int cpu) if (cpu_has_feature(CPU_FTR_PURR)) sysdev_remove_file(s, &attr_purr); + if (cpu_has_feature(CPU_FTR_SPURR)) + sysdev_remove_file(s, &attr_spurr); + if (cpu_has_feature(CPU_FTR_DSCR)) sysdev_remove_file(s, &attr_dscr); } diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index cacdecca610..a3631b15754 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -164,6 +164,7 @@ #define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */ #define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */ #define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */ +#define SPRN_SPURR 0x134 /* Scaled PURR */ #define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */ #define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */ #define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */ -- cgit v1.2.3-70-g09d2 From 08c183f31bdbb709f177f6d3110d5f288ea33933 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Sun, 10 Dec 2006 02:20:29 -0800 Subject: [PATCH] sched: add option to serialize load balancing Large sched domains can be very expensive to scan. Add an option SD_SERIALIZE to the sched domain flags. If that flag is set then we make sure that no other such domain is being balanced. [akpm@osdl.org: build fix] Signed-off-by: Christoph Lameter Cc: Peter Williams Cc: Nick Piggin Cc: Christoph Lameter Cc: "Siddha, Suresh B" Cc: "Chen, Kenneth W" Acked-by: Ingo Molnar Cc: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/topology.h | 1 + include/asm-ia64/topology.h | 1 + include/asm-powerpc/topology.h | 1 + include/asm-x86_64/topology.h | 1 + include/linux/sched.h | 1 + include/linux/topology.h | 3 ++- kernel/sched.c | 9 +++++++++ 7 files changed, 16 insertions(+), 1 deletion(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h index 978d0959613..ac58580ad66 100644 --- a/include/asm-i386/topology.h +++ b/include/asm-i386/topology.h @@ -89,6 +89,7 @@ static inline int node_to_first_cpu(int node) .flags = SD_LOAD_BALANCE \ | SD_BALANCE_EXEC \ | SD_BALANCE_FORK \ + | SD_SERIALIZE \ | SD_WAKE_BALANCE, \ .last_balance = jiffies, \ .balance_interval = 1, \ diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h index a6e38565ab4..22ed6749557 100644 --- a/include/asm-ia64/topology.h +++ b/include/asm-ia64/topology.h @@ -101,6 +101,7 @@ void build_cpu_to_node_map(void); .flags = SD_LOAD_BALANCE \ | SD_BALANCE_EXEC \ | SD_BALANCE_FORK \ + | SD_SERIALIZE \ | SD_WAKE_BALANCE, \ .last_balance = jiffies, \ .balance_interval = 64, \ diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h index 50c014007de..6610495f5f1 100644 --- a/include/asm-powerpc/topology.h +++ b/include/asm-powerpc/topology.h @@ -66,6 +66,7 @@ static inline int pcibus_to_node(struct pci_bus *bus) | SD_BALANCE_EXEC \ | SD_BALANCE_NEWIDLE \ | SD_WAKE_IDLE \ + | SD_SERIALIZE \ | SD_WAKE_BALANCE, \ .last_balance = jiffies, \ .balance_interval = 1, \ diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h index 5c8f49280db..2facec5914d 100644 --- a/include/asm-x86_64/topology.h +++ b/include/asm-x86_64/topology.h @@ -47,6 +47,7 @@ extern int __node_distance(int, int); .flags = SD_LOAD_BALANCE \ | SD_BALANCE_FORK \ | SD_BALANCE_EXEC \ + | SD_SERIALIZE \ | SD_WAKE_BALANCE, \ .last_balance = jiffies, \ .balance_interval = 1, \ diff --git a/include/linux/sched.h b/include/linux/sched.h index 1208feab46e..ea92e5c8908 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -648,6 +648,7 @@ enum idle_type #define SD_SHARE_CPUPOWER 128 /* Domain members share cpu power */ #define SD_POWERSAVINGS_BALANCE 256 /* Balance for power savings */ #define SD_SHARE_PKG_RESOURCES 512 /* Domain members share cpu pkg resources */ +#define SD_SERIALIZE 1024 /* Only a single load balancing instance */ #define BALANCE_FOR_MC_POWER \ (sched_smt_power_savings ? SD_POWERSAVINGS_BALANCE : 0) diff --git a/include/linux/topology.h b/include/linux/topology.h index b93bb6cc6cc..6c5a6e6e813 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -194,7 +194,8 @@ .wake_idx = 0, /* unused */ \ .forkexec_idx = 0, /* unused */ \ .per_cpu_gain = 100, \ - .flags = SD_LOAD_BALANCE, \ + .flags = SD_LOAD_BALANCE \ + | SD_SERIALIZE, \ .last_balance = jiffies, \ .balance_interval = 64, \ .nr_balance_failed = 0, \ diff --git a/kernel/sched.c b/kernel/sched.c index 0a4a26b21f6..2b2b780939c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2880,6 +2880,7 @@ static void update_load(struct rq *this_rq) * * Balancing parameters are set up in arch_init_sched_domains. */ +static DEFINE_SPINLOCK(balancing); static void run_rebalance_domains(struct softirq_action *h) { @@ -2909,6 +2910,11 @@ static void run_rebalance_domains(struct softirq_action *h) if (unlikely(!interval)) interval = 1; + if (sd->flags & SD_SERIALIZE) { + if (!spin_trylock(&balancing)) + goto out; + } + if (time_after_eq(jiffies, sd->last_balance + interval)) { if (load_balance(this_cpu, this_rq, sd, idle)) { /* @@ -2920,6 +2926,9 @@ static void run_rebalance_domains(struct softirq_action *h) } sd->last_balance = jiffies; } + if (sd->flags & SD_SERIALIZE) + spin_unlock(&balancing); +out: if (time_after(next_balance, sd->last_balance + interval)) next_balance = sd->last_balance + interval; } -- cgit v1.2.3-70-g09d2 From 45d8e7aaf47668550fdb6c2d3abbe42f48a76df2 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sun, 10 Dec 2006 23:15:47 -0600 Subject: [POWERPC] Only export __mtdcr/__mfdcr if CONFIG_PPC_DCR is set On 85xx we don't build in dcr support because the core doesn't implement the instructions. This caused problems when building an 85xx kernel. Additionally made it so we only build __mtdcr/__mfdcr if we are CONFIG_PPC_DCR_NATIVE. The 85xx build issue wasPointed out by Dai Haruki. Signed-off-by: Kumar Gala --- arch/powerpc/kernel/ppc_ksyms.c | 2 +- arch/powerpc/sysdev/Makefile | 3 ++- include/asm-powerpc/dcr-native.h | 37 +++++++++++++++++++++++++++++++++++-- include/asm-powerpc/dcr.h | 2 ++ include/asm-ppc/reg_booke.h | 36 ++---------------------------------- 5 files changed, 42 insertions(+), 38 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 9179f0739ea..95776b6af4e 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -208,7 +208,7 @@ EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */ extern long *intercept_table; EXPORT_SYMBOL(intercept_table); #endif /* CONFIG_PPC_STD_MMU_32 */ -#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) +#ifdef CONFIG_PPC_DCR_NATIVE EXPORT_SYMBOL(__mtdcr); EXPORT_SYMBOL(__mfdcr); #endif diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 6cc34597a62..04d4917eb30 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -5,7 +5,8 @@ endif obj-$(CONFIG_MPIC) += mpic.o obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o obj-$(CONFIG_PPC_MPC106) += grackle.o -obj-$(CONFIG_PPC_DCR) += dcr.o dcr-low.o +obj-$(CONFIG_PPC_DCR) += dcr.o +obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h index fd4a5f5e33d..d7a1bc1551c 100644 --- a/include/asm-powerpc/dcr-native.h +++ b/include/asm-powerpc/dcr-native.h @@ -20,8 +20,7 @@ #ifndef _ASM_POWERPC_DCR_NATIVE_H #define _ASM_POWERPC_DCR_NATIVE_H #ifdef __KERNEL__ - -#include +#ifndef __ASSEMBLY__ typedef struct {} dcr_host_t; @@ -32,7 +31,41 @@ typedef struct {} dcr_host_t; #define dcr_read(host, dcr_n) mfdcr(dcr_n) #define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value) +/* Device Control Registers */ +void __mtdcr(int reg, unsigned int val); +unsigned int __mfdcr(int reg); +#define mfdcr(rn) \ + ({unsigned int rval; \ + if (__builtin_constant_p(rn)) \ + asm volatile("mfdcr %0," __stringify(rn) \ + : "=r" (rval)); \ + else \ + rval = __mfdcr(rn); \ + rval;}) + +#define mtdcr(rn, v) \ +do { \ + if (__builtin_constant_p(rn)) \ + asm volatile("mtdcr " __stringify(rn) ",%0" \ + : : "r" (v)); \ + else \ + __mtdcr(rn, v); \ +} while (0) + +/* R/W of indirect DCRs make use of standard naming conventions for DCRs */ +#define mfdcri(base, reg) \ +({ \ + mtdcr(base ## _CFGADDR, base ## _ ## reg); \ + mfdcr(base ## _CFGDATA); \ +}) + +#define mtdcri(base, reg, data) \ +do { \ + mtdcr(base ## _CFGADDR, base ## _ ## reg); \ + mtdcr(base ## _CFGDATA, data); \ +} while (0) +#endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_DCR_NATIVE_H */ diff --git a/include/asm-powerpc/dcr.h b/include/asm-powerpc/dcr.h index 473f2c7fd89..b66c5e6941f 100644 --- a/include/asm-powerpc/dcr.h +++ b/include/asm-powerpc/dcr.h @@ -20,6 +20,7 @@ #ifndef _ASM_POWERPC_DCR_H #define _ASM_POWERPC_DCR_H #ifdef __KERNEL__ +#ifdef CONFIG_PPC_DCR #ifdef CONFIG_PPC_DCR_NATIVE #include @@ -38,5 +39,6 @@ extern unsigned int dcr_resource_len(struct device_node *np, unsigned int index); #endif /* CONFIG_PPC_MERGE */ +#endif /* CONFIG_PPC_DCR */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_DCR_H */ diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h index 602fbadeaf4..a263fc1e65c 100644 --- a/include/asm-ppc/reg_booke.h +++ b/include/asm-ppc/reg_booke.h @@ -9,41 +9,9 @@ #ifndef __ASM_PPC_REG_BOOKE_H__ #define __ASM_PPC_REG_BOOKE_H__ -#ifndef __ASSEMBLY__ -/* Device Control Registers */ -void __mtdcr(int reg, unsigned int val); -unsigned int __mfdcr(int reg); -#define mfdcr(rn) \ - ({unsigned int rval; \ - if (__builtin_constant_p(rn)) \ - asm volatile("mfdcr %0," __stringify(rn) \ - : "=r" (rval)); \ - else \ - rval = __mfdcr(rn); \ - rval;}) - -#define mtdcr(rn, v) \ -do { \ - if (__builtin_constant_p(rn)) \ - asm volatile("mtdcr " __stringify(rn) ",%0" \ - : : "r" (v)); \ - else \ - __mtdcr(rn, v); \ -} while (0) - -/* R/W of indirect DCRs make use of standard naming conventions for DCRs */ -#define mfdcri(base, reg) \ -({ \ - mtdcr(base ## _CFGADDR, base ## _ ## reg); \ - mfdcr(base ## _CFGDATA); \ -}) - -#define mtdcri(base, reg, data) \ -do { \ - mtdcr(base ## _CFGADDR, base ## _ ## reg); \ - mtdcr(base ## _CFGDATA, data); \ -} while (0) +#include +#ifndef __ASSEMBLY__ /* Performance Monitor Registers */ #define mfpmr(rn) ({unsigned int rval; \ asm volatile("mfpmr %0," __stringify(rn) \ -- cgit v1.2.3-70-g09d2 From 73c9ceab40b1269d6195e556773167c078ac8311 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 8 Dec 2006 03:30:41 -0800 Subject: [POWERPC] Generic BUG for powerpc This makes powerpc use the generic BUG machinery. The biggest reports the function name, since it is redundant with kallsyms, and not needed in general. There is an overall reduction of code, since module_32/64 duplicated several functions. Unfortunately there's no way to tell gcc that BUG won't return, so the BUG macro includes a goto loop. This will generate a real jmp instruction, which is never used. [akpm@osdl.org: build fix] [paulus@samba.org: remove infinite loop in BUG_ON] Signed-off-by: Jeremy Fitzhardinge Cc: Andi Kleen Cc: Hugh Dickens Cc: Michael Ellerman Cc: Benjamin Herrenschmidt Cc: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 5 +++ arch/powerpc/kernel/module_32.c | 23 +++-------- arch/powerpc/kernel/module_64.c | 23 +++-------- arch/powerpc/kernel/traps.c | 54 +++----------------------- arch/powerpc/kernel/vmlinux.lds.S | 6 +-- arch/powerpc/xmon/xmon.c | 10 ++--- include/asm-powerpc/bug.h | 80 +++++++++++++++++++-------------------- include/asm-powerpc/module.h | 2 - 8 files changed, 69 insertions(+), 134 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a35212b7346..f81d9f6f19f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -99,6 +99,11 @@ config AUDIT_ARCH bool default y +config GENERIC_BUG + bool + default y + depends on BUG + config DEFAULT_UIMAGE bool help diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c index e2c3c6a85f3..8339fd609de 100644 --- a/arch/powerpc/kernel/module_32.c +++ b/arch/powerpc/kernel/module_32.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "setup.h" @@ -290,23 +291,11 @@ int module_finalize(const Elf_Ehdr *hdr, struct module *me) { const Elf_Shdr *sect; + int err; - me->arch.bug_table = NULL; - me->arch.num_bugs = 0; - - /* Find the __bug_table section, if present */ - sect = find_section(hdr, sechdrs, "__bug_table"); - if (sect != NULL) { - me->arch.bug_table = (void *) sect->sh_addr; - me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); - } - - /* - * Strictly speaking this should have a spinlock to protect against - * traversals, but since we only traverse on BUG()s, a spinlock - * could potentially lead to deadlock and thus be counter-productive. - */ - list_add(&me->arch.bug_list, &module_bug_list); + err = module_bug_finalize(hdr, sechdrs, me); + if (err) /* never true, currently */ + return err; /* Apply feature fixups */ sect = find_section(hdr, sechdrs, "__ftr_fixup"); @@ -320,7 +309,7 @@ int module_finalize(const Elf_Ehdr *hdr, void module_arch_cleanup(struct module *mod) { - list_del(&mod->arch.bug_list); + module_bug_cleanup(mod); } struct bug_entry *module_find_bug(unsigned long bugaddr) diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 8dd1f0aae5d..75c7c4f1928 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -439,23 +440,11 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { const Elf_Shdr *sect; + int err; - me->arch.bug_table = NULL; - me->arch.num_bugs = 0; - - /* Find the __bug_table section, if present */ - sect = find_section(hdr, sechdrs, "__bug_table"); - if (sect != NULL) { - me->arch.bug_table = (void *) sect->sh_addr; - me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); - } - - /* - * Strictly speaking this should have a spinlock to protect against - * traversals, but since we only traverse on BUG()s, a spinlock - * could potentially lead to deadlock and thus be counter-productive. - */ - list_add(&me->arch.bug_list, &module_bug_list); + err = module_bug_finalize(hdr, sechdrs, me); + if (err) + return err; /* Apply feature fixups */ sect = find_section(hdr, sechdrs, "__ftr_fixup"); @@ -475,7 +464,7 @@ int module_finalize(const Elf_Ehdr *hdr, void module_arch_cleanup(struct module *mod) { - list_del(&mod->arch.bug_list); + module_bug_cleanup(mod); } struct bug_entry *module_find_bug(unsigned long bugaddr) diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index fde820e52d0..535f5066564 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -727,54 +728,9 @@ static int emulate_instruction(struct pt_regs *regs) return -EINVAL; } -/* - * Look through the list of trap instructions that are used for BUG(), - * BUG_ON() and WARN_ON() and see if we hit one. At this point we know - * that the exception was caused by a trap instruction of some kind. - * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0 - * otherwise. - */ -extern struct bug_entry __start___bug_table[], __stop___bug_table[]; - -#ifndef CONFIG_MODULES -#define module_find_bug(x) NULL -#endif - -struct bug_entry *find_bug(unsigned long bugaddr) +int is_valid_bugaddr(unsigned long addr) { - struct bug_entry *bug; - - for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) - if (bugaddr == bug->bug_addr) - return bug; - return module_find_bug(bugaddr); -} - -static int check_bug_trap(struct pt_regs *regs) -{ - struct bug_entry *bug; - unsigned long addr; - - if (regs->msr & MSR_PR) - return 0; /* not in kernel */ - addr = regs->nip; /* address of trap instruction */ - if (addr < PAGE_OFFSET) - return 0; - bug = find_bug(regs->nip); - if (bug == NULL) - return 0; - if (bug->line & BUG_WARNING_TRAP) { - /* this is a WARN_ON rather than BUG/BUG_ON */ - printk(KERN_ERR "Badness in %s at %s:%ld\n", - bug->function, bug->file, - bug->line & ~BUG_WARNING_TRAP); - dump_stack(); - return 1; - } - printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", - bug->function, bug->file, bug->line); - - return 0; + return is_kernel_addr(addr); } void __kprobes program_check_exception(struct pt_regs *regs) @@ -810,7 +766,9 @@ void __kprobes program_check_exception(struct pt_regs *regs) return; if (debugger_bpt(regs)) return; - if (check_bug_trap(regs)) { + + if (!(regs->msr & MSR_PR) && /* not user-mode */ + report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) { regs->nip += 4; return; } diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 04b98671a06..04b8e71bf5b 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -62,11 +62,7 @@ SECTIONS __stop___ex_table = .; } - __bug_table : { - __start___bug_table = .; - *(__bug_table) - __stop___bug_table = .; - } + BUG_TABLE /* * Init sections discarded at runtime diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index a34ed49e035..77540a2f770 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -1346,7 +1346,7 @@ static void backtrace(struct pt_regs *excp) static void print_bug_trap(struct pt_regs *regs) { - struct bug_entry *bug; + const struct bug_entry *bug; unsigned long addr; if (regs->msr & MSR_PR) @@ -1357,11 +1357,11 @@ static void print_bug_trap(struct pt_regs *regs) bug = find_bug(regs->nip); if (bug == NULL) return; - if (bug->line & BUG_WARNING_TRAP) + if (is_warning_bug(bug)) return; - printf("kernel BUG in %s at %s:%d!\n", - bug->function, bug->file, (unsigned int)bug->line); + printf("kernel BUG at %s:%u!\n", + bug->file, bug->line); } void excprint(struct pt_regs *fp) diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h index 978b2c7e84e..709568879f7 100644 --- a/include/asm-powerpc/bug.h +++ b/include/asm-powerpc/bug.h @@ -13,36 +13,39 @@ #ifndef __ASSEMBLY__ -struct bug_entry { - unsigned long bug_addr; - long line; - const char *file; - const char *function; -}; - -struct bug_entry *find_bug(unsigned long bugaddr); - -/* - * If this bit is set in the line number it means that the trap - * is for WARN_ON rather than BUG or BUG_ON. - */ -#define BUG_WARNING_TRAP 0x1000000 - #ifdef CONFIG_BUG +/* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and + sizeof(struct bug_entry), respectively */ +#ifdef CONFIG_DEBUG_BUGVERBOSE +#define _EMIT_BUG_ENTRY \ + ".section __bug_table,\"a\"\n" \ + "2:\t" PPC_LONG "1b, %0\n" \ + "\t.short %1, %2\n" \ + ".org 2b+%3\n" \ + ".previous\n" +#else +#define _EMIT_BUG_ENTRY \ + ".section __bug_table,\"a\"\n" \ + "2:\t" PPC_LONG "1b\n" \ + "\t.short %2\n" \ + ".org 2b+%3\n" \ + ".previous\n" +#endif + /* * BUG_ON() and WARN_ON() do their best to cooperate with compile-time * optimisations. However depending on the complexity of the condition * some compiler versions may not produce optimal results. */ -#define BUG() do { \ - __asm__ __volatile__( \ - "1: twi 31,0,0\n" \ - ".section __bug_table,\"a\"\n" \ - "\t"PPC_LONG" 1b,%0,%1,%2\n" \ - ".previous" \ - : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ +#define BUG() do { \ + __asm__ __volatile__( \ + "1: twi 31,0,0\n" \ + _EMIT_BUG_ENTRY \ + : : "i" (__FILE__), "i" (__LINE__), \ + "i" (0), "i" (sizeof(struct bug_entry))); \ + for(;;) ; \ } while (0) #define BUG_ON(x) do { \ @@ -51,23 +54,21 @@ struct bug_entry *find_bug(unsigned long bugaddr); BUG(); \ } else { \ __asm__ __volatile__( \ - "1: "PPC_TLNEI" %0,0\n" \ - ".section __bug_table,\"a\"\n" \ - "\t"PPC_LONG" 1b,%1,%2,%3\n" \ - ".previous" \ - : : "r" ((long)(x)), "i" (__LINE__), \ - "i" (__FILE__), "i" (__FUNCTION__)); \ + "1: "PPC_TLNEI" %4,0\n" \ + _EMIT_BUG_ENTRY \ + : : "i" (__FILE__), "i" (__LINE__), "i" (0), \ + "i" (sizeof(struct bug_entry)), \ + "r" ((long)(x))); \ } \ } while (0) #define __WARN() do { \ __asm__ __volatile__( \ "1: twi 31,0,0\n" \ - ".section __bug_table,\"a\"\n" \ - "\t"PPC_LONG" 1b,%0,%1,%2\n" \ - ".previous" \ - : : "i" (__LINE__ + BUG_WARNING_TRAP), \ - "i" (__FILE__), "i" (__FUNCTION__)); \ + _EMIT_BUG_ENTRY \ + : : "i" (__FILE__), "i" (__LINE__), \ + "i" (BUGFLAG_WARNING), \ + "i" (sizeof(struct bug_entry))); \ } while (0) #define WARN_ON(x) ({ \ @@ -77,13 +78,12 @@ struct bug_entry *find_bug(unsigned long bugaddr); __WARN(); \ } else { \ __asm__ __volatile__( \ - "1: "PPC_TLNEI" %0,0\n" \ - ".section __bug_table,\"a\"\n" \ - "\t"PPC_LONG" 1b,%1,%2,%3\n" \ - ".previous" \ - : : "r" (__ret_warn_on), \ - "i" (__LINE__ + BUG_WARNING_TRAP), \ - "i" (__FILE__), "i" (__FUNCTION__)); \ + "1: "PPC_TLNEI" %4,0\n" \ + _EMIT_BUG_ENTRY \ + : : "i" (__FILE__), "i" (__LINE__), \ + "i" (BUGFLAG_WARNING), \ + "i" (sizeof(struct bug_entry)), \ + "r" (__ret_warn_on)); \ } \ unlikely(__ret_warn_on); \ }) diff --git a/include/asm-powerpc/module.h b/include/asm-powerpc/module.h index 584fabfb4f0..e5f14b13ccf 100644 --- a/include/asm-powerpc/module.h +++ b/include/asm-powerpc/module.h @@ -46,8 +46,6 @@ struct mod_arch_specific { unsigned int num_bugs; }; -extern struct bug_entry *module_find_bug(unsigned long bugaddr); - /* * Select ELF headers. * Make empty section for module_frob_arch_sections to expand. -- cgit v1.2.3-70-g09d2 From 022416967a814aa1b3a9476a842c0947a1a9d784 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 11 Dec 2006 13:16:05 +0000 Subject: [PATCH] LOG2: Make powerpc's __ilog2_u64() take a 64-bit argument Make powerpc's __ilog2_u64() take a 64-bit argument. Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- include/asm-powerpc/bitops.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h index 0288144ea02..8f757f6246e 100644 --- a/include/asm-powerpc/bitops.h +++ b/include/asm-powerpc/bitops.h @@ -209,7 +209,7 @@ int __ilog2_u32(u32 n) #ifdef __powerpc64__ static inline __attribute__((const)) -int __ilog2_u64(u32 n) +int __ilog2_u64(u64 n) { int bit; asm ("cntlzd %0,%1" : "=r" (bit) : "r" (n)); -- cgit v1.2.3-70-g09d2 From 8a102eed9c4e1d21bad07a8fd97bd4fbf125d966 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 13 Dec 2006 00:34:30 -0800 Subject: [PATCH] PM: Fix SMP races in the freezer Currently, to tell a task that it should go to the refrigerator, we set the PF_FREEZE flag for it and send a fake signal to it. Unfortunately there are two SMP-related problems with this approach. First, a task running on another CPU may be updating its flags while the freezer attempts to set PF_FREEZE for it and this may leave the task's flags in an inconsistent state. Second, there is a potential race between freeze_process() and refrigerator() in which freeze_process() running on one CPU is reading a task's PF_FREEZE flag while refrigerator() running on another CPU has just set PF_FROZEN for the same task and attempts to reset PF_FREEZE for it. If the refrigerator wins the race, freeze_process() will state that PF_FREEZE hasn't been set for the task and will set it unnecessarily, so the task will go to the refrigerator once again after it's been thawed. To solve first of these problems we need to stop using PF_FREEZE to tell tasks that they should go to the refrigerator. Instead, we can introduce a special TIF_*** flag and use it for this purpose, since it is allowed to change the other tasks' TIF_*** flags and there are special calls for it. To avoid the freeze_process()-refrigerator() race we can make freeze_process() to always check the task's PF_FROZEN flag after it's read its "freeze" flag. We should also make sure that refrigerator() will always reset the task's "freeze" flag after it's set PF_FROZEN for it. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Cc: Russell King Cc: David Howells Cc: Andi Kleen Cc: "Luck, Tony" Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-arm/thread_info.h | 2 ++ include/asm-frv/thread_info.h | 2 ++ include/asm-i386/thread_info.h | 2 ++ include/asm-ia64/thread_info.h | 2 ++ include/asm-powerpc/thread_info.h | 2 ++ include/asm-sh/thread_info.h | 2 ++ include/asm-x86_64/thread_info.h | 2 ++ include/linux/freezer.h | 11 ++++++----- include/linux/sched.h | 1 - kernel/power/process.c | 17 ++++++++++------- 10 files changed, 30 insertions(+), 13 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h index d9b8bddc873..5014794f9eb 100644 --- a/include/asm-arm/thread_info.h +++ b/include/asm-arm/thread_info.h @@ -147,6 +147,7 @@ extern void iwmmxt_task_switch(struct thread_info *); #define TIF_POLLING_NRFLAG 16 #define TIF_USING_IWMMXT 17 #define TIF_MEMDIE 18 +#define TIF_FREEZE 19 #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) @@ -154,6 +155,7 @@ extern void iwmmxt_task_switch(struct thread_info *); #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) +#define _TIF_FREEZE (1 << TIF_FREEZE) /* * Change these and you break ASM code in entry-common.S diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h index d66c48e6ef1..d881f518e6a 100644 --- a/include/asm-frv/thread_info.h +++ b/include/asm-frv/thread_info.h @@ -116,6 +116,7 @@ register struct thread_info *__current_thread_info asm("gr15"); #define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 17 /* OOM killer killed process */ +#define TIF_FREEZE 18 /* freezing for suspend */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) @@ -125,6 +126,7 @@ register struct thread_info *__current_thread_info asm("gr15"); #define _TIF_IRET (1 << TIF_IRET) #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) +#define _TIF_FREEZE (1 << TIF_FREEZE) #define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ #define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */ diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h index 46d32ad9208..4b187bb377b 100644 --- a/include/asm-i386/thread_info.h +++ b/include/asm-i386/thread_info.h @@ -134,6 +134,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_MEMDIE 16 #define TIF_DEBUG 17 /* uses debug registers */ #define TIF_IO_BITMAP 18 /* uses I/O bitmap */ +#define TIF_FREEZE 19 /* is freezing for suspend */ #define _TIF_SYSCALL_TRACE (1<flags & PF_FREEZE; + return test_tsk_thread_flag(p, TIF_FREEZE); } /* * Request that a process be frozen - * FIXME: SMP problem. We may not modify other process' flags! */ static inline void freeze(struct task_struct *p) { - p->flags |= PF_FREEZE; + set_tsk_thread_flag(p, TIF_FREEZE); } /* @@ -33,7 +32,7 @@ static inline void freeze(struct task_struct *p) */ static inline void do_not_freeze(struct task_struct *p) { - p->flags &= ~PF_FREEZE; + clear_tsk_thread_flag(p, TIF_FREEZE); } /* @@ -54,7 +53,9 @@ static inline int thaw_process(struct task_struct *p) */ static inline void frozen_process(struct task_struct *p) { - p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN; + p->flags |= PF_FROZEN; + wmb(); + clear_tsk_thread_flag(p, TIF_FREEZE); } extern void refrigerator(void); diff --git a/include/linux/sched.h b/include/linux/sched.h index ea92e5c8908..44637353519 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1144,7 +1144,6 @@ static inline void put_task_struct(struct task_struct *t) #define PF_MEMALLOC 0x00000800 /* Allocating memory */ #define PF_FLUSHER 0x00001000 /* responsible for disk writeback */ #define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ -#define PF_FREEZE 0x00004000 /* this task is being frozen for suspend now */ #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ #define PF_FROZEN 0x00010000 /* frozen for system suspend */ #define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ diff --git a/kernel/power/process.c b/kernel/power/process.c index b9a32860bef..6d566bf7085 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -60,13 +60,16 @@ static inline void freeze_process(struct task_struct *p) unsigned long flags; if (!freezing(p)) { - if (p->state == TASK_STOPPED) - force_sig_specific(SIGSTOP, p); - - freeze(p); - spin_lock_irqsave(&p->sighand->siglock, flags); - signal_wake_up(p, p->state == TASK_STOPPED); - spin_unlock_irqrestore(&p->sighand->siglock, flags); + rmb(); + if (!frozen(p)) { + if (p->state == TASK_STOPPED) + force_sig_specific(SIGSTOP, p); + + freeze(p); + spin_lock_irqsave(&p->sighand->siglock, flags); + signal_wake_up(p, p->state == TASK_STOPPED); + spin_unlock_irqrestore(&p->sighand->siglock, flags); + } } } -- cgit v1.2.3-70-g09d2 From ec8c0446b6e2b67b5c8813eb517f4bf00efa99a9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 12 Dec 2006 17:14:57 +0000 Subject: [PATCH] Optimize D-cache alias handling on fork Virtually index, physically tagged cache architectures can get away without cache flushing when forking. This patch adds a new cache flushing function flush_cache_dup_mm(struct mm_struct *) which for the moment I've implemented to do the same thing on all architectures except on MIPS where it's a no-op. Signed-off-by: Ralf Baechle Signed-off-by: Linus Torvalds --- Documentation/cachetlb.txt | 23 +++++++++++++++++------ include/asm-alpha/cacheflush.h | 1 + include/asm-arm/cacheflush.h | 2 ++ include/asm-arm26/cacheflush.h | 1 + include/asm-avr32/cacheflush.h | 1 + include/asm-cris/cacheflush.h | 1 + include/asm-frv/cacheflush.h | 1 + include/asm-h8300/cacheflush.h | 1 + include/asm-i386/cacheflush.h | 1 + include/asm-ia64/cacheflush.h | 1 + include/asm-m32r/cacheflush.h | 3 +++ include/asm-m68k/cacheflush.h | 2 ++ include/asm-m68knommu/cacheflush.h | 1 + include/asm-mips/cacheflush.h | 2 ++ include/asm-parisc/cacheflush.h | 2 ++ include/asm-powerpc/cacheflush.h | 1 + include/asm-s390/cacheflush.h | 1 + include/asm-sh/cpu-sh2/cacheflush.h | 2 ++ include/asm-sh/cpu-sh3/cacheflush.h | 3 +++ include/asm-sh/cpu-sh4/cacheflush.h | 1 + include/asm-sh64/cacheflush.h | 2 ++ include/asm-sparc/cacheflush.h | 1 + include/asm-sparc64/cacheflush.h | 1 + include/asm-v850/cacheflush.h | 1 + include/asm-x86_64/cacheflush.h | 1 + include/asm-xtensa/cacheflush.h | 2 ++ kernel/fork.c | 2 +- 27 files changed, 54 insertions(+), 7 deletions(-) (limited to 'include/asm-powerpc') diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt index 53245c429f7..73e794f0ff0 100644 --- a/Documentation/cachetlb.txt +++ b/Documentation/cachetlb.txt @@ -179,10 +179,21 @@ Here are the routines, one by one: lines associated with 'mm'. This interface is used to handle whole address space - page table operations such as what happens during - fork, exit, and exec. + page table operations such as what happens during exit and exec. + +2) void flush_cache_dup_mm(struct mm_struct *mm) + + This interface flushes an entire user address space from + the caches. That is, after running, there will be no cache + lines associated with 'mm'. + + This interface is used to handle whole address space + page table operations such as what happens during fork. + + This option is separate from flush_cache_mm to allow some + optimizations for VIPT caches. -2) void flush_cache_range(struct vm_area_struct *vma, +3) void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) Here we are flushing a specific range of (user) virtual @@ -199,7 +210,7 @@ Here are the routines, one by one: call flush_cache_page (see below) for each entry which may be modified. -3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) +4) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) This time we need to remove a PAGE_SIZE sized range from the cache. The 'vma' is the backing structure used by @@ -220,7 +231,7 @@ Here are the routines, one by one: This is used primarily during fault processing. -4) void flush_cache_kmaps(void) +5) void flush_cache_kmaps(void) This routine need only be implemented if the platform utilizes highmem. It will be called right before all of the kmaps @@ -232,7 +243,7 @@ Here are the routines, one by one: This routing should be implemented in asm/highmem.h -5) void flush_cache_vmap(unsigned long start, unsigned long end) +6) void flush_cache_vmap(unsigned long start, unsigned long end) void flush_cache_vunmap(unsigned long start, unsigned long end) Here in these two interfaces we are flushing a specific range diff --git a/include/asm-alpha/cacheflush.h b/include/asm-alpha/cacheflush.h index 805640b4107..b686cc7fc44 100644 --- a/include/asm-alpha/cacheflush.h +++ b/include/asm-alpha/cacheflush.h @@ -6,6 +6,7 @@ /* Caches aren't brain-dead on the Alpha. */ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_dcache_page(page) do { } while (0) diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index f0845646aac..378a3a2ce8d 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h @@ -319,6 +319,8 @@ extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, unsigned long len, int write); #endif +#define flush_cache_dup_mm(mm) flush_cache_mm(mm) + /* * flush_cache_user_range is used when we want to ensure that the * Harvard caches are synchronised for the user space address range. diff --git a/include/asm-arm26/cacheflush.h b/include/asm-arm26/cacheflush.h index 9c1b9c7f2eb..14ae15b6faa 100644 --- a/include/asm-arm26/cacheflush.h +++ b/include/asm-arm26/cacheflush.h @@ -22,6 +22,7 @@ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma,start,end) do { } while (0) #define flush_cache_page(vma,vmaddr,pfn) do { } while (0) #define flush_cache_vmap(start, end) do { } while (0) diff --git a/include/asm-avr32/cacheflush.h b/include/asm-avr32/cacheflush.h index f1bf1708980..dfaaa88cd41 100644 --- a/include/asm-avr32/cacheflush.h +++ b/include/asm-avr32/cacheflush.h @@ -87,6 +87,7 @@ void invalidate_icache_region(void *start, size_t len); */ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_cache_vmap(start, end) do { } while (0) diff --git a/include/asm-cris/cacheflush.h b/include/asm-cris/cacheflush.h index 72cc71dffe7..01af2de27c5 100644 --- a/include/asm-cris/cacheflush.h +++ b/include/asm-cris/cacheflush.h @@ -9,6 +9,7 @@ */ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_dcache_page(page) do { } while (0) diff --git a/include/asm-frv/cacheflush.h b/include/asm-frv/cacheflush.h index eaa5826bc1c..02500405a6f 100644 --- a/include/asm-frv/cacheflush.h +++ b/include/asm-frv/cacheflush.h @@ -20,6 +20,7 @@ */ #define flush_cache_all() do {} while(0) #define flush_cache_mm(mm) do {} while(0) +#define flush_cache_dup_mm(mm) do {} while(0) #define flush_cache_range(mm, start, end) do {} while(0) #define flush_cache_page(vma, vmaddr, pfn) do {} while(0) #define flush_cache_vmap(start, end) do {} while(0) diff --git a/include/asm-h8300/cacheflush.h b/include/asm-h8300/cacheflush.h index 1e4d95bb5ec..71210d141b6 100644 --- a/include/asm-h8300/cacheflush.h +++ b/include/asm-h8300/cacheflush.h @@ -12,6 +12,7 @@ #define flush_cache_all() #define flush_cache_mm(mm) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma,a,b) #define flush_cache_page(vma,p,pfn) #define flush_dcache_page(page) diff --git a/include/asm-i386/cacheflush.h b/include/asm-i386/cacheflush.h index 7199f7b326f..74e03c8f2e5 100644 --- a/include/asm-i386/cacheflush.h +++ b/include/asm-i386/cacheflush.h @@ -7,6 +7,7 @@ /* Caches aren't brain-dead on the intel. */ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_dcache_page(page) do { } while (0) diff --git a/include/asm-ia64/cacheflush.h b/include/asm-ia64/cacheflush.h index f2dacb4245e..4906916d715 100644 --- a/include/asm-ia64/cacheflush.h +++ b/include/asm-ia64/cacheflush.h @@ -18,6 +18,7 @@ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_icache_page(vma,page) do { } while (0) diff --git a/include/asm-m32r/cacheflush.h b/include/asm-m32r/cacheflush.h index 8b261b49149..56961a9511b 100644 --- a/include/asm-m32r/cacheflush.h +++ b/include/asm-m32r/cacheflush.h @@ -9,6 +9,7 @@ extern void _flush_cache_copyback_all(void); #if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_dcache_page(page) do { } while (0) @@ -29,6 +30,7 @@ extern void smp_flush_cache_all(void); #elif defined(CONFIG_CHIP_M32102) #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_dcache_page(page) do { } while (0) @@ -41,6 +43,7 @@ extern void smp_flush_cache_all(void); #else #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_dcache_page(page) do { } while (0) diff --git a/include/asm-m68k/cacheflush.h b/include/asm-m68k/cacheflush.h index 24d3ff44913..16bf375fdbe 100644 --- a/include/asm-m68k/cacheflush.h +++ b/include/asm-m68k/cacheflush.h @@ -89,6 +89,8 @@ static inline void flush_cache_mm(struct mm_struct *mm) __flush_cache_030(); } +#define flush_cache_dup_mm(mm) flush_cache_mm(mm) + /* flush_cache_range/flush_cache_page must be macros to avoid a dependency on linux/mm.h, which includes this file... */ static inline void flush_cache_range(struct vm_area_struct *vma, diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h index c3aadf3b0d8..163dcb1a968 100644 --- a/include/asm-m68knommu/cacheflush.h +++ b/include/asm-m68knommu/cacheflush.h @@ -8,6 +8,7 @@ #define flush_cache_all() __flush_cache_all() #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) __flush_cache_all() #define flush_cache_page(vma, vmaddr) do { } while (0) #define flush_dcache_range(start,len) __flush_cache_all() diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h index e3c9925876a..0ddada3bb0b 100644 --- a/include/asm-mips/cacheflush.h +++ b/include/asm-mips/cacheflush.h @@ -17,6 +17,7 @@ * * - flush_cache_all() flushes entire cache * - flush_cache_mm(mm) flushes the specified mm context's cache lines + * - flush_cache_dup mm(mm) handles cache flushing when forking * - flush_cache_page(mm, vmaddr, pfn) flushes a single page * - flush_cache_range(vma, start, end) flushes a range of pages * - flush_icache_range(start, end) flush a range of instructions @@ -31,6 +32,7 @@ extern void (*flush_cache_all)(void); extern void (*__flush_cache_all)(void); extern void (*flush_cache_mm)(struct mm_struct *mm); +#define flush_cache_dup_mm(mm) do { (void) (mm); } while (0) extern void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h index 2bc41f2e027..aedb0512cb0 100644 --- a/include/asm-parisc/cacheflush.h +++ b/include/asm-parisc/cacheflush.h @@ -15,6 +15,8 @@ #define flush_cache_mm(mm) flush_cache_all_local() #endif +#define flush_cache_dup_mm(mm) flush_cache_mm(mm) + #define flush_kernel_dcache_range(start,size) \ flush_kernel_dcache_range_asm((start), (start)+(size)); diff --git a/include/asm-powerpc/cacheflush.h b/include/asm-powerpc/cacheflush.h index 8a740c88d93..08e93e78921 100644 --- a/include/asm-powerpc/cacheflush.h +++ b/include/asm-powerpc/cacheflush.h @@ -18,6 +18,7 @@ */ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_icache_page(vma, page) do { } while (0) diff --git a/include/asm-s390/cacheflush.h b/include/asm-s390/cacheflush.h index e399a8ba2ed..f7cade8083f 100644 --- a/include/asm-s390/cacheflush.h +++ b/include/asm-s390/cacheflush.h @@ -7,6 +7,7 @@ /* Caches aren't brain-dead on the s390. */ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_dcache_page(page) do { } while (0) diff --git a/include/asm-sh/cpu-sh2/cacheflush.h b/include/asm-sh/cpu-sh2/cacheflush.h index f556fa80ea9..2979efb26de 100644 --- a/include/asm-sh/cpu-sh2/cacheflush.h +++ b/include/asm-sh/cpu-sh2/cacheflush.h @@ -15,6 +15,7 @@ * * - flush_cache_all() flushes entire cache * - flush_cache_mm(mm) flushes the specified mm context's cache lines + * - flush_cache_dup mm(mm) handles cache flushing when forking * - flush_cache_page(mm, vmaddr, pfn) flushes a single page * - flush_cache_range(vma, start, end) flushes a range of pages * @@ -27,6 +28,7 @@ */ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_dcache_page(page) do { } while (0) diff --git a/include/asm-sh/cpu-sh3/cacheflush.h b/include/asm-sh/cpu-sh3/cacheflush.h index 03fde97a7fd..f70d8ef76a1 100644 --- a/include/asm-sh/cpu-sh3/cacheflush.h +++ b/include/asm-sh/cpu-sh3/cacheflush.h @@ -15,6 +15,7 @@ * * - flush_cache_all() flushes entire cache * - flush_cache_mm(mm) flushes the specified mm context's cache lines + * - flush_cache_dup mm(mm) handles cache flushing when forking * - flush_cache_page(mm, vmaddr, pfn) flushes a single page * - flush_cache_range(vma, start, end) flushes a range of pages * @@ -39,6 +40,7 @@ void flush_cache_all(void); void flush_cache_mm(struct mm_struct *mm); +#define flush_cache_dup_mm(mm) flush_cache_mm(mm) void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn); @@ -48,6 +50,7 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page); #else #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_dcache_page(page) do { } while (0) diff --git a/include/asm-sh/cpu-sh4/cacheflush.h b/include/asm-sh/cpu-sh4/cacheflush.h index 515fd574267..b01a10f3122 100644 --- a/include/asm-sh/cpu-sh4/cacheflush.h +++ b/include/asm-sh/cpu-sh4/cacheflush.h @@ -18,6 +18,7 @@ */ void flush_cache_all(void); void flush_cache_mm(struct mm_struct *mm); +#define flush_cache_dup_mm(mm) flush_cache_mm(mm) void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, diff --git a/include/asm-sh64/cacheflush.h b/include/asm-sh64/cacheflush.h index 55f71aa0aa6..1e53a47bdc9 100644 --- a/include/asm-sh64/cacheflush.h +++ b/include/asm-sh64/cacheflush.h @@ -21,6 +21,8 @@ extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, unsigned long addr, int len); +#define flush_cache_dup_mm(mm) flush_cache_mm(mm) + #define flush_dcache_mmap_lock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0) diff --git a/include/asm-sparc/cacheflush.h b/include/asm-sparc/cacheflush.h index fc632f811cd..68ac1091027 100644 --- a/include/asm-sparc/cacheflush.h +++ b/include/asm-sparc/cacheflush.h @@ -48,6 +48,7 @@ BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long) #define flush_cache_all() BTFIXUP_CALL(flush_cache_all)() #define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm) +#define flush_cache_dup_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm) #define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end) #define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr) #define flush_icache_range(start, end) do { } while (0) diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h index 745d1ab6037..122e4058dd9 100644 --- a/include/asm-sparc64/cacheflush.h +++ b/include/asm-sparc64/cacheflush.h @@ -12,6 +12,7 @@ /* These are the same regardless of whether this is an SMP kernel or not. */ #define flush_cache_mm(__mm) \ do { if ((__mm) == current->mm) flushw_user(); } while(0) +#define flush_cache_dup_mm(mm) flush_cache_mm(mm) #define flush_cache_range(vma, start, end) \ flush_cache_mm((vma)->vm_mm) #define flush_cache_page(vma, page, pfn) \ diff --git a/include/asm-v850/cacheflush.h b/include/asm-v850/cacheflush.h index e1a87f82f1a..9ece05a202e 100644 --- a/include/asm-v850/cacheflush.h +++ b/include/asm-v850/cacheflush.h @@ -24,6 +24,7 @@ systems with MMUs, so we don't need them. */ #define flush_cache_all() ((void)0) #define flush_cache_mm(mm) ((void)0) +#define flush_cache_dup_mm(mm) ((void)0) #define flush_cache_range(vma, start, end) ((void)0) #define flush_cache_page(vma, vmaddr, pfn) ((void)0) #define flush_dcache_page(page) ((void)0) diff --git a/include/asm-x86_64/cacheflush.h b/include/asm-x86_64/cacheflush.h index d32f7f58752..ab1cb5c7dc9 100644 --- a/include/asm-x86_64/cacheflush.h +++ b/include/asm-x86_64/cacheflush.h @@ -7,6 +7,7 @@ /* Caches aren't brain-dead on the intel. */ #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) #define flush_dcache_page(page) do { } while (0) diff --git a/include/asm-xtensa/cacheflush.h b/include/asm-xtensa/cacheflush.h index 337765b629d..22ef901b784 100644 --- a/include/asm-xtensa/cacheflush.h +++ b/include/asm-xtensa/cacheflush.h @@ -75,6 +75,7 @@ extern void __flush_invalidate_dcache_range(unsigned long, unsigned long); #define flush_cache_all() __flush_invalidate_cache_all(); #define flush_cache_mm(mm) __flush_invalidate_cache_all(); +#define flush_cache_dup_mm(mm) __flush_invalidate_cache_all(); #define flush_cache_vmap(start,end) __flush_invalidate_cache_all(); #define flush_cache_vunmap(start,end) __flush_invalidate_cache_all(); @@ -88,6 +89,7 @@ extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned lon #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_vmap(start,end) do { } while (0) #define flush_cache_vunmap(start,end) do { } while (0) diff --git a/kernel/fork.c b/kernel/fork.c index d16c566eb64..fc723e595cd 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -203,7 +203,7 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) struct mempolicy *pol; down_write(&oldmm->mmap_sem); - flush_cache_mm(oldmm); + flush_cache_dup_mm(oldmm); /* * Not linked in yet - no deadlock potential: */ -- cgit v1.2.3-70-g09d2 From f1fa16e8816a2285ed77070ce60a6858fb7913cc Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 19 Dec 2006 15:32:42 +0100 Subject: [POWERPC] cell: add forward struct declarations to spu.h Needed to be able to include spu.h independant from other headers. Signed-off-by: Arnd Bergmann --- include/asm-powerpc/spu.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index fdad4267b44..3d90264e9d3 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -161,6 +161,7 @@ struct spu_syscall_block { extern long spu_sys_callback(struct spu_syscall_block *s); /* syscalls implemented in spufs */ +struct file; extern struct spufs_calls { asmlinkage long (*create_thread)(const char __user *name, unsigned int flags, mode_t mode); @@ -232,6 +233,7 @@ void spu_remove_sysdev_attr_group(struct attribute_group *attrs); * to object-id spufs file from user space and the notifer * function can assume that spu->ctx is valid. */ +struct notifier_block; int spu_switch_event_register(struct notifier_block * n); int spu_switch_event_unregister(struct notifier_block * n); -- cgit v1.2.3-70-g09d2 From 007d88d042d7b71aa2c9fc615aef97888e20ddf3 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 1 Jan 2007 18:45:34 +0000 Subject: [POWERPC] Fix manual assembly WARN_ON() in enter_rtas(). When we switched over to the generic BUG mechanism we forgot to change the assembly code which open-codes a WARN_ON() in enter_rtas(), so the bug table got corrupted. This patch provides an EMIT_BUG_ENTRY macro for use in assembly code, and uses it in entry_64.S. Tested with CONFIG_DEBUG_BUGVERBOSE on ppc64 but not without -- I tried to turn it off but it wouldn't go away; I suspect Aunt Tillie probably needed it. This version gets __FILE__ and __LINE__ right in the assembly version -- rather than saying include/asm-powerpc/bug.h line 21 every time which is a little suboptimal. Signed-off-by: David Woodhouse Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/asm-offsets.c | 3 +++ arch/powerpc/kernel/entry_64.S | 13 +++++-------- include/asm-powerpc/bug.h | 27 ++++++++++++++++++++++++--- 3 files changed, 32 insertions(+), 11 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index e96521530d2..030d300cd71 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -303,5 +303,8 @@ int main(void) DEFINE(NSEC_PER_SEC, NSEC_PER_SEC); DEFINE(CLOCK_REALTIME_RES, TICK_NSEC); +#ifdef CONFIG_BUG + DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry)); +#endif return 0; } diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 1a3d4de197d..2551c0884af 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -28,6 +28,7 @@ #include #include #include +#include /* * System calls. @@ -634,19 +635,15 @@ _GLOBAL(enter_rtas) li r0,0 mtcr r0 +#ifdef CONFIG_BUG /* There is no way it is acceptable to get here with interrupts enabled, * check it with the asm equivalent of WARN_ON */ lbz r0,PACASOFTIRQEN(r13) 1: tdnei r0,0 -.section __bug_table,"a" - .llong 1b,__LINE__ + 0x1000000, 1f, 2f -.previous -.section .rodata,"a" -1: .asciz __FILE__ -2: .asciz "enter_rtas" -.previous - + EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING +#endif + /* Hard-disable interrupts */ mfmsr r6 rldicl r7,r6,48,1 diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h index 709568879f7..f6fa3947484 100644 --- a/include/asm-powerpc/bug.h +++ b/include/asm-powerpc/bug.h @@ -11,10 +11,31 @@ #define BUG_OPCODE .long 0x00b00b00 /* For asm */ #define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */ -#ifndef __ASSEMBLY__ - #ifdef CONFIG_BUG +#ifdef __ASSEMBLY__ +#ifdef CONFIG_DEBUG_BUGVERBOSE +.macro EMIT_BUG_ENTRY addr,file,line,flags + .section __bug_table,"a" +5001: PPC_LONG \addr, 5002f + .short \line, \flags + .org 5001b+BUG_ENTRY_SIZE + .previous + .section .rodata,"a" +5002: .asciz "\file" + .previous +.endm +#else + .macro EMIT_BUG_ENTRY addr,file,line,flags + .section __bug_table,"a" +5001: PPC_LONG \addr + .short \flags + .org 5001b+BUG_ENTRY_SIZE + .previous +.endm +#endif /* verbose */ + +#else /* !__ASSEMBLY__ */ /* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and sizeof(struct bug_entry), respectively */ #ifdef CONFIG_DEBUG_BUGVERBOSE @@ -91,8 +112,8 @@ #define HAVE_ARCH_BUG #define HAVE_ARCH_BUG_ON #define HAVE_ARCH_WARN_ON -#endif /* CONFIG_BUG */ #endif /* __ASSEMBLY __ */ +#endif /* CONFIG_BUG */ #include -- cgit v1.2.3-70-g09d2 From 5c334eed6ecd66cebfbc80267149e755510d8bc8 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Tue, 2 Jan 2007 23:29:53 +0100 Subject: [POWERPC] 52xx: Don't use device_initcall to probe of_platform_bus Using device_initcall makes it happen for every platform that compiles this file in. This is really bad, for obvious reasons. Instead, we use the .init field of the machine description. If the platform needs the hook to do something specific it can provides its own function and call mpc52xx_declare_of_platform_devices from there. If not, the mpc52xx_declare_of_platform_devices function can directly be used as the init hook. Signed-off-by: Sylvain Munaut Acked-by: Grant Likely Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/52xx/lite5200.c | 1 + arch/powerpc/platforms/52xx/mpc52xx_common.c | 7 ++++--- include/asm-powerpc/mpc52xx.h | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index eaff71e74fb..0f21bab33f6 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c @@ -153,6 +153,7 @@ define_machine(lite52xx) { .name = "lite52xx", .probe = lite52xx_probe, .setup_arch = lite52xx_setup_arch, + .init = mpc52xx_declare_of_platform_devices, .init_IRQ = mpc52xx_init_irq, .get_irq = mpc52xx_get_irq, .show_cpuinfo = lite52xx_show_cpuinfo, diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index 8331ff45777..cc40889074b 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -116,11 +116,12 @@ unmap_regs: if (xlb) iounmap(xlb); } -static int __init +void __init mpc52xx_declare_of_platform_devices(void) { /* Find every child of the SOC node and add it to of_platform */ - return of_platform_bus_probe(NULL, NULL, NULL); + if (of_platform_bus_probe(NULL, NULL, NULL)) + printk(KERN_ERR __FILE__ ": " + "Error while probing of_platform bus\n"); } -device_initcall(mpc52xx_declare_of_platform_devices); diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h index 4a28a850998..4560d72fc75 100644 --- a/include/asm-powerpc/mpc52xx.h +++ b/include/asm-powerpc/mpc52xx.h @@ -244,6 +244,7 @@ struct mpc52xx_cdm { extern void __iomem * mpc52xx_find_and_map(const char *); extern unsigned int mpc52xx_find_ipb_freq(struct device_node *node); extern void mpc52xx_setup_cpu(void); +extern void mpc52xx_declare_of_platform_devices(void); extern void mpc52xx_init_irq(void); extern unsigned int mpc52xx_get_irq(void); -- cgit v1.2.3-70-g09d2 From dc40127ca5c6e1da48d2b5f9d0c65b5795faac12 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 9 Jan 2007 02:43:02 +1100 Subject: [POWERPC] Fix bugs in the hypervisor call stats code There were a few issues with the HCALL_STATS code: - PURR cpu feature checks were backwards - We iterated one entry off the end of the hcall_stats array - Remove dead update_hcall_stats() function prototype I noticed one thing while debugging, and that is we call H_ENTER (to set up the MMU hashtable in early init) before we have done the cpu fixups. This means we will execute the PURR SPR reads even on a CPU that isnt capable of it. I wonder if we can move the CPU feature fixups earlier. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/hvCall.S | 6 +++--- arch/powerpc/platforms/pseries/hvCall_inst.c | 4 ++-- include/asm-powerpc/hvcall.h | 2 -- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'include/asm-powerpc') diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 527da445aaa..5c7e3878989 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S @@ -26,7 +26,7 @@ BEGIN_FTR_SECTION; \ mfspr r0,SPRN_PURR; /* get PURR and */ \ std r0,STK_PARM(r6)(r1); /* save for later */ \ -END_FTR_SECTION_IFCLR(CPU_FTR_PURR); +END_FTR_SECTION_IFSET(CPU_FTR_PURR); /* * postcall is performed immediately before function return which @@ -43,7 +43,7 @@ BEGIN_FTR_SECTION; \ mfspr r8,SPRN_PURR; /* PURR after */ \ ld r6,STK_PARM(r6)(r1); /* PURR before */ \ subf r6,r6,r8; /* delta */ \ -END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ +END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ ld r5,STK_PARM(r5)(r1); /* timebase before */ \ subf r5,r5,r7; /* time delta */ \ \ @@ -66,7 +66,7 @@ BEGIN_FTR_SECTION; \ ld r7,HCALL_STAT_PURR(r4); /* PURR */ \ add r7,r7,r6; \ std r7,HCALL_STAT_PURR(r4); \ -END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ +END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ 1: #else #define HCALL_INST_PRECALL diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c index 80181c4c49e..3ddc04925d5 100644 --- a/arch/powerpc/platforms/pseries/hvCall_inst.c +++ b/arch/powerpc/platforms/pseries/hvCall_inst.c @@ -34,7 +34,7 @@ DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats); */ static void *hc_start(struct seq_file *m, loff_t *pos) { - if ((int)*pos < HCALL_STAT_ARRAY_SIZE) + if ((int)*pos < (HCALL_STAT_ARRAY_SIZE-1)) return (void *)(unsigned long)(*pos + 1); return NULL; @@ -57,7 +57,7 @@ static int hc_show(struct seq_file *m, void *p) struct hcall_stats *hs = (struct hcall_stats *)m->private; if (hs[h_num].num_calls) { - if (!cpu_has_feature(CPU_FTR_PURR)) + if (cpu_has_feature(CPU_FTR_PURR)) seq_printf(m, "%lu %lu %lu %lu\n", h_num<<2, hs[h_num].num_calls, hs[h_num].tb_total, diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h index 257d1cecb8c..7a500732b67 100644 --- a/include/asm-powerpc/hvcall.h +++ b/include/asm-powerpc/hvcall.h @@ -252,8 +252,6 @@ struct hcall_stats { unsigned long tb_total; /* total wall time (mftb) of calls. */ unsigned long purr_total; /* total cpu time (PURR) of calls. */ }; -void update_hcall_stats(unsigned long opcode, unsigned long tb_delta, - unsigned long purr_delta); #define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1) #endif /* __ASSEMBLY__ */ -- cgit v1.2.3-70-g09d2 From aae7d14f619c665b83e07013e3dda8694ea3e40b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 10 Jan 2007 23:15:45 -0800 Subject: [PATCH] FD_ZERO build fix unionfs managed to hit this on s390. Some architectures use __ptr_t in their FD_ZERO implementation. We don't have a __ptr_t. Switch them over to plain old void*. Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Al Viro Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: "Luck, Tony" Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: Josef 'Jeff' Sipek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-alpha/posix_types.h | 2 +- include/asm-ia64/posix_types.h | 2 +- include/asm-powerpc/posix_types.h | 2 +- include/asm-s390/posix_types.h | 2 +- include/asm-xtensa/posix_types.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include/asm-powerpc') diff --git a/include/asm-alpha/posix_types.h b/include/asm-alpha/posix_types.h index c78c04a94f4..db167413300 100644 --- a/include/asm-alpha/posix_types.h +++ b/include/asm-alpha/posix_types.h @@ -49,7 +49,7 @@ typedef unsigned int __kernel_old_dev_t; #define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) #define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0) #define __FD_ZERO(set) \ - ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) + ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set))) #else /* __GNUC__ */ diff --git a/include/asm-ia64/posix_types.h b/include/asm-ia64/posix_types.h index adb62272694..17885567b73 100644 --- a/include/asm-ia64/posix_types.h +++ b/include/asm-ia64/posix_types.h @@ -54,7 +54,7 @@ typedef unsigned int __kernel_old_dev_t; #define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) #define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0) #define __FD_ZERO(set) \ - ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) + ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set))) # else /* !__GNUC__ */ diff --git a/include/asm-powerpc/posix_types.h b/include/asm-powerpc/posix_types.h index c6391077224..2f2288f520b 100644 --- a/include/asm-powerpc/posix_types.h +++ b/include/asm-powerpc/posix_types.h @@ -60,7 +60,7 @@ typedef struct { #define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) #define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0) #define __FD_ZERO(set) \ - ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) + ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set))) #else /* __GNUC__ */ diff --git a/include/asm-s390/posix_types.h b/include/asm-s390/posix_types.h index b94c98856e1..397d93fba3a 100644 --- a/include/asm-s390/posix_types.h +++ b/include/asm-s390/posix_types.h @@ -104,7 +104,7 @@ static inline int __FD_ISSET(unsigned long fd, const __kernel_fd_set *fdsetp) #undef __FD_ZERO #define __FD_ZERO(fdsetp) \ - ((void) memset ((__ptr_t) (fdsetp), 0, sizeof (__kernel_fd_set))) + ((void) memset ((void *) (fdsetp), 0, sizeof (__kernel_fd_set))) #endif /* __KERNEL__ */ diff --git a/include/asm-xtensa/posix_types.h b/include/asm-xtensa/posix_types.h index 3470b44c12c..4ad77dda6d5 100644 --- a/include/asm-xtensa/posix_types.h +++ b/include/asm-xtensa/posix_types.h @@ -60,7 +60,7 @@ typedef struct { #define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) #define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) #define __FD_ZERO(set) \ - ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) + ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set))) #else /* __GNUC__ */ -- cgit v1.2.3-70-g09d2