提交 57260e40 编写于 作者: A Arnd Bergmann

Merge tag 'imx-fixes-rc' of git://git.pengutronix.de/git/imx/linux-2.6 into fixes

From Sascha Hauer <s.hauer@pengutronix.de>:

ARM i.MX fixes for 3.7-rc

* tag 'imx-fixes-rc' of git://git.pengutronix.de/git/imx/linux-2.6:
  ARM: imx: ehci: fix host power mask bit
  ARM i.MX: fix error-valued pointer dereference in clk_register_gate2()
Signed-off-by: NArnd Bergmann <arnd@arndb.de>
...@@ -27,17 +27,17 @@ Start End Size Use ...@@ -27,17 +27,17 @@ Start End Size Use
----------------------------------------------------------------------- -----------------------------------------------------------------------
0000000000000000 0000007fffffffff 512GB user 0000000000000000 0000007fffffffff 512GB user
ffffff8000000000 ffffffbbfffcffff ~240GB vmalloc ffffff8000000000 ffffffbbfffeffff ~240GB vmalloc
ffffffbbfffd0000 ffffffbcfffdffff 64KB [guard page] ffffffbbffff0000 ffffffbbffffffff 64KB [guard page]
ffffffbbfffe0000 ffffffbcfffeffff 64KB PCI I/O space ffffffbc00000000 ffffffbdffffffff 8GB vmemmap
ffffffbbffff0000 ffffffbcffffffff 64KB [guard page] ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap]
ffffffbc00000000 ffffffbdffffffff 8GB vmemmap ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space
ffffffbe00000000 ffffffbffbffffff ~8GB [guard, future vmmemap] ffffffbbffff0000 ffffffbcffffffff ~2MB [guard]
ffffffbffc000000 ffffffbfffffffff 64MB modules ffffffbffc000000 ffffffbfffffffff 64MB modules
......
VERSION = 3 VERSION = 3
PATCHLEVEL = 7 PATCHLEVEL = 7
SUBLEVEL = 0 SUBLEVEL = 0
EXTRAVERSION = -rc4 EXTRAVERSION = -rc5
NAME = Terrified Chipmunk NAME = Terrified Chipmunk
# *DOCUMENTATION* # *DOCUMENTATION*
......
...@@ -64,7 +64,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); ...@@ -64,7 +64,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
static inline void __raw_writew(u16 val, volatile void __iomem *addr) static inline void __raw_writew(u16 val, volatile void __iomem *addr)
{ {
asm volatile("strh %1, %0" asm volatile("strh %1, %0"
: "+Qo" (*(volatile u16 __force *)addr) : "+Q" (*(volatile u16 __force *)addr)
: "r" (val)); : "r" (val));
} }
...@@ -72,7 +72,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr) ...@@ -72,7 +72,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
{ {
u16 val; u16 val;
asm volatile("ldrh %1, %0" asm volatile("ldrh %1, %0"
: "+Qo" (*(volatile u16 __force *)addr), : "+Q" (*(volatile u16 __force *)addr),
"=r" (val)); "=r" (val));
return val; return val;
} }
......
...@@ -10,7 +10,5 @@ ...@@ -10,7 +10,5 @@
extern void sched_clock_postinit(void); extern void sched_clock_postinit(void);
extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
unsigned long rate);
#endif #endif
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
#if __LINUX_ARM_ARCH__ <= 6 #if __LINUX_ARM_ARCH__ <= 6
ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, =elf_hwcap @ may not have MVFR regs
ldr \tmp, [\tmp, #0] ldr \tmp, [\tmp, #0]
tst \tmp, #HWCAP_VFPv3D16 tst \tmp, #HWCAP_VFPD32
ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} ldcnel p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31}
addne \base, \base, #32*4 @ step over unused register space addeq \base, \base, #32*4 @ step over unused register space
#else #else
VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0
and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field
...@@ -51,9 +51,9 @@ ...@@ -51,9 +51,9 @@
#if __LINUX_ARM_ARCH__ <= 6 #if __LINUX_ARM_ARCH__ <= 6
ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, =elf_hwcap @ may not have MVFR regs
ldr \tmp, [\tmp, #0] ldr \tmp, [\tmp, #0]
tst \tmp, #HWCAP_VFPv3D16 tst \tmp, #HWCAP_VFPD32
stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} stcnel p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31}
addne \base, \base, #32*4 @ step over unused register space addeq \base, \base, #32*4 @ step over unused register space
#else #else
VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0
and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field
......
...@@ -18,11 +18,12 @@ ...@@ -18,11 +18,12 @@
#define HWCAP_THUMBEE (1 << 11) #define HWCAP_THUMBEE (1 << 11)
#define HWCAP_NEON (1 << 12) #define HWCAP_NEON (1 << 12)
#define HWCAP_VFPv3 (1 << 13) #define HWCAP_VFPv3 (1 << 13)
#define HWCAP_VFPv3D16 (1 << 14) #define HWCAP_VFPv3D16 (1 << 14) /* also set for VFPv4-D16 */
#define HWCAP_TLS (1 << 15) #define HWCAP_TLS (1 << 15)
#define HWCAP_VFPv4 (1 << 16) #define HWCAP_VFPv4 (1 << 16)
#define HWCAP_IDIVA (1 << 17) #define HWCAP_IDIVA (1 << 17)
#define HWCAP_IDIVT (1 << 18) #define HWCAP_IDIVT (1 << 18)
#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */
#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) #define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT)
......
...@@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks) ...@@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks)
update_sched_clock(); update_sched_clock();
} }
void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
unsigned long rate)
{
setup_sched_clock(read, bits, rate);
cd.needs_suspend = true;
}
void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
{ {
unsigned long r, w; unsigned long r, w;
...@@ -189,18 +182,15 @@ void __init sched_clock_postinit(void) ...@@ -189,18 +182,15 @@ void __init sched_clock_postinit(void)
static int sched_clock_suspend(void) static int sched_clock_suspend(void)
{ {
sched_clock_poll(sched_clock_timer.data); sched_clock_poll(sched_clock_timer.data);
if (cd.needs_suspend) cd.suspended = true;
cd.suspended = true;
return 0; return 0;
} }
static void sched_clock_resume(void) static void sched_clock_resume(void)
{ {
if (cd.needs_suspend) { cd.epoch_cyc = read_sched_clock();
cd.epoch_cyc = read_sched_clock(); cd.epoch_cyc_copy = cd.epoch_cyc;
cd.epoch_cyc_copy = cd.epoch_cyc; cd.suspended = false;
cd.suspended = false;
}
} }
static struct syscore_ops sched_clock_ops = { static struct syscore_ops sched_clock_ops = {
......
...@@ -112,7 +112,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name, ...@@ -112,7 +112,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
clk = clk_register(dev, &gate->hw); clk = clk_register(dev, &gate->hw);
if (IS_ERR(clk)) if (IS_ERR(clk))
kfree(clk); kfree(gate);
return clk; return clk;
} }
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define MX25_H1_SIC_SHIFT 21 #define MX25_H1_SIC_SHIFT 21
#define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT) #define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT)
#define MX25_H1_PP_BIT (1 << 18) #define MX25_H1_PP_BIT (1 << 18)
#define MX25_H1_PM_BIT (1 << 8) #define MX25_H1_PM_BIT (1 << 16)
#define MX25_H1_IPPUE_UP_BIT (1 << 7) #define MX25_H1_IPPUE_UP_BIT (1 << 7)
#define MX25_H1_IPPUE_DOWN_BIT (1 << 6) #define MX25_H1_IPPUE_DOWN_BIT (1 << 6)
#define MX25_H1_TLL_BIT (1 << 5) #define MX25_H1_TLL_BIT (1 << 5)
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define MX35_H1_SIC_SHIFT 21 #define MX35_H1_SIC_SHIFT 21
#define MX35_H1_SIC_MASK (0x3 << MX35_H1_SIC_SHIFT) #define MX35_H1_SIC_MASK (0x3 << MX35_H1_SIC_SHIFT)
#define MX35_H1_PP_BIT (1 << 18) #define MX35_H1_PP_BIT (1 << 18)
#define MX35_H1_PM_BIT (1 << 8) #define MX35_H1_PM_BIT (1 << 16)
#define MX35_H1_IPPUE_UP_BIT (1 << 7) #define MX35_H1_IPPUE_UP_BIT (1 << 7)
#define MX35_H1_IPPUE_DOWN_BIT (1 << 6) #define MX35_H1_IPPUE_DOWN_BIT (1 << 6)
#define MX35_H1_TLL_BIT (1 << 5) #define MX35_H1_TLL_BIT (1 << 5)
......
...@@ -745,7 +745,7 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs, ...@@ -745,7 +745,7 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
static int static int
do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{ {
union offset_union offset; union offset_union uninitialized_var(offset);
unsigned long instr = 0, instrptr; unsigned long instr = 0, instrptr;
int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs); int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
unsigned int type; unsigned int type;
......
...@@ -701,11 +701,14 @@ static int __init vfp_init(void) ...@@ -701,11 +701,14 @@ static int __init vfp_init(void)
elf_hwcap |= HWCAP_VFPv3; elf_hwcap |= HWCAP_VFPv3;
/* /*
* Check for VFPv3 D16. CPUs in this configuration * Check for VFPv3 D16 and VFPv4 D16. CPUs in
* only have 16 x 64bit registers. * this configuration only have 16 x 64bit
* registers.
*/ */
if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1) if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1)
elf_hwcap |= HWCAP_VFPv3D16; elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */
else
elf_hwcap |= HWCAP_VFPD32;
} }
#endif #endif
/* /*
......
...@@ -166,3 +166,14 @@ void free_xenballooned_pages(int nr_pages, struct page **pages) ...@@ -166,3 +166,14 @@ void free_xenballooned_pages(int nr_pages, struct page **pages)
*pages = NULL; *pages = NULL;
} }
EXPORT_SYMBOL_GPL(free_xenballooned_pages); EXPORT_SYMBOL_GPL(free_xenballooned_pages);
/* In the hypervisor.S file. */
EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
EXPORT_SYMBOL_GPL(HYPERVISOR_xen_version);
EXPORT_SYMBOL_GPL(HYPERVISOR_console_io);
EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op);
EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op);
EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op);
EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op);
EXPORT_SYMBOL_GPL(privcmd_call);
config ARM64 config ARM64
def_bool y def_bool y
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select GENERIC_HARDIRQS_NO_DEPRECATED select GENERIC_HARDIRQS_NO_DEPRECATED
select GENERIC_IOMAP select GENERIC_IOMAP
......
...@@ -25,12 +25,10 @@ ...@@ -25,12 +25,10 @@
#include <asm/user.h> #include <asm/user.h>
typedef unsigned long elf_greg_t; typedef unsigned long elf_greg_t;
typedef unsigned long elf_freg_t[3];
#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef struct user_fpsimd_state elf_fpregset_t;
typedef struct user_fp elf_fpregset_t;
#define EM_AARCH64 183 #define EM_AARCH64 183
...@@ -87,7 +85,6 @@ typedef struct user_fp elf_fpregset_t; ...@@ -87,7 +85,6 @@ typedef struct user_fp elf_fpregset_t;
#define R_AARCH64_MOVW_PREL_G2_NC 292 #define R_AARCH64_MOVW_PREL_G2_NC 292
#define R_AARCH64_MOVW_PREL_G3 293 #define R_AARCH64_MOVW_PREL_G3 293
/* /*
* These are used to set parameters in the core dumps. * These are used to set parameters in the core dumps.
*/ */
......
...@@ -25,9 +25,8 @@ ...@@ -25,9 +25,8 @@
* - FPSR and FPCR * - FPSR and FPCR
* - 32 128-bit data registers * - 32 128-bit data registers
* *
* Note that user_fp forms a prefix of this structure, which is relied * Note that user_fpsimd forms a prefix of this structure, which is
* upon in the ptrace FP/SIMD accessors. struct user_fpsimd_state must * relied upon in the ptrace FP/SIMD accessors.
* form a prefix of struct fpsimd_state.
*/ */
struct fpsimd_state { struct fpsimd_state {
union { union {
......
...@@ -114,7 +114,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) ...@@ -114,7 +114,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
* I/O port access primitives. * I/O port access primitives.
*/ */
#define IO_SPACE_LIMIT 0xffff #define IO_SPACE_LIMIT 0xffff
#define PCI_IOBASE ((void __iomem *)0xffffffbbfffe0000UL) #define PCI_IOBASE ((void __iomem *)(MODULES_VADDR - SZ_2M))
static inline u8 inb(unsigned long addr) static inline u8 inb(unsigned long addr)
{ {
...@@ -225,9 +225,9 @@ extern void __iounmap(volatile void __iomem *addr); ...@@ -225,9 +225,9 @@ extern void __iounmap(volatile void __iomem *addr);
#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC)) #define PROT_NORMAL_NC (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
#define ioremap(addr, size) __ioremap((addr), (size), PROT_DEVICE_nGnRE) #define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
#define ioremap_nocache(addr, size) __ioremap((addr), (size), PROT_DEVICE_nGnRE) #define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
#define ioremap_wc(addr, size) __ioremap((addr), (size), PROT_NORMAL_NC) #define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
#define iounmap __iounmap #define iounmap __iounmap
#define ARCH_HAS_IOREMAP_WC #define ARCH_HAS_IOREMAP_WC
......
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#else #else
#define STACK_TOP STACK_TOP_MAX #define STACK_TOP STACK_TOP_MAX
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
#define ARCH_LOW_ADDRESS_LIMIT PHYS_MASK
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
struct debug_info { struct debug_info {
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION
#define __ARCH_WANT_COMPAT_STAT64 #define __ARCH_WANT_COMPAT_STAT64
#define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE #define __ARCH_WANT_SYS_PAUSE
......
...@@ -613,17 +613,11 @@ enum armv8_pmuv3_perf_types { ...@@ -613,17 +613,11 @@ enum armv8_pmuv3_perf_types {
ARMV8_PMUV3_PERFCTR_BUS_ACCESS = 0x19, ARMV8_PMUV3_PERFCTR_BUS_ACCESS = 0x19,
ARMV8_PMUV3_PERFCTR_MEM_ERROR = 0x1A, ARMV8_PMUV3_PERFCTR_MEM_ERROR = 0x1A,
ARMV8_PMUV3_PERFCTR_BUS_CYCLES = 0x1D, ARMV8_PMUV3_PERFCTR_BUS_CYCLES = 0x1D,
/*
* This isn't an architected event.
* We detect this event number and use the cycle counter instead.
*/
ARMV8_PMUV3_PERFCTR_CPU_CYCLES = 0xFF,
}; };
/* PMUv3 HW events mapping. */ /* PMUv3 HW events mapping. */
static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES, [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED, [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
[PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
[PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
...@@ -1106,7 +1100,7 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc, ...@@ -1106,7 +1100,7 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,
unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT; unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT;
/* Always place a cycle counter into the cycle counter. */ /* Always place a cycle counter into the cycle counter. */
if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) { if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) {
if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
return -EAGAIN; return -EAGAIN;
......
...@@ -309,24 +309,6 @@ struct task_struct *__switch_to(struct task_struct *prev, ...@@ -309,24 +309,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
return last; return last;
} }
/*
* Fill in the task's elfregs structure for a core dump.
*/
int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
{
elf_core_copy_regs(elfregs, task_pt_regs(t));
return 1;
}
/*
* fill in the fpe structure for a core dump...
*/
int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
{
return 0;
}
EXPORT_SYMBOL(dump_fpu);
/* /*
* Shuffle the argument into the correct register before calling the * Shuffle the argument into the correct register before calling the
* thread function. x1 is the thread argument, x2 is the pointer to * thread function. x1 is the thread argument, x2 is the pointer to
......
...@@ -211,8 +211,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) ...@@ -211,8 +211,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
* before we continue. * before we continue.
*/ */
set_cpu_online(cpu, true); set_cpu_online(cpu, true);
while (!cpu_active(cpu)) complete(&cpu_running);
cpu_relax();
/* /*
* OK, it's off to the idle thread for us * OK, it's off to the idle thread for us
......
...@@ -80,7 +80,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) ...@@ -80,7 +80,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
#ifdef CONFIG_ZONE_DMA32 #ifdef CONFIG_ZONE_DMA32
/* 4GB maximum for 32-bit only capable devices */ /* 4GB maximum for 32-bit only capable devices */
max_dma32 = min(max, MAX_DMA32_PFN); max_dma32 = min(max, MAX_DMA32_PFN);
zone_size[ZONE_DMA32] = max_dma32 - min; zone_size[ZONE_DMA32] = max(min, max_dma32) - min;
#endif #endif
zone_size[ZONE_NORMAL] = max - max_dma32; zone_size[ZONE_NORMAL] = max - max_dma32;
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
#define __ARCH_H8300_CACHE_H #define __ARCH_H8300_CACHE_H
/* bytes per L1 cache line */ /* bytes per L1 cache line */
#define L1_CACHE_BYTES 4 #define L1_CACHE_SHIFT 2
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
/* m68k-elf-gcc 2.95.2 doesn't like these */ /* m68k-elf-gcc 2.95.2 doesn't like these */
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#define LPM_ANYPATH 0xff #define LPM_ANYPATH 0xff
#define __MAX_CSSID 0 #define __MAX_CSSID 0
#define __MAX_SUBCHANNEL 65535
#define __MAX_SSID 3
#include <asm/scsw.h> #include <asm/scsw.h>
......
...@@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud) ...@@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud)
static inline int pmd_present(pmd_t pmd) static inline int pmd_present(pmd_t pmd)
{ {
return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL; unsigned long mask = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO;
return (pmd_val(pmd) & mask) == _HPAGE_TYPE_NONE ||
!(pmd_val(pmd) & _SEGMENT_ENTRY_INV);
} }
static inline int pmd_none(pmd_t pmd) static inline int pmd_none(pmd_t pmd)
{ {
return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL; return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) &&
!(pmd_val(pmd) & _SEGMENT_ENTRY_RO);
} }
static inline int pmd_large(pmd_t pmd) static inline int pmd_large(pmd_t pmd)
...@@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp) ...@@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
} }
#ifdef CONFIG_TRANSPARENT_HUGEPAGE #ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define SEGMENT_NONE __pgprot(_HPAGE_TYPE_NONE)
#define SEGMENT_RO __pgprot(_HPAGE_TYPE_RO)
#define SEGMENT_RW __pgprot(_HPAGE_TYPE_RW)
#define __HAVE_ARCH_PGTABLE_DEPOSIT #define __HAVE_ARCH_PGTABLE_DEPOSIT
extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable); extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable);
...@@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, ...@@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot) static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
{ {
unsigned long pgprot_pmd = 0; /*
* pgprot is PAGE_NONE, PAGE_RO, or PAGE_RW (see __Pxxx / __Sxxx)
if (pgprot_val(pgprot) & _PAGE_INVALID) { * Convert to segment table entry format.
if (pgprot_val(pgprot) & _PAGE_SWT) */
pgprot_pmd |= _HPAGE_TYPE_NONE; if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
pgprot_pmd |= _SEGMENT_ENTRY_INV; return pgprot_val(SEGMENT_NONE);
} if (pgprot_val(pgprot) == pgprot_val(PAGE_RO))
if (pgprot_val(pgprot) & _PAGE_RO) return pgprot_val(SEGMENT_RO);
pgprot_pmd |= _SEGMENT_ENTRY_RO; return pgprot_val(SEGMENT_RW);
return pgprot_pmd;
} }
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
...@@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd) ...@@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
static inline pmd_t pmd_mkwrite(pmd_t pmd) static inline pmd_t pmd_mkwrite(pmd_t pmd)
{ {
pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO; /* Do not clobber _HPAGE_TYPE_NONE pages! */
if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV))
pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
return pmd; return pmd;
} }
......
...@@ -44,6 +44,12 @@ _sclp_wait_int: ...@@ -44,6 +44,12 @@ _sclp_wait_int:
#endif #endif
mvc .LoldpswS1-.LbaseS1(16,%r13),0(%r8) mvc .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
mvc 0(16,%r8),0(%r9) mvc 0(16,%r8),0(%r9)
#ifdef CONFIG_64BIT
epsw %r6,%r7 # set current addressing mode
nill %r6,0x1 # in new psw (31 or 64 bit mode)
nilh %r7,0x8000
stm %r6,%r7,0(%r8)
#endif
lhi %r6,0x0200 # cr mask for ext int (cr0.54) lhi %r6,0x0200 # cr mask for ext int (cr0.54)
ltr %r2,%r2 ltr %r2,%r2
jz .LsetctS1 jz .LsetctS1
...@@ -87,7 +93,7 @@ _sclp_wait_int: ...@@ -87,7 +93,7 @@ _sclp_wait_int:
.long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int .long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
.LextpswS1_64: .LextpswS1_64:
.quad 0x0000000180000000, .LwaitS1 # PSW to handle ext int, 64 bit .quad 0, .LwaitS1 # PSW to handle ext int, 64 bit
#endif #endif
.LwaitpswS1: .LwaitpswS1:
.long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int .long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
......
...@@ -39,7 +39,7 @@ static __always_inline unsigned long follow_table(struct mm_struct *mm, ...@@ -39,7 +39,7 @@ static __always_inline unsigned long follow_table(struct mm_struct *mm,
pmd = pmd_offset(pud, addr); pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd)) if (pmd_none(*pmd))
return -0x10UL; return -0x10UL;
if (pmd_huge(*pmd)) { if (pmd_large(*pmd)) {
if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO)) if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
return -0x04UL; return -0x04UL;
return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK); return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
......
...@@ -126,7 +126,7 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr, ...@@ -126,7 +126,7 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,
*/ */
if (pmd_none(pmd) || pmd_trans_splitting(pmd)) if (pmd_none(pmd) || pmd_trans_splitting(pmd))
return 0; return 0;
if (unlikely(pmd_huge(pmd))) { if (unlikely(pmd_large(pmd))) {
if (!gup_huge_pmd(pmdp, pmd, addr, next, if (!gup_huge_pmd(pmdp, pmd, addr, next,
write, pages, nr)) write, pages, nr))
return 0; return 0;
......
...@@ -20,6 +20,7 @@ config SPARC ...@@ -20,6 +20,7 @@ config SPARC
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
select SYSCTL_EXCEPTION_TRACE select SYSCTL_EXCEPTION_TRACE
select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_OPTIONAL_GPIOLIB
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select RTC_CLASS select RTC_CLASS
select RTC_DRV_M48T59 select RTC_DRV_M48T59
select HAVE_IRQ_WORK select HAVE_IRQ_WORK
......
...@@ -13,13 +13,13 @@ obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o ...@@ -13,13 +13,13 @@ obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o
obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o
sha1-sparc64-y := sha1_asm.o sha1_glue.o crop_devid.o sha1-sparc64-y := sha1_asm.o sha1_glue.o
sha256-sparc64-y := sha256_asm.o sha256_glue.o crop_devid.o sha256-sparc64-y := sha256_asm.o sha256_glue.o
sha512-sparc64-y := sha512_asm.o sha512_glue.o crop_devid.o sha512-sparc64-y := sha512_asm.o sha512_glue.o
md5-sparc64-y := md5_asm.o md5_glue.o crop_devid.o md5-sparc64-y := md5_asm.o md5_glue.o
aes-sparc64-y := aes_asm.o aes_glue.o crop_devid.o aes-sparc64-y := aes_asm.o aes_glue.o
des-sparc64-y := des_asm.o des_glue.o crop_devid.o des-sparc64-y := des_asm.o des_glue.o
camellia-sparc64-y := camellia_asm.o camellia_glue.o crop_devid.o camellia-sparc64-y := camellia_asm.o camellia_glue.o
crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o crop_devid.o crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o
...@@ -475,3 +475,5 @@ MODULE_LICENSE("GPL"); ...@@ -475,3 +475,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated"); MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated");
MODULE_ALIAS("aes"); MODULE_ALIAS("aes");
#include "crop_devid.c"
...@@ -320,3 +320,5 @@ MODULE_LICENSE("GPL"); ...@@ -320,3 +320,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated"); MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
MODULE_ALIAS("aes"); MODULE_ALIAS("aes");
#include "crop_devid.c"
...@@ -177,3 +177,5 @@ MODULE_LICENSE("GPL"); ...@@ -177,3 +177,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated"); MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated");
MODULE_ALIAS("crc32c"); MODULE_ALIAS("crc32c");
#include "crop_devid.c"
...@@ -527,3 +527,5 @@ MODULE_LICENSE("GPL"); ...@@ -527,3 +527,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated"); MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");
MODULE_ALIAS("des"); MODULE_ALIAS("des");
#include "crop_devid.c"
...@@ -186,3 +186,5 @@ MODULE_LICENSE("GPL"); ...@@ -186,3 +186,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated"); MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated");
MODULE_ALIAS("md5"); MODULE_ALIAS("md5");
#include "crop_devid.c"
...@@ -181,3 +181,5 @@ MODULE_LICENSE("GPL"); ...@@ -181,3 +181,5 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated"); MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated");
MODULE_ALIAS("sha1"); MODULE_ALIAS("sha1");
#include "crop_devid.c"
...@@ -239,3 +239,5 @@ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 op ...@@ -239,3 +239,5 @@ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 op
MODULE_ALIAS("sha224"); MODULE_ALIAS("sha224");
MODULE_ALIAS("sha256"); MODULE_ALIAS("sha256");
#include "crop_devid.c"
...@@ -224,3 +224,5 @@ MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 op ...@@ -224,3 +224,5 @@ MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 op
MODULE_ALIAS("sha384"); MODULE_ALIAS("sha384");
MODULE_ALIAS("sha512"); MODULE_ALIAS("sha512");
#include "crop_devid.c"
/* atomic.h: Thankfully the V9 is at least reasonable for this /* atomic.h: Thankfully the V9 is at least reasonable for this
* stuff. * stuff.
* *
* Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com) * Copyright (C) 1996, 1997, 2000, 2012 David S. Miller (davem@redhat.com)
*/ */
#ifndef __ARCH_SPARC64_ATOMIC__ #ifndef __ARCH_SPARC64_ATOMIC__
...@@ -106,6 +106,8 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u) ...@@ -106,6 +106,8 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
extern long atomic64_dec_if_positive(atomic64_t *v);
/* Atomic operations are already serializing */ /* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier() #define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier() #define smp_mb__after_atomic_dec() barrier()
......
#ifndef _SPARC64_BACKOFF_H #ifndef _SPARC64_BACKOFF_H
#define _SPARC64_BACKOFF_H #define _SPARC64_BACKOFF_H
/* The macros in this file implement an exponential backoff facility
* for atomic operations.
*
* When multiple threads compete on an atomic operation, it is
* possible for one thread to be continually denied a successful
* completion of the compare-and-swap instruction. Heavily
* threaded cpu implementations like Niagara can compound this
* problem even further.
*
* When an atomic operation fails and needs to be retried, we spin a
* certain number of times. At each subsequent failure of the same
* operation we double the spin count, realizing an exponential
* backoff.
*
* When we spin, we try to use an operation that will cause the
* current cpu strand to block, and therefore make the core fully
* available to any other other runnable strands. There are two
* options, based upon cpu capabilities.
*
* On all cpus prior to SPARC-T4 we do three dummy reads of the
* condition code register. Each read blocks the strand for something
* between 40 and 50 cpu cycles.
*
* For SPARC-T4 and later we have a special "pause" instruction
* available. This is implemented using writes to register %asr27.
* The cpu will block the number of cycles written into the register,
* unless a disrupting trap happens first. SPARC-T4 specifically
* implements pause with a granularity of 8 cycles. Each strand has
* an internal pause counter which decrements every 8 cycles. So the
* chip shifts the %asr27 value down by 3 bits, and writes the result
* into the pause counter. If a value smaller than 8 is written, the
* chip blocks for 1 cycle.
*
* To achieve the same amount of backoff as the three %ccr reads give
* on earlier chips, we shift the backoff value up by 7 bits. (Three
* %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the
* whole amount we want to block into the pause register, rather than
* loop writing 128 each time.
*/
#define BACKOFF_LIMIT (4 * 1024) #define BACKOFF_LIMIT (4 * 1024)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -11,16 +51,25 @@ ...@@ -11,16 +51,25 @@
#define BACKOFF_LABEL(spin_label, continue_label) \ #define BACKOFF_LABEL(spin_label, continue_label) \
spin_label spin_label
#define BACKOFF_SPIN(reg, tmp, label) \ #define BACKOFF_SPIN(reg, tmp, label) \
mov reg, tmp; \ mov reg, tmp; \
88: brnz,pt tmp, 88b; \ 88: rd %ccr, %g0; \
sub tmp, 1, tmp; \ rd %ccr, %g0; \
set BACKOFF_LIMIT, tmp; \ rd %ccr, %g0; \
cmp reg, tmp; \ .section .pause_3insn_patch,"ax";\
bg,pn %xcc, label; \ .word 88b; \
nop; \ sllx tmp, 7, tmp; \
ba,pt %xcc, label; \ wr tmp, 0, %asr27; \
sllx reg, 1, reg; clr tmp; \
.previous; \
brnz,pt tmp, 88b; \
sub tmp, 1, tmp; \
set BACKOFF_LIMIT, tmp; \
cmp reg, tmp; \
bg,pn %xcc, label; \
nop; \
ba,pt %xcc, label; \
sllx reg, 1, reg;
#else #else
......
...@@ -232,9 +232,10 @@ static inline void __user *arch_compat_alloc_user_space(long len) ...@@ -232,9 +232,10 @@ static inline void __user *arch_compat_alloc_user_space(long len)
struct pt_regs *regs = current_thread_info()->kregs; struct pt_regs *regs = current_thread_info()->kregs;
unsigned long usp = regs->u_regs[UREG_I6]; unsigned long usp = regs->u_regs[UREG_I6];
if (!(test_thread_flag(TIF_32BIT))) if (test_thread_64bit_stack(usp))
usp += STACK_BIAS; usp += STACK_BIAS;
else
if (test_thread_flag(TIF_32BIT))
usp &= 0xffffffffUL; usp &= 0xffffffffUL;
usp -= len; usp -= len;
......
...@@ -196,7 +196,22 @@ extern unsigned long get_wchan(struct task_struct *task); ...@@ -196,7 +196,22 @@ extern unsigned long get_wchan(struct task_struct *task);
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->tpc) #define KSTK_EIP(tsk) (task_pt_regs(tsk)->tpc)
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->u_regs[UREG_FP]) #define KSTK_ESP(tsk) (task_pt_regs(tsk)->u_regs[UREG_FP])
#define cpu_relax() barrier() /* Please see the commentary in asm/backoff.h for a description of
* what these instructions are doing and how they have been choosen.
* To make a long story short, we are trying to yield the current cpu
* strand during busy loops.
*/
#define cpu_relax() asm volatile("\n99:\n\t" \
"rd %%ccr, %%g0\n\t" \
"rd %%ccr, %%g0\n\t" \
"rd %%ccr, %%g0\n\t" \
".section .pause_3insn_patch,\"ax\"\n\t"\
".word 99b\n\t" \
"wr %%g0, 128, %%asr27\n\t" \
"nop\n\t" \
"nop\n\t" \
".previous" \
::: "memory")
/* Prefetch support. This is tuned for UltraSPARC-III and later. /* Prefetch support. This is tuned for UltraSPARC-III and later.
* UltraSPARC-I will treat these as nops, and UltraSPARC-II has * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
......
...@@ -63,5 +63,10 @@ extern char *of_console_options; ...@@ -63,5 +63,10 @@ extern char *of_console_options;
extern void irq_trans_init(struct device_node *dp); extern void irq_trans_init(struct device_node *dp);
extern char *build_path_component(struct device_node *dp); extern char *build_path_component(struct device_node *dp);
/* SPARC has a local implementation */
extern int of_address_to_resource(struct device_node *dev, int index,
struct resource *r);
#define of_address_to_resource of_address_to_resource
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _SPARC_PROM_H */ #endif /* _SPARC_PROM_H */
...@@ -259,6 +259,11 @@ static inline bool test_and_clear_restore_sigmask(void) ...@@ -259,6 +259,11 @@ static inline bool test_and_clear_restore_sigmask(void)
#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG) #define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
#define thread32_stack_is_64bit(__SP) (((__SP) & 0x1) != 0)
#define test_thread_64bit_stack(__SP) \
((test_thread_flag(TIF_32BIT) && !thread32_stack_is_64bit(__SP)) ? \
false : true)
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -372,7 +372,9 @@ etrap_spill_fixup_64bit: \ ...@@ -372,7 +372,9 @@ etrap_spill_fixup_64bit: \
/* Normal 32bit spill */ /* Normal 32bit spill */
#define SPILL_2_GENERIC(ASI) \ #define SPILL_2_GENERIC(ASI) \
srl %sp, 0, %sp; \ and %sp, 1, %g3; \
brnz,pn %g3, (. - (128 + 4)); \
srl %sp, 0, %sp; \
stwa %l0, [%sp + %g0] ASI; \ stwa %l0, [%sp + %g0] ASI; \
mov 0x04, %g3; \ mov 0x04, %g3; \
stwa %l1, [%sp + %g3] ASI; \ stwa %l1, [%sp + %g3] ASI; \
...@@ -398,14 +400,16 @@ etrap_spill_fixup_64bit: \ ...@@ -398,14 +400,16 @@ etrap_spill_fixup_64bit: \
stwa %i6, [%g1 + %g0] ASI; \ stwa %i6, [%g1 + %g0] ASI; \
stwa %i7, [%g1 + %g3] ASI; \ stwa %i7, [%g1 + %g3] ASI; \
saved; \ saved; \
retry; nop; nop; \ retry; \
b,a,pt %xcc, spill_fixup_dax; \ b,a,pt %xcc, spill_fixup_dax; \
b,a,pt %xcc, spill_fixup_mna; \ b,a,pt %xcc, spill_fixup_mna; \
b,a,pt %xcc, spill_fixup; b,a,pt %xcc, spill_fixup;
#define SPILL_2_GENERIC_ETRAP \ #define SPILL_2_GENERIC_ETRAP \
etrap_user_spill_32bit: \ etrap_user_spill_32bit: \
srl %sp, 0, %sp; \ and %sp, 1, %g3; \
brnz,pn %g3, etrap_user_spill_64bit; \
srl %sp, 0, %sp; \
stwa %l0, [%sp + 0x00] %asi; \ stwa %l0, [%sp + 0x00] %asi; \
stwa %l1, [%sp + 0x04] %asi; \ stwa %l1, [%sp + 0x04] %asi; \
stwa %l2, [%sp + 0x08] %asi; \ stwa %l2, [%sp + 0x08] %asi; \
...@@ -427,7 +431,7 @@ etrap_user_spill_32bit: \ ...@@ -427,7 +431,7 @@ etrap_user_spill_32bit: \
ba,pt %xcc, etrap_save; \ ba,pt %xcc, etrap_save; \
wrpr %g1, %cwp; \ wrpr %g1, %cwp; \
nop; nop; nop; nop; \ nop; nop; nop; nop; \
nop; nop; nop; nop; \ nop; nop; \
ba,a,pt %xcc, etrap_spill_fixup_32bit; \ ba,a,pt %xcc, etrap_spill_fixup_32bit; \
ba,a,pt %xcc, etrap_spill_fixup_32bit; \ ba,a,pt %xcc, etrap_spill_fixup_32bit; \
ba,a,pt %xcc, etrap_spill_fixup_32bit; ba,a,pt %xcc, etrap_spill_fixup_32bit;
...@@ -592,7 +596,9 @@ user_rtt_fill_64bit: \ ...@@ -592,7 +596,9 @@ user_rtt_fill_64bit: \
/* Normal 32bit fill */ /* Normal 32bit fill */
#define FILL_2_GENERIC(ASI) \ #define FILL_2_GENERIC(ASI) \
srl %sp, 0, %sp; \ and %sp, 1, %g3; \
brnz,pn %g3, (. - (128 + 4)); \
srl %sp, 0, %sp; \
lduwa [%sp + %g0] ASI, %l0; \ lduwa [%sp + %g0] ASI, %l0; \
mov 0x04, %g2; \ mov 0x04, %g2; \
mov 0x08, %g3; \ mov 0x08, %g3; \
...@@ -616,14 +622,16 @@ user_rtt_fill_64bit: \ ...@@ -616,14 +622,16 @@ user_rtt_fill_64bit: \
lduwa [%g1 + %g3] ASI, %i6; \ lduwa [%g1 + %g3] ASI, %i6; \
lduwa [%g1 + %g5] ASI, %i7; \ lduwa [%g1 + %g5] ASI, %i7; \
restored; \ restored; \
retry; nop; nop; nop; nop; \ retry; nop; nop; \
b,a,pt %xcc, fill_fixup_dax; \ b,a,pt %xcc, fill_fixup_dax; \
b,a,pt %xcc, fill_fixup_mna; \ b,a,pt %xcc, fill_fixup_mna; \
b,a,pt %xcc, fill_fixup; b,a,pt %xcc, fill_fixup;
#define FILL_2_GENERIC_RTRAP \ #define FILL_2_GENERIC_RTRAP \
user_rtt_fill_32bit: \ user_rtt_fill_32bit: \
srl %sp, 0, %sp; \ and %sp, 1, %g3; \
brnz,pn %g3, user_rtt_fill_64bit; \
srl %sp, 0, %sp; \
lduwa [%sp + 0x00] %asi, %l0; \ lduwa [%sp + 0x00] %asi, %l0; \
lduwa [%sp + 0x04] %asi, %l1; \ lduwa [%sp + 0x04] %asi, %l1; \
lduwa [%sp + 0x08] %asi, %l2; \ lduwa [%sp + 0x08] %asi, %l2; \
...@@ -643,7 +651,7 @@ user_rtt_fill_32bit: \ ...@@ -643,7 +651,7 @@ user_rtt_fill_32bit: \
ba,pt %xcc, user_rtt_pre_restore; \ ba,pt %xcc, user_rtt_pre_restore; \
restored; \ restored; \
nop; nop; nop; nop; nop; \ nop; nop; nop; nop; nop; \
nop; nop; nop; nop; nop; \ nop; nop; nop; \
ba,a,pt %xcc, user_rtt_fill_fixup; \ ba,a,pt %xcc, user_rtt_fill_fixup; \
ba,a,pt %xcc, user_rtt_fill_fixup; \ ba,a,pt %xcc, user_rtt_fill_fixup; \
ba,a,pt %xcc, user_rtt_fill_fixup; ba,a,pt %xcc, user_rtt_fill_fixup;
......
...@@ -405,8 +405,13 @@ ...@@ -405,8 +405,13 @@
#define __NR_setns 337 #define __NR_setns 337
#define __NR_process_vm_readv 338 #define __NR_process_vm_readv 338
#define __NR_process_vm_writev 339 #define __NR_process_vm_writev 339
#define __NR_kern_features 340
#define __NR_kcmp 341
#define NR_syscalls 340 #define NR_syscalls 342
/* Bitmask values returned from kern_features system call. */
#define KERN_FEATURE_MIXED_MODE_STACK 0x00000001
#ifdef __32bit_syscall_numbers__ #ifdef __32bit_syscall_numbers__
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
......
...@@ -59,6 +59,13 @@ struct popc_6insn_patch_entry { ...@@ -59,6 +59,13 @@ struct popc_6insn_patch_entry {
extern struct popc_6insn_patch_entry __popc_6insn_patch, extern struct popc_6insn_patch_entry __popc_6insn_patch,
__popc_6insn_patch_end; __popc_6insn_patch_end;
struct pause_patch_entry {
unsigned int addr;
unsigned int insns[3];
};
extern struct pause_patch_entry __pause_3insn_patch,
__pause_3insn_patch_end;
extern void __init per_cpu_patch(void); extern void __init per_cpu_patch(void);
extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *, extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
struct sun4v_1insn_patch_entry *); struct sun4v_1insn_patch_entry *);
......
...@@ -56,11 +56,13 @@ static inline unsigned int leon_eirq_get(int cpu) ...@@ -56,11 +56,13 @@ static inline unsigned int leon_eirq_get(int cpu)
static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc) static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)
{ {
unsigned int eirq; unsigned int eirq;
struct irq_bucket *p;
int cpu = sparc_leon3_cpuid(); int cpu = sparc_leon3_cpuid();
eirq = leon_eirq_get(cpu); eirq = leon_eirq_get(cpu);
if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */ p = irq_map[eirq];
generic_handle_irq(irq_map[eirq]->irq); if ((eirq & 0x10) && p && p->irq) /* bit4 tells if IRQ happened */
generic_handle_irq(p->irq);
} }
/* The extended IRQ controller has been found, this function registers it */ /* The extended IRQ controller has been found, this function registers it */
......
...@@ -1762,15 +1762,25 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, ...@@ -1762,15 +1762,25 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
ufp = regs->u_regs[UREG_I6] & 0xffffffffUL; ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
do { do {
struct sparc_stackf32 *usf, sf;
unsigned long pc; unsigned long pc;
usf = (struct sparc_stackf32 *) ufp; if (thread32_stack_is_64bit(ufp)) {
if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) struct sparc_stackf *usf, sf;
break;
pc = sf.callers_pc; ufp += STACK_BIAS;
ufp = (unsigned long)sf.fp; usf = (struct sparc_stackf *) ufp;
if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
break;
pc = sf.callers_pc & 0xffffffff;
ufp = ((unsigned long) sf.fp) & 0xffffffff;
} else {
struct sparc_stackf32 *usf, sf;
usf = (struct sparc_stackf32 *) ufp;
if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
break;
pc = sf.callers_pc;
ufp = (unsigned long)sf.fp;
}
perf_callchain_store(entry, pc); perf_callchain_store(entry, pc);
} while (entry->nr < PERF_MAX_STACK_DEPTH); } while (entry->nr < PERF_MAX_STACK_DEPTH);
} }
......
...@@ -452,13 +452,16 @@ void flush_thread(void) ...@@ -452,13 +452,16 @@ void flush_thread(void)
/* It's a bit more tricky when 64-bit tasks are involved... */ /* It's a bit more tricky when 64-bit tasks are involved... */
static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
{ {
bool stack_64bit = test_thread_64bit_stack(psp);
unsigned long fp, distance, rval; unsigned long fp, distance, rval;
if (!(test_thread_flag(TIF_32BIT))) { if (stack_64bit) {
csp += STACK_BIAS; csp += STACK_BIAS;
psp += STACK_BIAS; psp += STACK_BIAS;
__get_user(fp, &(((struct reg_window __user *)psp)->ins[6])); __get_user(fp, &(((struct reg_window __user *)psp)->ins[6]));
fp += STACK_BIAS; fp += STACK_BIAS;
if (test_thread_flag(TIF_32BIT))
fp &= 0xffffffff;
} else } else
__get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6])); __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6]));
...@@ -472,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) ...@@ -472,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
rval = (csp - distance); rval = (csp - distance);
if (copy_in_user((void __user *) rval, (void __user *) psp, distance)) if (copy_in_user((void __user *) rval, (void __user *) psp, distance))
rval = 0; rval = 0;
else if (test_thread_flag(TIF_32BIT)) { else if (!stack_64bit) {
if (put_user(((u32)csp), if (put_user(((u32)csp),
&(((struct reg_window32 __user *)rval)->ins[6]))) &(((struct reg_window32 __user *)rval)->ins[6])))
rval = 0; rval = 0;
...@@ -507,18 +510,18 @@ void synchronize_user_stack(void) ...@@ -507,18 +510,18 @@ void synchronize_user_stack(void)
flush_user_windows(); flush_user_windows();
if ((window = get_thread_wsaved()) != 0) { if ((window = get_thread_wsaved()) != 0) {
int winsize = sizeof(struct reg_window);
int bias = 0;
if (test_thread_flag(TIF_32BIT))
winsize = sizeof(struct reg_window32);
else
bias = STACK_BIAS;
window -= 1; window -= 1;
do { do {
unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
struct reg_window *rwin = &t->reg_window[window]; struct reg_window *rwin = &t->reg_window[window];
int winsize = sizeof(struct reg_window);
unsigned long sp;
sp = t->rwbuf_stkptrs[window];
if (test_thread_64bit_stack(sp))
sp += STACK_BIAS;
else
winsize = sizeof(struct reg_window32);
if (!copy_to_user((char __user *)sp, rwin, winsize)) { if (!copy_to_user((char __user *)sp, rwin, winsize)) {
shift_window_buffer(window, get_thread_wsaved() - 1, t); shift_window_buffer(window, get_thread_wsaved() - 1, t);
...@@ -544,13 +547,6 @@ void fault_in_user_windows(void) ...@@ -544,13 +547,6 @@ void fault_in_user_windows(void)
{ {
struct thread_info *t = current_thread_info(); struct thread_info *t = current_thread_info();
unsigned long window; unsigned long window;
int winsize = sizeof(struct reg_window);
int bias = 0;
if (test_thread_flag(TIF_32BIT))
winsize = sizeof(struct reg_window32);
else
bias = STACK_BIAS;
flush_user_windows(); flush_user_windows();
window = get_thread_wsaved(); window = get_thread_wsaved();
...@@ -558,8 +554,16 @@ void fault_in_user_windows(void) ...@@ -558,8 +554,16 @@ void fault_in_user_windows(void)
if (likely(window != 0)) { if (likely(window != 0)) {
window -= 1; window -= 1;
do { do {
unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
struct reg_window *rwin = &t->reg_window[window]; struct reg_window *rwin = &t->reg_window[window];
int winsize = sizeof(struct reg_window);
unsigned long sp;
sp = t->rwbuf_stkptrs[window];
if (test_thread_64bit_stack(sp))
sp += STACK_BIAS;
else
winsize = sizeof(struct reg_window32);
if (unlikely(sp & 0x7UL)) if (unlikely(sp & 0x7UL))
stack_unaligned(sp); stack_unaligned(sp);
......
...@@ -151,7 +151,7 @@ static int regwindow64_get(struct task_struct *target, ...@@ -151,7 +151,7 @@ static int regwindow64_get(struct task_struct *target,
{ {
unsigned long rw_addr = regs->u_regs[UREG_I6]; unsigned long rw_addr = regs->u_regs[UREG_I6];
if (test_tsk_thread_flag(current, TIF_32BIT)) { if (!test_thread_64bit_stack(rw_addr)) {
struct reg_window32 win32; struct reg_window32 win32;
int i; int i;
...@@ -176,7 +176,7 @@ static int regwindow64_set(struct task_struct *target, ...@@ -176,7 +176,7 @@ static int regwindow64_set(struct task_struct *target,
{ {
unsigned long rw_addr = regs->u_regs[UREG_I6]; unsigned long rw_addr = regs->u_regs[UREG_I6];
if (test_tsk_thread_flag(current, TIF_32BIT)) { if (!test_thread_64bit_stack(rw_addr)) {
struct reg_window32 win32; struct reg_window32 win32;
int i; int i;
......
...@@ -316,6 +316,25 @@ static void __init popc_patch(void) ...@@ -316,6 +316,25 @@ static void __init popc_patch(void)
} }
} }
static void __init pause_patch(void)
{
struct pause_patch_entry *p;
p = &__pause_3insn_patch;
while (p < &__pause_3insn_patch_end) {
unsigned long i, addr = p->addr;
for (i = 0; i < 3; i++) {
*(unsigned int *) (addr + (i * 4)) = p->insns[i];
wmb();
__asm__ __volatile__("flush %0"
: : "r" (addr + (i * 4)));
}
p++;
}
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void __init boot_cpu_id_too_large(int cpu) void __init boot_cpu_id_too_large(int cpu)
{ {
...@@ -528,6 +547,8 @@ static void __init init_sparc64_elf_hwcap(void) ...@@ -528,6 +547,8 @@ static void __init init_sparc64_elf_hwcap(void)
if (sparc64_elf_hwcap & AV_SPARC_POPC) if (sparc64_elf_hwcap & AV_SPARC_POPC)
popc_patch(); popc_patch();
if (sparc64_elf_hwcap & AV_SPARC_PAUSE)
pause_patch();
} }
void __init setup_arch(char **cmdline_p) void __init setup_arch(char **cmdline_p)
......
...@@ -751,3 +751,8 @@ int kernel_execve(const char *filename, ...@@ -751,3 +751,8 @@ int kernel_execve(const char *filename,
: "cc"); : "cc");
return __res; return __res;
} }
asmlinkage long sys_kern_features(void)
{
return KERN_FEATURE_MIXED_MODE_STACK;
}
...@@ -85,3 +85,4 @@ sys_call_table: ...@@ -85,3 +85,4 @@ sys_call_table:
/*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
/*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime /*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
/*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev /*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
/*340*/ .long sys_ni_syscall, sys_kcmp
...@@ -86,6 +86,7 @@ sys_call_table32: ...@@ -86,6 +86,7 @@ sys_call_table32:
.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
/*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime /*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
.word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
/*340*/ .word sys_kern_features, sys_kcmp
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
...@@ -163,3 +164,4 @@ sys_call_table: ...@@ -163,3 +164,4 @@ sys_call_table:
.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
/*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime /*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
.word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
/*340*/ .word sys_kern_features, sys_kcmp
...@@ -113,21 +113,24 @@ static inline long sign_extend_imm13(long imm) ...@@ -113,21 +113,24 @@ static inline long sign_extend_imm13(long imm)
static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
{ {
unsigned long value; unsigned long value, fp;
if (reg < 16) if (reg < 16)
return (!reg ? 0 : regs->u_regs[reg]); return (!reg ? 0 : regs->u_regs[reg]);
fp = regs->u_regs[UREG_FP];
if (regs->tstate & TSTATE_PRIV) { if (regs->tstate & TSTATE_PRIV) {
struct reg_window *win; struct reg_window *win;
win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); win = (struct reg_window *)(fp + STACK_BIAS);
value = win->locals[reg - 16]; value = win->locals[reg - 16];
} else if (test_thread_flag(TIF_32BIT)) { } else if (!test_thread_64bit_stack(fp)) {
struct reg_window32 __user *win32; struct reg_window32 __user *win32;
win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
get_user(value, &win32->locals[reg - 16]); get_user(value, &win32->locals[reg - 16]);
} else { } else {
struct reg_window __user *win; struct reg_window __user *win;
win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); win = (struct reg_window __user *)(fp + STACK_BIAS);
get_user(value, &win->locals[reg - 16]); get_user(value, &win->locals[reg - 16]);
} }
return value; return value;
...@@ -135,19 +138,24 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) ...@@ -135,19 +138,24 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs) static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
{ {
unsigned long fp;
if (reg < 16) if (reg < 16)
return &regs->u_regs[reg]; return &regs->u_regs[reg];
fp = regs->u_regs[UREG_FP];
if (regs->tstate & TSTATE_PRIV) { if (regs->tstate & TSTATE_PRIV) {
struct reg_window *win; struct reg_window *win;
win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); win = (struct reg_window *)(fp + STACK_BIAS);
return &win->locals[reg - 16]; return &win->locals[reg - 16];
} else if (test_thread_flag(TIF_32BIT)) { } else if (!test_thread_64bit_stack(fp)) {
struct reg_window32 *win32; struct reg_window32 *win32;
win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP])); win32 = (struct reg_window32 *)((unsigned long)((u32)fp));
return (unsigned long *)&win32->locals[reg - 16]; return (unsigned long *)&win32->locals[reg - 16];
} else { } else {
struct reg_window *win; struct reg_window *win;
win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); win = (struct reg_window *)(fp + STACK_BIAS);
return &win->locals[reg - 16]; return &win->locals[reg - 16];
} }
} }
...@@ -392,13 +400,15 @@ int handle_popc(u32 insn, struct pt_regs *regs) ...@@ -392,13 +400,15 @@ int handle_popc(u32 insn, struct pt_regs *regs)
if (rd) if (rd)
regs->u_regs[rd] = ret; regs->u_regs[rd] = ret;
} else { } else {
if (test_thread_flag(TIF_32BIT)) { unsigned long fp = regs->u_regs[UREG_FP];
if (!test_thread_64bit_stack(fp)) {
struct reg_window32 __user *win32; struct reg_window32 __user *win32;
win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
put_user(ret, &win32->locals[rd - 16]); put_user(ret, &win32->locals[rd - 16]);
} else { } else {
struct reg_window __user *win; struct reg_window __user *win;
win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); win = (struct reg_window __user *)(fp + STACK_BIAS);
put_user(ret, &win->locals[rd - 16]); put_user(ret, &win->locals[rd - 16]);
} }
} }
...@@ -554,7 +564,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs) ...@@ -554,7 +564,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs)
reg[0] = 0; reg[0] = 0;
if ((insn & 0x780000) == 0x180000) if ((insn & 0x780000) == 0x180000)
reg[1] = 0; reg[1] = 0;
} else if (test_thread_flag(TIF_32BIT)) { } else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
put_user(0, (int __user *) reg); put_user(0, (int __user *) reg);
if ((insn & 0x780000) == 0x180000) if ((insn & 0x780000) == 0x180000)
put_user(0, ((int __user *) reg) + 1); put_user(0, ((int __user *) reg) + 1);
......
...@@ -149,21 +149,24 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2, ...@@ -149,21 +149,24 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
{ {
unsigned long value; unsigned long value, fp;
if (reg < 16) if (reg < 16)
return (!reg ? 0 : regs->u_regs[reg]); return (!reg ? 0 : regs->u_regs[reg]);
fp = regs->u_regs[UREG_FP];
if (regs->tstate & TSTATE_PRIV) { if (regs->tstate & TSTATE_PRIV) {
struct reg_window *win; struct reg_window *win;
win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); win = (struct reg_window *)(fp + STACK_BIAS);
value = win->locals[reg - 16]; value = win->locals[reg - 16];
} else if (test_thread_flag(TIF_32BIT)) { } else if (!test_thread_64bit_stack(fp)) {
struct reg_window32 __user *win32; struct reg_window32 __user *win32;
win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
get_user(value, &win32->locals[reg - 16]); get_user(value, &win32->locals[reg - 16]);
} else { } else {
struct reg_window __user *win; struct reg_window __user *win;
win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); win = (struct reg_window __user *)(fp + STACK_BIAS);
get_user(value, &win->locals[reg - 16]); get_user(value, &win->locals[reg - 16]);
} }
return value; return value;
...@@ -172,16 +175,18 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) ...@@ -172,16 +175,18 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
static inline unsigned long __user *__fetch_reg_addr_user(unsigned int reg, static inline unsigned long __user *__fetch_reg_addr_user(unsigned int reg,
struct pt_regs *regs) struct pt_regs *regs)
{ {
unsigned long fp = regs->u_regs[UREG_FP];
BUG_ON(reg < 16); BUG_ON(reg < 16);
BUG_ON(regs->tstate & TSTATE_PRIV); BUG_ON(regs->tstate & TSTATE_PRIV);
if (test_thread_flag(TIF_32BIT)) { if (!test_thread_64bit_stack(fp)) {
struct reg_window32 __user *win32; struct reg_window32 __user *win32;
win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
return (unsigned long __user *)&win32->locals[reg - 16]; return (unsigned long __user *)&win32->locals[reg - 16];
} else { } else {
struct reg_window __user *win; struct reg_window __user *win;
win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); win = (struct reg_window __user *)(fp + STACK_BIAS);
return &win->locals[reg - 16]; return &win->locals[reg - 16];
} }
} }
...@@ -204,7 +209,7 @@ static void store_reg(struct pt_regs *regs, unsigned long val, unsigned long rd) ...@@ -204,7 +209,7 @@ static void store_reg(struct pt_regs *regs, unsigned long val, unsigned long rd)
} else { } else {
unsigned long __user *rd_user = __fetch_reg_addr_user(rd, regs); unsigned long __user *rd_user = __fetch_reg_addr_user(rd, regs);
if (test_thread_flag(TIF_32BIT)) if (!test_thread_64bit_stack(regs->u_regs[UREG_FP]))
__put_user((u32)val, (u32 __user *)rd_user); __put_user((u32)val, (u32 __user *)rd_user);
else else
__put_user(val, rd_user); __put_user(val, rd_user);
......
...@@ -132,6 +132,11 @@ SECTIONS ...@@ -132,6 +132,11 @@ SECTIONS
*(.popc_6insn_patch) *(.popc_6insn_patch)
__popc_6insn_patch_end = .; __popc_6insn_patch_end = .;
} }
.pause_3insn_patch : {
__pause_3insn_patch = .;
*(.pause_3insn_patch)
__pause_3insn_patch_end = .;
}
PERCPU_SECTION(SMP_CACHE_BYTES) PERCPU_SECTION(SMP_CACHE_BYTES)
. = ALIGN(PAGE_SIZE); . = ALIGN(PAGE_SIZE);
......
...@@ -43,6 +43,8 @@ spill_fixup_mna: ...@@ -43,6 +43,8 @@ spill_fixup_mna:
spill_fixup_dax: spill_fixup_dax:
TRAP_LOAD_THREAD_REG(%g6, %g1) TRAP_LOAD_THREAD_REG(%g6, %g1)
ldx [%g6 + TI_FLAGS], %g1 ldx [%g6 + TI_FLAGS], %g1
andcc %sp, 0x1, %g0
movne %icc, 0, %g1
andcc %g1, _TIF_32BIT, %g0 andcc %g1, _TIF_32BIT, %g0
ldub [%g6 + TI_WSAVED], %g1 ldub [%g6 + TI_WSAVED], %g1
sll %g1, 3, %g3 sll %g1, 3, %g3
......
/* atomic.S: These things are too big to do inline. /* atomic.S: These things are too big to do inline.
* *
* Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) * Copyright (C) 1999, 2007 2012 David S. Miller (davem@davemloft.net)
*/ */
#include <linux/linkage.h> #include <linux/linkage.h>
...@@ -117,3 +117,17 @@ ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */ ...@@ -117,3 +117,17 @@ ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */
sub %g1, %o0, %o0 sub %g1, %o0, %o0
2: BACKOFF_SPIN(%o2, %o3, 1b) 2: BACKOFF_SPIN(%o2, %o3, 1b)
ENDPROC(atomic64_sub_ret) ENDPROC(atomic64_sub_ret)
ENTRY(atomic64_dec_if_positive) /* %o0 = atomic_ptr */
BACKOFF_SETUP(%o2)
1: ldx [%o0], %g1
brlez,pn %g1, 3f
sub %g1, 1, %g7
casx [%o0], %g1, %g7
cmp %g1, %g7
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
nop
3: retl
sub %g1, 1, %o0
2: BACKOFF_SPIN(%o2, %o3, 1b)
ENDPROC(atomic64_dec_if_positive)
...@@ -116,6 +116,7 @@ EXPORT_SYMBOL(atomic64_add); ...@@ -116,6 +116,7 @@ EXPORT_SYMBOL(atomic64_add);
EXPORT_SYMBOL(atomic64_add_ret); EXPORT_SYMBOL(atomic64_add_ret);
EXPORT_SYMBOL(atomic64_sub); EXPORT_SYMBOL(atomic64_sub);
EXPORT_SYMBOL(atomic64_sub_ret); EXPORT_SYMBOL(atomic64_sub_ret);
EXPORT_SYMBOL(atomic64_dec_if_positive);
/* Atomic bit operations. */ /* Atomic bit operations. */
EXPORT_SYMBOL(test_and_set_bit); EXPORT_SYMBOL(test_and_set_bit);
......
...@@ -320,7 +320,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap) ...@@ -320,7 +320,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap)
XR = 0; XR = 0;
else if (freg < 16) else if (freg < 16)
XR = regs->u_regs[freg]; XR = regs->u_regs[freg];
else if (test_thread_flag(TIF_32BIT)) { else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
struct reg_window32 __user *win32; struct reg_window32 __user *win32;
flushw_user (); flushw_user ();
win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
......
...@@ -359,18 +359,14 @@ HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val, ...@@ -359,18 +359,14 @@ HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
return _hypercall4(int, update_va_mapping, va, return _hypercall4(int, update_va_mapping, va,
new_val.pte, new_val.pte >> 32, flags); new_val.pte, new_val.pte >> 32, flags);
} }
extern int __must_check xen_event_channel_op_compat(int, void *);
static inline int static inline int
HYPERVISOR_event_channel_op(int cmd, void *arg) HYPERVISOR_event_channel_op(int cmd, void *arg)
{ {
int rc = _hypercall2(int, event_channel_op, cmd, arg); int rc = _hypercall2(int, event_channel_op, cmd, arg);
if (unlikely(rc == -ENOSYS)) { if (unlikely(rc == -ENOSYS))
struct evtchn_op op; rc = xen_event_channel_op_compat(cmd, arg);
op.cmd = cmd;
memcpy(&op.u, arg, sizeof(op.u));
rc = _hypercall1(int, event_channel_op_compat, &op);
memcpy(arg, &op.u, sizeof(op.u));
}
return rc; return rc;
} }
...@@ -386,17 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str) ...@@ -386,17 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str)
return _hypercall3(int, console_io, cmd, count, str); return _hypercall3(int, console_io, cmd, count, str);
} }
extern int __must_check HYPERVISOR_physdev_op_compat(int, void *);
static inline int static inline int
HYPERVISOR_physdev_op(int cmd, void *arg) HYPERVISOR_physdev_op(int cmd, void *arg)
{ {
int rc = _hypercall2(int, physdev_op, cmd, arg); int rc = _hypercall2(int, physdev_op, cmd, arg);
if (unlikely(rc == -ENOSYS)) { if (unlikely(rc == -ENOSYS))
struct physdev_op op; rc = HYPERVISOR_physdev_op_compat(cmd, arg);
op.cmd = cmd;
memcpy(&op.u, arg, sizeof(op.u));
rc = _hypercall1(int, physdev_op_compat, &op);
memcpy(arg, &op.u, sizeof(op.u));
}
return rc; return rc;
} }
......
...@@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work) ...@@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work)
struct crypto_async_request *req, *backlog; struct crypto_async_request *req, *backlog;
cpu_queue = container_of(work, struct cryptd_cpu_queue, work); cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
/* Only handle one request at a time to avoid hogging crypto /*
* workqueue. preempt_disable/enable is used to prevent * Only handle one request at a time to avoid hogging crypto workqueue.
* being preempted by cryptd_enqueue_request() */ * preempt_disable/enable is used to prevent being preempted by
* cryptd_enqueue_request(). local_bh_disable/enable is used to prevent
* cryptd_enqueue_request() being accessed from software interrupts.
*/
local_bh_disable();
preempt_disable(); preempt_disable();
backlog = crypto_get_backlog(&cpu_queue->queue); backlog = crypto_get_backlog(&cpu_queue->queue);
req = crypto_dequeue_request(&cpu_queue->queue); req = crypto_dequeue_request(&cpu_queue->queue);
preempt_enable(); preempt_enable();
local_bh_enable();
if (!req) if (!req)
return; return;
......
...@@ -83,9 +83,16 @@ EXPORT_SYMBOL_GPL(platform_get_resource); ...@@ -83,9 +83,16 @@ EXPORT_SYMBOL_GPL(platform_get_resource);
*/ */
int platform_get_irq(struct platform_device *dev, unsigned int num) int platform_get_irq(struct platform_device *dev, unsigned int num)
{ {
#ifdef CONFIG_SPARC
/* sparc does not have irqs represented as IORESOURCE_IRQ resources */
if (!dev || num >= dev->archdata.num_irqs)
return -ENXIO;
return dev->archdata.irqs[num];
#else
struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
return r ? r->start : -ENXIO; return r ? r->start : -ENXIO;
#endif
} }
EXPORT_SYMBOL_GPL(platform_get_irq); EXPORT_SYMBOL_GPL(platform_get_irq);
......
...@@ -47,7 +47,7 @@ if GPIOLIB ...@@ -47,7 +47,7 @@ if GPIOLIB
config OF_GPIO config OF_GPIO
def_bool y def_bool y
depends on OF && !SPARC depends on OF
config DEBUG_GPIO config DEBUG_GPIO
bool "Debug GPIO calls" bool "Debug GPIO calls"
......
...@@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp) ...@@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp)
int minor_id = iminor(inode); int minor_id = iminor(inode);
struct drm_minor *minor; struct drm_minor *minor;
int retcode = 0; int retcode = 0;
int need_setup = 0;
struct address_space *old_mapping;
minor = idr_find(&drm_minors_idr, minor_id); minor = idr_find(&drm_minors_idr, minor_id);
if (!minor) if (!minor)
...@@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp) ...@@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp)
if (drm_device_is_unplugged(dev)) if (drm_device_is_unplugged(dev))
return -ENODEV; return -ENODEV;
if (!dev->open_count++)
need_setup = 1;
mutex_lock(&dev->struct_mutex);
old_mapping = dev->dev_mapping;
if (old_mapping == NULL)
dev->dev_mapping = &inode->i_data;
/* ihold ensures nobody can remove inode with our i_data */
ihold(container_of(dev->dev_mapping, struct inode, i_data));
inode->i_mapping = dev->dev_mapping;
filp->f_mapping = dev->dev_mapping;
mutex_unlock(&dev->struct_mutex);
retcode = drm_open_helper(inode, filp, dev); retcode = drm_open_helper(inode, filp, dev);
if (!retcode) { if (retcode)
atomic_inc(&dev->counts[_DRM_STAT_OPENS]); goto err_undo;
if (!dev->open_count++) atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
retcode = drm_setup(dev); if (need_setup) {
} retcode = drm_setup(dev);
if (!retcode) { if (retcode)
mutex_lock(&dev->struct_mutex); goto err_undo;
if (dev->dev_mapping == NULL)
dev->dev_mapping = &inode->i_data;
/* ihold ensures nobody can remove inode with our i_data */
ihold(container_of(dev->dev_mapping, struct inode, i_data));
inode->i_mapping = dev->dev_mapping;
filp->f_mapping = dev->dev_mapping;
mutex_unlock(&dev->struct_mutex);
} }
return 0;
err_undo:
mutex_lock(&dev->struct_mutex);
filp->f_mapping = old_mapping;
inode->i_mapping = old_mapping;
iput(container_of(dev->dev_mapping, struct inode, i_data));
dev->dev_mapping = old_mapping;
mutex_unlock(&dev->struct_mutex);
dev->open_count--;
return retcode; return retcode;
} }
EXPORT_SYMBOL(drm_open); EXPORT_SYMBOL(drm_open);
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include <subdev/bar.h>
#include <engine/software.h> #include <engine/software.h>
#include <engine/disp.h> #include <engine/disp.h>
...@@ -37,6 +39,7 @@ nv50_disp_sclass[] = { ...@@ -37,6 +39,7 @@ nv50_disp_sclass[] = {
static void static void
nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
{ {
struct nouveau_bar *bar = nouveau_bar(priv);
struct nouveau_disp *disp = &priv->base; struct nouveau_disp *disp = &priv->base;
struct nouveau_software_chan *chan, *temp; struct nouveau_software_chan *chan, *temp;
unsigned long flags; unsigned long flags;
...@@ -46,18 +49,19 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) ...@@ -46,18 +49,19 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
if (chan->vblank.crtc != crtc) if (chan->vblank.crtc != crtc)
continue; continue;
nv_wr32(priv, 0x001704, chan->vblank.channel);
nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
if (nv_device(priv)->chipset == 0x50) { if (nv_device(priv)->chipset == 0x50) {
nv_wr32(priv, 0x001704, chan->vblank.channel);
nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
bar->flush(bar);
nv_wr32(priv, 0x001570, chan->vblank.offset); nv_wr32(priv, 0x001570, chan->vblank.offset);
nv_wr32(priv, 0x001574, chan->vblank.value); nv_wr32(priv, 0x001574, chan->vblank.value);
} else { } else {
if (nv_device(priv)->chipset >= 0xc0) { nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
nv_wr32(priv, 0x06000c, bar->flush(bar);
upper_32_bits(chan->vblank.offset)); nv_wr32(priv, 0x06000c,
} upper_32_bits(chan->vblank.offset));
nv_wr32(priv, 0x060010, chan->vblank.offset); nv_wr32(priv, 0x060010,
lower_32_bits(chan->vblank.offset));
nv_wr32(priv, 0x060014, chan->vblank.value); nv_wr32(priv, 0x060014, chan->vblank.value);
} }
......
...@@ -156,8 +156,8 @@ nv40_graph_context_ctor(struct nouveau_object *parent, ...@@ -156,8 +156,8 @@ nv40_graph_context_ctor(struct nouveau_object *parent,
static int static int
nv40_graph_context_fini(struct nouveau_object *object, bool suspend) nv40_graph_context_fini(struct nouveau_object *object, bool suspend)
{ {
struct nv04_graph_priv *priv = (void *)object->engine; struct nv40_graph_priv *priv = (void *)object->engine;
struct nv04_graph_chan *chan = (void *)object; struct nv40_graph_chan *chan = (void *)object;
u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4; u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4;
int ret = 0; int ret = 0;
......
...@@ -38,7 +38,7 @@ struct nv40_mpeg_priv { ...@@ -38,7 +38,7 @@ struct nv40_mpeg_priv {
}; };
struct nv40_mpeg_chan { struct nv40_mpeg_chan {
struct nouveau_mpeg base; struct nouveau_mpeg_chan base;
}; };
/******************************************************************************* /*******************************************************************************
......
...@@ -67,7 +67,7 @@ nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) ...@@ -67,7 +67,7 @@ nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
static void static void
nv41_vm_flush(struct nouveau_vm *vm) nv41_vm_flush(struct nouveau_vm *vm)
{ {
struct nv04_vm_priv *priv = (void *)vm->vmm; struct nv04_vmmgr_priv *priv = (void *)vm->vmm;
mutex_lock(&nv_subdev(priv)->mutex); mutex_lock(&nv_subdev(priv)->mutex);
nv_wr32(priv, 0x100810, 0x00000022); nv_wr32(priv, 0x100810, 0x00000022);
......
...@@ -355,7 +355,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) ...@@ -355,7 +355,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
* valid - it's not (rh#613284) * valid - it's not (rh#613284)
*/ */
if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
if (!(nv_connector->edid = nouveau_acpi_edid(dev, connector))) { if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
status = connector_status_connected; status = connector_status_connected;
goto out; goto out;
} }
......
...@@ -1696,35 +1696,43 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) ...@@ -1696,35 +1696,43 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
return ATOM_PPLL2; return ATOM_PPLL2;
DRM_ERROR("unable to allocate a PPLL\n"); DRM_ERROR("unable to allocate a PPLL\n");
return ATOM_PPLL_INVALID; return ATOM_PPLL_INVALID;
} else { } else if (ASIC_IS_AVIVO(rdev)) {
if (ASIC_IS_AVIVO(rdev)) { /* in DP mode, the DP ref clock can come from either PPLL
/* in DP mode, the DP ref clock can come from either PPLL * depending on the asic:
* depending on the asic: * DCE3: PPLL1 or PPLL2
* DCE3: PPLL1 or PPLL2 */
*/ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { /* use the same PPLL for all DP monitors */
/* use the same PPLL for all DP monitors */ pll = radeon_get_shared_dp_ppll(crtc);
pll = radeon_get_shared_dp_ppll(crtc); if (pll != ATOM_PPLL_INVALID)
if (pll != ATOM_PPLL_INVALID) return pll;
return pll; } else {
} else { /* use the same PPLL for all monitors with the same clock */
/* use the same PPLL for all monitors with the same clock */ pll = radeon_get_shared_nondp_ppll(crtc);
pll = radeon_get_shared_nondp_ppll(crtc); if (pll != ATOM_PPLL_INVALID)
if (pll != ATOM_PPLL_INVALID) return pll;
return pll; }
} /* all other cases */
/* all other cases */ pll_in_use = radeon_get_pll_use_mask(crtc);
pll_in_use = radeon_get_pll_use_mask(crtc); /* the order shouldn't matter here, but we probably
* need this until we have atomic modeset
*/
if (rdev->flags & RADEON_IS_IGP) {
if (!(pll_in_use & (1 << ATOM_PPLL1))) if (!(pll_in_use & (1 << ATOM_PPLL1)))
return ATOM_PPLL1; return ATOM_PPLL1;
if (!(pll_in_use & (1 << ATOM_PPLL2))) if (!(pll_in_use & (1 << ATOM_PPLL2)))
return ATOM_PPLL2; return ATOM_PPLL2;
DRM_ERROR("unable to allocate a PPLL\n");
return ATOM_PPLL_INVALID;
} else { } else {
/* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ if (!(pll_in_use & (1 << ATOM_PPLL2)))
return radeon_crtc->crtc_id; return ATOM_PPLL2;
if (!(pll_in_use & (1 << ATOM_PPLL1)))
return ATOM_PPLL1;
} }
DRM_ERROR("unable to allocate a PPLL\n");
return ATOM_PPLL_INVALID;
} else {
/* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
return radeon_crtc->crtc_id;
} }
} }
......
...@@ -1372,7 +1372,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s ...@@ -1372,7 +1372,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN);
for (i = 0; i < rdev->num_crtc; i++) { for (i = 0; i < rdev->num_crtc; i++) {
if (save->crtc_enabled) { if (save->crtc_enabled[i]) {
if (ASIC_IS_DCE6(rdev)) { if (ASIC_IS_DCE6(rdev)) {
tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
......
...@@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg) ...@@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg)
/* check config regs */ /* check config regs */
switch (reg) { switch (reg) {
case GRBM_GFX_INDEX: case GRBM_GFX_INDEX:
case CP_STRMOUT_CNTL:
case CP_COHER_CNTL:
case CP_COHER_SIZE:
case VGT_VTX_VECT_EJECT_REG: case VGT_VTX_VECT_EJECT_REG:
case VGT_CACHE_INVALIDATION: case VGT_CACHE_INVALIDATION:
case VGT_GS_VERTEX_REUSE: case VGT_GS_VERTEX_REUSE:
......
...@@ -91,6 +91,10 @@ ...@@ -91,6 +91,10 @@
#define FB_READ_EN (1 << 0) #define FB_READ_EN (1 << 0)
#define FB_WRITE_EN (1 << 1) #define FB_WRITE_EN (1 << 1)
#define CP_STRMOUT_CNTL 0x84FC
#define CP_COHER_CNTL 0x85F0
#define CP_COHER_SIZE 0x85F4
#define CP_COHER_BASE 0x85F8 #define CP_COHER_BASE 0x85F8
#define CP_STALLED_STAT1 0x8674 #define CP_STALLED_STAT1 0x8674
#define CP_STALLED_STAT2 0x8678 #define CP_STALLED_STAT2 0x8678
......
...@@ -2474,6 +2474,7 @@ static bool si_vm_reg_valid(u32 reg) ...@@ -2474,6 +2474,7 @@ static bool si_vm_reg_valid(u32 reg)
/* check config regs */ /* check config regs */
switch (reg) { switch (reg) {
case GRBM_GFX_INDEX: case GRBM_GFX_INDEX:
case CP_STRMOUT_CNTL:
case VGT_VTX_VECT_EJECT_REG: case VGT_VTX_VECT_EJECT_REG:
case VGT_CACHE_INVALIDATION: case VGT_CACHE_INVALIDATION:
case VGT_ESGS_RING_SIZE: case VGT_ESGS_RING_SIZE:
......
...@@ -424,6 +424,7 @@ ...@@ -424,6 +424,7 @@
# define RDERR_INT_ENABLE (1 << 0) # define RDERR_INT_ENABLE (1 << 0)
# define GUI_IDLE_INT_ENABLE (1 << 19) # define GUI_IDLE_INT_ENABLE (1 << 19)
#define CP_STRMOUT_CNTL 0x84FC
#define SCRATCH_REG0 0x8500 #define SCRATCH_REG0 0x8500
#define SCRATCH_REG1 0x8504 #define SCRATCH_REG1 0x8504
#define SCRATCH_REG2 0x8508 #define SCRATCH_REG2 0x8508
......
...@@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) ...@@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
BUG_ON(!atomic_read(&bo->reserved)); BUG_ON(!atomic_read(&bo->reserved));
BUG_ON(old_mem_type != TTM_PL_VRAM && BUG_ON(old_mem_type != TTM_PL_VRAM &&
old_mem_type != VMW_PL_FLAG_GMR); old_mem_type != VMW_PL_GMR);
pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
if (pin) if (pin)
......
...@@ -1098,6 +1098,11 @@ static void vmw_pm_complete(struct device *kdev) ...@@ -1098,6 +1098,11 @@ static void vmw_pm_complete(struct device *kdev)
struct drm_device *dev = pci_get_drvdata(pdev); struct drm_device *dev = pci_get_drvdata(pdev);
struct vmw_private *dev_priv = vmw_priv(dev); struct vmw_private *dev_priv = vmw_priv(dev);
mutex_lock(&dev_priv->hw_mutex);
vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
(void) vmw_read(dev_priv, SVGA_REG_ID);
mutex_unlock(&dev_priv->hw_mutex);
/** /**
* Reclaim 3d reference held by fbdev and potentially * Reclaim 3d reference held by fbdev and potentially
* start fifo. * start fifo.
......
...@@ -42,7 +42,6 @@ static struct cdev hidraw_cdev; ...@@ -42,7 +42,6 @@ static struct cdev hidraw_cdev;
static struct class *hidraw_class; static struct class *hidraw_class;
static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
static DEFINE_MUTEX(minors_lock); static DEFINE_MUTEX(minors_lock);
static void drop_ref(struct hidraw *hid, int exists_bit);
static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{ {
...@@ -114,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, ...@@ -114,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
__u8 *buf; __u8 *buf;
int ret = 0; int ret = 0;
if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { if (!hidraw_table[minor]) {
ret = -ENODEV; ret = -ENODEV;
goto out; goto out;
} }
...@@ -262,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file) ...@@ -262,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
} }
mutex_lock(&minors_lock); mutex_lock(&minors_lock);
if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { if (!hidraw_table[minor]) {
err = -ENODEV; err = -ENODEV;
goto out_unlock; goto out_unlock;
} }
...@@ -299,12 +298,36 @@ static int hidraw_open(struct inode *inode, struct file *file) ...@@ -299,12 +298,36 @@ static int hidraw_open(struct inode *inode, struct file *file)
static int hidraw_release(struct inode * inode, struct file * file) static int hidraw_release(struct inode * inode, struct file * file)
{ {
unsigned int minor = iminor(inode); unsigned int minor = iminor(inode);
struct hidraw *dev;
struct hidraw_list *list = file->private_data; struct hidraw_list *list = file->private_data;
int ret;
int i;
mutex_lock(&minors_lock);
if (!hidraw_table[minor]) {
ret = -ENODEV;
goto unlock;
}
drop_ref(hidraw_table[minor], 0);
list_del(&list->node); list_del(&list->node);
dev = hidraw_table[minor];
if (!--dev->open) {
if (list->hidraw->exist) {
hid_hw_power(dev->hid, PM_HINT_NORMAL);
hid_hw_close(dev->hid);
} else {
kfree(list->hidraw);
}
}
for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
kfree(list->buffer[i].value);
kfree(list); kfree(list);
return 0; ret = 0;
unlock:
mutex_unlock(&minors_lock);
return ret;
} }
static long hidraw_ioctl(struct file *file, unsigned int cmd, static long hidraw_ioctl(struct file *file, unsigned int cmd,
...@@ -506,7 +529,21 @@ EXPORT_SYMBOL_GPL(hidraw_connect); ...@@ -506,7 +529,21 @@ EXPORT_SYMBOL_GPL(hidraw_connect);
void hidraw_disconnect(struct hid_device *hid) void hidraw_disconnect(struct hid_device *hid)
{ {
struct hidraw *hidraw = hid->hidraw; struct hidraw *hidraw = hid->hidraw;
drop_ref(hidraw, 1);
mutex_lock(&minors_lock);
hidraw->exist = 0;
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
hidraw_table[hidraw->minor] = NULL;
if (hidraw->open) {
hid_hw_close(hid);
wake_up_interruptible(&hidraw->wait);
} else {
kfree(hidraw);
}
mutex_unlock(&minors_lock);
} }
EXPORT_SYMBOL_GPL(hidraw_disconnect); EXPORT_SYMBOL_GPL(hidraw_disconnect);
...@@ -555,23 +592,3 @@ void hidraw_exit(void) ...@@ -555,23 +592,3 @@ void hidraw_exit(void)
unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
} }
static void drop_ref(struct hidraw *hidraw, int exists_bit)
{
mutex_lock(&minors_lock);
if (exists_bit) {
hid_hw_close(hidraw->hid);
hidraw->exist = 0;
if (hidraw->open)
wake_up_interruptible(&hidraw->wait);
} else {
--hidraw->open;
}
if (!hidraw->open && !hidraw->exist) {
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
hidraw_table[hidraw->minor] = NULL;
kfree(hidraw);
}
mutex_unlock(&minors_lock);
}
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
* ASB100-A supports pwm1, while plain ASB100 does not. There is no known * ASB100-A supports pwm1, while plain ASB100 does not. There is no known
* way for the driver to tell which one is there. * way for the driver to tell which one is there.
* *
* Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* asb100 7 3 1 4 0x31 0x0694 yes no * asb100 7 3 1 4 0x31 0x0694 yes no
*/ */
......
...@@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) ...@@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
mutex_init(&data->lock); mutex_init(&data->lock);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
data->name = w83627ehf_device_names[sio_data->kind]; data->name = w83627ehf_device_names[sio_data->kind];
data->bank = 0xff; /* Force initial bank selection */
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
/* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
/* /*
* Supports following chips: * Supports following chips:
* *
* Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) * w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC)
* w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) * w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC)
* w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) * w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC)
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
/* /*
* Supports following chips: * Supports following chips:
* *
* Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* as99127f 7 3 0 3 0x31 0x12c3 yes no * as99127f 7 3 0 3 0x31 0x12c3 yes no
* as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no * as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no
* w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes * w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
/* /*
* Supports following chips: * Supports following chips:
* *
* Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* w83791d 10 5 5 3 0x71 0x5ca3 yes no * w83791d 10 5 5 3 0x71 0x5ca3 yes no
* *
* The w83791d chip appears to be part way between the 83781d and the * The w83791d chip appears to be part way between the 83781d and the
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
/* /*
* Supports following chips: * Supports following chips:
* *
* Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* w83792d 9 7 7 3 0x7a 0x5ca3 yes no * w83792d 9 7 7 3 0x7a 0x5ca3 yes no
*/ */
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
/* /*
* Supports following chips: * Supports following chips:
* *
* Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* w83l786ng 3 2 2 2 0x7b 0x5ca3 yes no * w83l786ng 3 2 2 2 0x7b 0x5ca3 yes no
*/ */
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
menuconfig ISDN menuconfig ISDN
bool "ISDN support" bool "ISDN support"
depends on NET depends on NET && NETDEVICES
depends on !S390 && !UML depends on !S390 && !UML
---help--- ---help---
ISDN ("Integrated Services Digital Network", called RNIS in France) ISDN ("Integrated Services Digital Network", called RNIS in France)
......
...@@ -6,7 +6,7 @@ if ISDN_I4L ...@@ -6,7 +6,7 @@ if ISDN_I4L
config ISDN_PPP config ISDN_PPP
bool "Support synchronous PPP" bool "Support synchronous PPP"
depends on INET && NETDEVICES depends on INET
select SLHC select SLHC
help help
Over digital connections such as ISDN, there is no need to Over digital connections such as ISDN, there is no need to
......
...@@ -1312,7 +1312,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) ...@@ -1312,7 +1312,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
} else } else
return -EINVAL; return -EINVAL;
break; break;
#ifdef CONFIG_NETDEVICES
case IIOCNETGPN: case IIOCNETGPN:
/* Get peer phone number of a connected /* Get peer phone number of a connected
* isdn network interface */ * isdn network interface */
...@@ -1322,7 +1321,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) ...@@ -1322,7 +1321,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
return isdn_net_getpeer(&phone, argp); return isdn_net_getpeer(&phone, argp);
} else } else
return -EINVAL; return -EINVAL;
#endif
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1352,7 +1350,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) ...@@ -1352,7 +1350,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
case IIOCNETLCR: case IIOCNETLCR:
printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n"); printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
return -ENODEV; return -ENODEV;
#ifdef CONFIG_NETDEVICES
case IIOCNETAIF: case IIOCNETAIF:
/* Add a network-interface */ /* Add a network-interface */
if (arg) { if (arg) {
...@@ -1491,7 +1488,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) ...@@ -1491,7 +1488,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
return -EFAULT; return -EFAULT;
return isdn_net_force_hangup(name); return isdn_net_force_hangup(name);
break; break;
#endif /* CONFIG_NETDEVICES */
case IIOCSETVER: case IIOCSETVER:
dev->net_verbose = arg; dev->net_verbose = arg;
printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose); printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
......
...@@ -208,7 +208,7 @@ static unsigned long exynos5250_dwmmc_caps[4] = { ...@@ -208,7 +208,7 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
MMC_CAP_CMD23, MMC_CAP_CMD23,
}; };
static struct dw_mci_drv_data exynos5250_drv_data = { static const struct dw_mci_drv_data exynos5250_drv_data = {
.caps = exynos5250_dwmmc_caps, .caps = exynos5250_dwmmc_caps,
.init = dw_mci_exynos_priv_init, .init = dw_mci_exynos_priv_init,
.setup_clock = dw_mci_exynos_setup_clock, .setup_clock = dw_mci_exynos_setup_clock,
...@@ -220,14 +220,14 @@ static struct dw_mci_drv_data exynos5250_drv_data = { ...@@ -220,14 +220,14 @@ static struct dw_mci_drv_data exynos5250_drv_data = {
static const struct of_device_id dw_mci_exynos_match[] = { static const struct of_device_id dw_mci_exynos_match[] = {
{ .compatible = "samsung,exynos5250-dw-mshc", { .compatible = "samsung,exynos5250-dw-mshc",
.data = (void *)&exynos5250_drv_data, }, .data = &exynos5250_drv_data, },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
int dw_mci_exynos_probe(struct platform_device *pdev) int dw_mci_exynos_probe(struct platform_device *pdev)
{ {
struct dw_mci_drv_data *drv_data; const struct dw_mci_drv_data *drv_data;
const struct of_device_id *match; const struct of_device_id *match;
match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node); match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node);
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "dw_mmc.h" #include "dw_mmc.h"
int dw_mci_pltfm_register(struct platform_device *pdev, int dw_mci_pltfm_register(struct platform_device *pdev,
struct dw_mci_drv_data *drv_data) const struct dw_mci_drv_data *drv_data)
{ {
struct dw_mci *host; struct dw_mci *host;
struct resource *regs; struct resource *regs;
...@@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev, ...@@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
if (!host->regs) if (!host->regs)
return -ENOMEM; return -ENOMEM;
if (host->drv_data->init) { if (drv_data && drv_data->init) {
ret = host->drv_data->init(host); ret = drv_data->init(host);
if (ret) if (ret)
return ret; return ret;
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#define _DW_MMC_PLTFM_H_ #define _DW_MMC_PLTFM_H_
extern int dw_mci_pltfm_register(struct platform_device *pdev, extern int dw_mci_pltfm_register(struct platform_device *pdev,
struct dw_mci_drv_data *drv_data); const struct dw_mci_drv_data *drv_data);
extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev); extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);
extern const struct dev_pm_ops dw_mci_pltfm_pmops; extern const struct dev_pm_ops dw_mci_pltfm_pmops;
......
...@@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) ...@@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
{ {
struct mmc_data *data; struct mmc_data *data;
struct dw_mci_slot *slot = mmc_priv(mmc); struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci_drv_data *drv_data = slot->host->drv_data;
u32 cmdr; u32 cmdr;
cmd->error = -EINPROGRESS; cmd->error = -EINPROGRESS;
...@@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) ...@@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
cmdr |= SDMMC_CMD_DAT_WR; cmdr |= SDMMC_CMD_DAT_WR;
} }
if (slot->host->drv_data->prepare_command) if (drv_data && drv_data->prepare_command)
slot->host->drv_data->prepare_command(slot->host, &cmdr); drv_data->prepare_command(slot->host, &cmdr);
return cmdr; return cmdr;
} }
...@@ -434,7 +435,7 @@ static int dw_mci_idmac_init(struct dw_mci *host) ...@@ -434,7 +435,7 @@ static int dw_mci_idmac_init(struct dw_mci *host)
return 0; return 0;
} }
static struct dw_mci_dma_ops dw_mci_idmac_ops = { static const struct dw_mci_dma_ops dw_mci_idmac_ops = {
.init = dw_mci_idmac_init, .init = dw_mci_idmac_init,
.start = dw_mci_idmac_start_dma, .start = dw_mci_idmac_start_dma,
.stop = dw_mci_idmac_stop_dma, .stop = dw_mci_idmac_stop_dma,
...@@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) ...@@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{ {
struct dw_mci_slot *slot = mmc_priv(mmc); struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci_drv_data *drv_data = slot->host->drv_data;
u32 regs; u32 regs;
/* set default 1 bit mode */ /* set default 1 bit mode */
...@@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
slot->clock = ios->clock; slot->clock = ios->clock;
} }
if (slot->host->drv_data->set_ios) if (drv_data && drv_data->set_ios)
slot->host->drv_data->set_ios(slot->host, ios); drv_data->set_ios(slot->host, ios);
switch (ios->power_mode) { switch (ios->power_mode) {
case MMC_POWER_UP: case MMC_POWER_UP:
...@@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) ...@@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
{ {
struct mmc_host *mmc; struct mmc_host *mmc;
struct dw_mci_slot *slot; struct dw_mci_slot *slot;
struct dw_mci_drv_data *drv_data = host->drv_data;
int ctrl_id, ret; int ctrl_id, ret;
u8 bus_width; u8 bus_width;
...@@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) ...@@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
} else { } else {
ctrl_id = to_platform_device(host->dev)->id; ctrl_id = to_platform_device(host->dev)->id;
} }
if (host->drv_data && host->drv_data->caps) if (drv_data && drv_data->caps)
mmc->caps |= host->drv_data->caps[ctrl_id]; mmc->caps |= drv_data->caps[ctrl_id];
if (host->pdata->caps2) if (host->pdata->caps2)
mmc->caps2 = host->pdata->caps2; mmc->caps2 = host->pdata->caps2;
...@@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) ...@@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
else else
bus_width = 1; bus_width = 1;
if (host->drv_data->setup_bus) { if (drv_data && drv_data->setup_bus) {
struct device_node *slot_np; struct device_node *slot_np;
slot_np = dw_mci_of_find_slot_node(host->dev, slot->id); slot_np = dw_mci_of_find_slot_node(host->dev, slot->id);
ret = host->drv_data->setup_bus(host, slot_np, bus_width); ret = drv_data->setup_bus(host, slot_np, bus_width);
if (ret) if (ret)
goto err_setup_bus; goto err_setup_bus;
} }
...@@ -1968,7 +1971,7 @@ static void dw_mci_init_dma(struct dw_mci *host) ...@@ -1968,7 +1971,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
/* Determine which DMA interface to use */ /* Determine which DMA interface to use */
#ifdef CONFIG_MMC_DW_IDMAC #ifdef CONFIG_MMC_DW_IDMAC
host->dma_ops = &dw_mci_idmac_ops; host->dma_ops = &dw_mci_idmac_ops;
dev_info(&host->dev, "Using internal DMA controller.\n"); dev_info(host->dev, "Using internal DMA controller.\n");
#endif #endif
if (!host->dma_ops) if (!host->dma_ops)
...@@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) ...@@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
struct dw_mci_board *pdata; struct dw_mci_board *pdata;
struct device *dev = host->dev; struct device *dev = host->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct dw_mci_drv_data *drv_data = host->drv_data;
int idx, ret; int idx, ret;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
...@@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) ...@@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
if (host->drv_data->parse_dt) { if (drv_data && drv_data->parse_dt) {
ret = host->drv_data->parse_dt(host); ret = drv_data->parse_dt(host);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) ...@@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
int dw_mci_probe(struct dw_mci *host) int dw_mci_probe(struct dw_mci *host)
{ {
struct dw_mci_drv_data *drv_data = host->drv_data;
int width, i, ret = 0; int width, i, ret = 0;
u32 fifo_size; u32 fifo_size;
int init_slots = 0; int init_slots = 0;
...@@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host) ...@@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host)
else else
host->bus_hz = clk_get_rate(host->ciu_clk); host->bus_hz = clk_get_rate(host->ciu_clk);
if (host->drv_data->setup_clock) { if (drv_data && drv_data->setup_clock) {
ret = host->drv_data->setup_clock(host); ret = drv_data->setup_clock(host);
if (ret) { if (ret) {
dev_err(host->dev, dev_err(host->dev,
"implementation specific clock setup failed\n"); "implementation specific clock setup failed\n");
...@@ -2228,6 +2233,21 @@ int dw_mci_probe(struct dw_mci *host) ...@@ -2228,6 +2233,21 @@ int dw_mci_probe(struct dw_mci *host)
else else
host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
/*
* Enable interrupts for command done, data over, data empty, card det,
* receive ready and error such as transmit, receive timeout, crc error
*/
mci_writel(host, RINTSTS, 0xFFFFFFFF);
mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
SDMMC_INT_TXDR | SDMMC_INT_RXDR |
DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
dev_info(host->dev, "DW MMC controller at irq %d, "
"%d bit host data width, "
"%u deep fifo\n",
host->irq, width, fifo_size);
/* We need at least one slot to succeed */ /* We need at least one slot to succeed */
for (i = 0; i < host->num_slots; i++) { for (i = 0; i < host->num_slots; i++) {
ret = dw_mci_init_slot(host, i); ret = dw_mci_init_slot(host, i);
...@@ -2257,20 +2277,6 @@ int dw_mci_probe(struct dw_mci *host) ...@@ -2257,20 +2277,6 @@ int dw_mci_probe(struct dw_mci *host)
else else
host->data_offset = DATA_240A_OFFSET; host->data_offset = DATA_240A_OFFSET;
/*
* Enable interrupts for command done, data over, data empty, card det,
* receive ready and error such as transmit, receive timeout, crc error
*/
mci_writel(host, RINTSTS, 0xFFFFFFFF);
mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
SDMMC_INT_TXDR | SDMMC_INT_RXDR |
DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
dev_info(host->dev, "DW MMC controller at irq %d, "
"%d bit host data width, "
"%u deep fifo\n",
host->irq, width, fifo_size);
if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
......
...@@ -1134,4 +1134,4 @@ module_platform_driver(mxcmci_driver); ...@@ -1134,4 +1134,4 @@ module_platform_driver(mxcmci_driver);
MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
MODULE_AUTHOR("Sascha Hauer, Pengutronix"); MODULE_AUTHOR("Sascha Hauer, Pengutronix");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:imx-mmc"); MODULE_ALIAS("platform:mxc-mmc");
...@@ -178,7 +178,8 @@ struct omap_hsmmc_host { ...@@ -178,7 +178,8 @@ struct omap_hsmmc_host {
static int omap_hsmmc_card_detect(struct device *dev, int slot) static int omap_hsmmc_card_detect(struct device *dev, int slot)
{ {
struct omap_mmc_platform_data *mmc = dev->platform_data; struct omap_hsmmc_host *host = dev_get_drvdata(dev);
struct omap_mmc_platform_data *mmc = host->pdata;
/* NOTE: assumes card detect signal is active-low */ /* NOTE: assumes card detect signal is active-low */
return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
...@@ -186,7 +187,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot) ...@@ -186,7 +187,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot)
static int omap_hsmmc_get_wp(struct device *dev, int slot) static int omap_hsmmc_get_wp(struct device *dev, int slot)
{ {
struct omap_mmc_platform_data *mmc = dev->platform_data; struct omap_hsmmc_host *host = dev_get_drvdata(dev);
struct omap_mmc_platform_data *mmc = host->pdata;
/* NOTE: assumes write protect signal is active-high */ /* NOTE: assumes write protect signal is active-high */
return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); return gpio_get_value_cansleep(mmc->slots[0].gpio_wp);
...@@ -194,7 +196,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot) ...@@ -194,7 +196,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot)
static int omap_hsmmc_get_cover_state(struct device *dev, int slot) static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
{ {
struct omap_mmc_platform_data *mmc = dev->platform_data; struct omap_hsmmc_host *host = dev_get_drvdata(dev);
struct omap_mmc_platform_data *mmc = host->pdata;
/* NOTE: assumes card detect signal is active-low */ /* NOTE: assumes card detect signal is active-low */
return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
...@@ -204,7 +207,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot) ...@@ -204,7 +207,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
{ {
struct omap_mmc_platform_data *mmc = dev->platform_data; struct omap_hsmmc_host *host = dev_get_drvdata(dev);
struct omap_mmc_platform_data *mmc = host->pdata;
disable_irq(mmc->slots[0].card_detect_irq); disable_irq(mmc->slots[0].card_detect_irq);
return 0; return 0;
...@@ -212,7 +216,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) ...@@ -212,7 +216,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)
{ {
struct omap_mmc_platform_data *mmc = dev->platform_data; struct omap_hsmmc_host *host = dev_get_drvdata(dev);
struct omap_mmc_platform_data *mmc = host->pdata;
enable_irq(mmc->slots[0].card_detect_irq); enable_irq(mmc->slots[0].card_detect_irq);
return 0; return 0;
...@@ -2009,9 +2014,9 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev) ...@@ -2009,9 +2014,9 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
clk_put(host->dbclk); clk_put(host->dbclk);
} }
mmc_free_host(host->mmc); omap_hsmmc_gpio_free(host->pdata);
iounmap(host->base); iounmap(host->base);
omap_hsmmc_gpio_free(pdev->dev.platform_data); mmc_free_host(host->mmc);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res) if (res)
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -84,30 +85,32 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev) ...@@ -84,30 +85,32 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev)
struct sdhci_dove_priv *priv; struct sdhci_dove_priv *priv;
int ret; int ret;
ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
if (ret)
goto sdhci_dove_register_fail;
priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv), priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv),
GFP_KERNEL); GFP_KERNEL);
if (!priv) { if (!priv) {
dev_err(&pdev->dev, "unable to allocate private data"); dev_err(&pdev->dev, "unable to allocate private data");
ret = -ENOMEM; return -ENOMEM;
goto sdhci_dove_allocate_fail;
} }
priv->clk = clk_get(&pdev->dev, NULL);
if (!IS_ERR(priv->clk))
clk_prepare_enable(priv->clk);
ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
if (ret)
goto sdhci_dove_register_fail;
host = platform_get_drvdata(pdev); host = platform_get_drvdata(pdev);
pltfm_host = sdhci_priv(host); pltfm_host = sdhci_priv(host);
pltfm_host->priv = priv; pltfm_host->priv = priv;
priv->clk = clk_get(&pdev->dev, NULL);
if (!IS_ERR(priv->clk))
clk_prepare_enable(priv->clk);
return 0; return 0;
sdhci_dove_allocate_fail:
sdhci_pltfm_unregister(pdev);
sdhci_dove_register_fail: sdhci_dove_register_fail:
if (!IS_ERR(priv->clk)) {
clk_disable_unprepare(priv->clk);
clk_put(priv->clk);
}
return ret; return ret;
} }
...@@ -117,14 +120,13 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev) ...@@ -117,14 +120,13 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_dove_priv *priv = pltfm_host->priv; struct sdhci_dove_priv *priv = pltfm_host->priv;
if (priv->clk) { sdhci_pltfm_unregister(pdev);
if (!IS_ERR(priv->clk)) {
clk_disable_unprepare(priv->clk); if (!IS_ERR(priv->clk)) {
clk_put(priv->clk); clk_disable_unprepare(priv->clk);
} clk_put(priv->clk);
devm_kfree(&pdev->dev, priv->clk);
} }
return sdhci_pltfm_unregister(pdev); return 0;
} }
static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = { static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {
......
...@@ -169,6 +169,16 @@ static void esdhc_of_resume(struct sdhci_host *host) ...@@ -169,6 +169,16 @@ static void esdhc_of_resume(struct sdhci_host *host)
} }
#endif #endif
static void esdhc_of_platform_init(struct sdhci_host *host)
{
u32 vvn;
vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
if (vvn == VENDOR_V_22)
host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
}
static struct sdhci_ops sdhci_esdhc_ops = { static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl, .read_l = esdhc_readl,
.read_w = esdhc_readw, .read_w = esdhc_readw,
...@@ -180,6 +190,7 @@ static struct sdhci_ops sdhci_esdhc_ops = { ...@@ -180,6 +190,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.enable_dma = esdhc_of_enable_dma, .enable_dma = esdhc_of_enable_dma,
.get_max_clock = esdhc_of_get_max_clock, .get_max_clock = esdhc_of_get_max_clock,
.get_min_clock = esdhc_of_get_min_clock, .get_min_clock = esdhc_of_get_min_clock,
.platform_init = esdhc_of_platform_init,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.platform_suspend = esdhc_of_suspend, .platform_suspend = esdhc_of_suspend,
.platform_resume = esdhc_of_resume, .platform_resume = esdhc_of_resume,
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册