ARM i.MX fixes for 3.7-rc

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABCAAGBQJQplk7AAoJEPFlmONMx+ezYSMP/2oG4bGXA3O0ktyTOC2VA63v
 VEoElBItx1ZdwKmVOMOQfH5IHHFUnOxrIBB27+67qr22/gfjlrUftpVMkiwpNhqP
 itYkPZWynkJ+1mZMpV7nJC9PEuyKdw5FKQJovsrsGYkwOfXfylx8kJWJH+zLwXRg
 wLcTsb33U+H+zyWz2TCLr8+SHEiepVcRrsBgjDp1PlIK1eMhZPztdQWVvD6zZjej
 vnB4ea+VUE8Q6HS7CwtBf++u97hsehD7ZZ1raEllhdiXi6SXtK0ARMKk0gSalQXU
 mg/tV2yU3blFZFFcebPG1Mdfow6E+5xzrboCJwB0X3LnkHkdBsUr5KA4AzqedDt9
 KmQqXj1vsLpDQaGMrT+icRkZmKgeBnNb84IxU69WJiEiStJeUNz7WWtGhmGcMn7L
 T9H33gaJbrYqcVj2NSiHP1XbHG0NKv79PgogzfPxQdR0oLXCVpFdw1cgy898bNFj
 Oche3MG1w9p2hTfDZbQpivJOSZWqh92ug8/yTPFR8EwoM6WHhROv13E1GdO22LF0
 QPQOcXtyiYsPlPB02rqpkfAC49At5o03i3IGcT5wn4wTbyEa8BQl5ZyDwAXg2ZAi
 MBMskQ2V4u5sbf8Ok0Vj7ji/OLgKz/k7D3IfQ6CyBaOtILIF6X96Mh+sWGsX82sj
 QTwkEhTr/Tgk5wtivn8i
 =3SGE
 -----END PGP SIGNATURE-----

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: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2012-11-16 16:42:59 +01:00
commit 57260e4088
205 changed files with 1689 additions and 1155 deletions

View File

@ -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
ffffffbbffff0000 ffffffbcffffffff 64KB [guard page]
ffffffbc00000000 ffffffbdffffffff 8GB vmemmap ffffffbc00000000 ffffffbdffffffff 8GB vmemmap
ffffffbe00000000 ffffffbffbffffff ~8GB [guard, future vmmemap] ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap]
ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space
ffffffbbffff0000 ffffffbcffffffff ~2MB [guard]
ffffffbffc000000 ffffffbfffffffff 64MB modules ffffffbffc000000 ffffffbfffffffff 64MB modules

View File

@ -1,7 +1,7 @@
VERSION = 3 VERSION = 3
PATCHLEVEL = 7 PATCHLEVEL = 7
SUBLEVEL = 0 SUBLEVEL = 0
EXTRAVERSION = -rc4 EXTRAVERSION = -rc5
NAME = Terrified Chipmunk NAME = Terrified Chipmunk
# *DOCUMENTATION* # *DOCUMENTATION*

View File

@ -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)
{ {
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;
} }

View File

@ -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

View File

@ -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 @@
#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

View File

@ -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)

View File

@ -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,19 +182,16 @@ 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 = {
.suspend = sched_clock_suspend, .suspend = sched_clock_suspend,

View File

@ -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;
} }

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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
/* /*

View File

@ -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);

View File

@ -1,6 +1,7 @@
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

View File

@ -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;
#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.
*/ */

View File

@ -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 {

View File

@ -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);
#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

View File

@ -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 {

View File

@ -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

View File

@ -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,
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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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>

View File

@ -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)
} }
#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,
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,6 +1276,8 @@ 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)
{ {
/* Do not clobber _HPAGE_TYPE_NONE pages! */
if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV))
pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO; pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
return pmd; return pmd;
} }

View File

@ -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:
.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

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -1,7 +1,7 @@
/* 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)
#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()

View File

@ -1,6 +1,46 @@
#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
@ -13,7 +53,16 @@
#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; \
rd %ccr, %g0; \
rd %ccr, %g0; \
.section .pause_3insn_patch,"ax";\
.word 88b; \
sllx tmp, 7, tmp; \
wr tmp, 0, %asr27; \
clr tmp; \
.previous; \
brnz,pt tmp, 88b; \
sub tmp, 1, tmp; \ sub tmp, 1, tmp; \
set BACKOFF_LIMIT, tmp; \ set BACKOFF_LIMIT, tmp; \
cmp reg, tmp; \ cmp reg, tmp; \

View File

@ -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;

View File

@ -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

View File

@ -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 */

View File

@ -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__ */

View File

@ -372,6 +372,8 @@ etrap_spill_fixup_64bit: \
/* Normal 32bit spill */ /* Normal 32bit spill */
#define SPILL_2_GENERIC(ASI) \ #define SPILL_2_GENERIC(ASI) \
and %sp, 1, %g3; \
brnz,pn %g3, (. - (128 + 4)); \
srl %sp, 0, %sp; \ srl %sp, 0, %sp; \
stwa %l0, [%sp + %g0] ASI; \ stwa %l0, [%sp + %g0] ASI; \
mov 0x04, %g3; \ mov 0x04, %g3; \
@ -398,13 +400,15 @@ 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: \
and %sp, 1, %g3; \
brnz,pn %g3, etrap_user_spill_64bit; \
srl %sp, 0, %sp; \ srl %sp, 0, %sp; \
stwa %l0, [%sp + 0x00] %asi; \ stwa %l0, [%sp + 0x00] %asi; \
stwa %l1, [%sp + 0x04] %asi; \ stwa %l1, [%sp + 0x04] %asi; \
@ -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,6 +596,8 @@ user_rtt_fill_64bit: \
/* Normal 32bit fill */ /* Normal 32bit fill */
#define FILL_2_GENERIC(ASI) \ #define FILL_2_GENERIC(ASI) \
and %sp, 1, %g3; \
brnz,pn %g3, (. - (128 + 4)); \
srl %sp, 0, %sp; \ srl %sp, 0, %sp; \
lduwa [%sp + %g0] ASI, %l0; \ lduwa [%sp + %g0] ASI, %l0; \
mov 0x04, %g2; \ mov 0x04, %g2; \
@ -616,13 +622,15 @@ 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: \
and %sp, 1, %g3; \
brnz,pn %g3, user_rtt_fill_64bit; \
srl %sp, 0, %sp; \ srl %sp, 0, %sp; \
lduwa [%sp + 0x00] %asi, %l0; \ lduwa [%sp + 0x00] %asi, %l0; \
lduwa [%sp + 0x04] %asi, %l1; \ lduwa [%sp + 0x04] %asi, %l1; \
@ -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;

View File

@ -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,

View File

@ -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 *);

View File

@ -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 */

View File

@ -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;
if (thread32_stack_is_64bit(ufp)) {
struct sparc_stackf *usf, sf;
ufp += STACK_BIAS;
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; usf = (struct sparc_stackf32 *) ufp;
if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
break; break;
pc = sf.callers_pc; pc = sf.callers_pc;
ufp = (unsigned long)sf.fp; 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);
} }

View File

@ -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)
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)
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)
{ {
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)
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);

View File

@ -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,
{ {
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;

View File

@ -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)
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)

View File

@ -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;
}

View File

@ -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

View File

@ -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:
.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

View File

@ -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)
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)
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)
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);

View File

@ -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)
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)
} 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);

View File

@ -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);

View File

@ -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

View File

@ -1,6 +1,6 @@
/* 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 */
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)

View File

@ -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);

View File

@ -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]));

View File

@ -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)
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;
} }

View File

@ -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;

View File

@ -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);

View File

@ -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"

View File

@ -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)
if (drm_device_is_unplugged(dev)) if (drm_device_is_unplugged(dev))
return -ENODEV; return -ENODEV;
retcode = drm_open_helper(inode, filp, dev);
if (!retcode) {
atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
if (!dev->open_count++) if (!dev->open_count++)
retcode = drm_setup(dev); need_setup = 1;
}
if (!retcode) {
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
if (dev->dev_mapping == NULL) old_mapping = dev->dev_mapping;
if (old_mapping == NULL)
dev->dev_mapping = &inode->i_data; dev->dev_mapping = &inode->i_data;
/* ihold ensures nobody can remove inode with our i_data */ /* ihold ensures nobody can remove inode with our i_data */
ihold(container_of(dev->dev_mapping, struct inode, i_data)); ihold(container_of(dev->dev_mapping, struct inode, i_data));
inode->i_mapping = dev->dev_mapping; inode->i_mapping = dev->dev_mapping;
filp->f_mapping = dev->dev_mapping; filp->f_mapping = dev->dev_mapping;
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
}
retcode = drm_open_helper(inode, filp, dev);
if (retcode)
goto err_undo;
atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
if (need_setup) {
retcode = drm_setup(dev);
if (retcode)
goto err_undo;
}
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);

View File

@ -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[] = {
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)
if (chan->vblank.crtc != crtc) if (chan->vblank.crtc != crtc)
continue; continue;
if (nv_device(priv)->chipset == 0x50) {
nv_wr32(priv, 0x001704, chan->vblank.channel); nv_wr32(priv, 0x001704, chan->vblank.channel);
nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
bar->flush(bar);
if (nv_device(priv)->chipset == 0x50) {
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);
bar->flush(bar);
nv_wr32(priv, 0x06000c, nv_wr32(priv, 0x06000c,
upper_32_bits(chan->vblank.offset)); upper_32_bits(chan->vblank.offset));
} nv_wr32(priv, 0x060010,
nv_wr32(priv, 0x060010, chan->vblank.offset); lower_32_bits(chan->vblank.offset));
nv_wr32(priv, 0x060014, chan->vblank.value); nv_wr32(priv, 0x060014, chan->vblank.value);
} }

View File

@ -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;

View File

@ -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;
}; };
/******************************************************************************* /*******************************************************************************

View File

@ -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);

View File

@ -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;
} }

View File

@ -1696,8 +1696,7 @@ 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
@ -1715,10 +1714,20 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
} }
/* 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;
} else {
if (!(pll_in_use & (1 << ATOM_PPLL2)))
return ATOM_PPLL2;
if (!(pll_in_use & (1 << ATOM_PPLL1)))
return ATOM_PPLL1;
}
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 {
@ -1726,7 +1735,6 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
return radeon_crtc->crtc_id; return radeon_crtc->crtc_id;
} }
} }
}
void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev) void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev)
{ {

View File

@ -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;

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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,
__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)
} }
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 @@ out:
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);
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)
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);
}

View File

@ -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 */

View File

@ -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)

View File

@ -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

View File

@ -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)
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)
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)
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);

View File

@ -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 = {
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);

View File

@ -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,
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;
} }

View File

@ -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;

View File

@ -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)
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)
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)
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)
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)
{ {
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)
} 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)
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)
/* 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)
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)
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)
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)
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)
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)
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");

View File

@ -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");

View File

@ -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)
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)
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)
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)
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)
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)

View File

@ -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)
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)
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)) { if (!IS_ERR(priv->clk)) {
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
clk_put(priv->clk); clk_put(priv->clk);
} }
devm_kfree(&pdev->dev, priv->clk); return 0;
}
return sdhci_pltfm_unregister(pdev);
} }
static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = { static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {

View File

@ -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 = {
.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,

View File

@ -1196,7 +1196,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
if (pci_resource_len(pdev, bar) != 0x100) { if (pci_resource_len(pdev, bar) < 0x100) {
dev_err(&pdev->dev, "Invalid iomem size. You may " dev_err(&pdev->dev, "Invalid iomem size. You may "
"experience problems.\n"); "experience problems.\n");
} }

View File

@ -150,6 +150,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
goto err_remap; goto err_remap;
} }
/*
* Some platforms need to probe the controller to be able to
* determine which caps should be used.
*/
if (host->ops && host->ops->platform_init)
host->ops->platform_init(host);
platform_set_drvdata(pdev, host); platform_set_drvdata(pdev, host);
return host; return host;

View File

@ -211,8 +211,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
if (ourhost->cur_clk != best_src) { if (ourhost->cur_clk != best_src) {
struct clk *clk = ourhost->clk_bus[best_src]; struct clk *clk = ourhost->clk_bus[best_src];
clk_enable(clk); clk_prepare_enable(clk);
clk_disable(ourhost->clk_bus[ourhost->cur_clk]); clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
/* turn clock off to card before changing clock source */ /* turn clock off to card before changing clock source */
writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
@ -607,7 +607,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
} }
/* enable the local io clock and keep it running for the moment. */ /* enable the local io clock and keep it running for the moment. */
clk_enable(sc->clk_io); clk_prepare_enable(sc->clk_io);
for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
struct clk *clk; struct clk *clk;
@ -638,7 +638,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
} }
#ifndef CONFIG_PM_RUNTIME #ifndef CONFIG_PM_RUNTIME
clk_enable(sc->clk_bus[sc->cur_clk]); clk_prepare_enable(sc->clk_bus[sc->cur_clk]);
#endif #endif
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -747,13 +747,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
sdhci_s3c_setup_card_detect_gpio(sc); sdhci_s3c_setup_card_detect_gpio(sc);
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
clk_disable(sc->clk_io); if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
clk_disable_unprepare(sc->clk_io);
#endif #endif
return 0; return 0;
err_req_regs: err_req_regs:
#ifndef CONFIG_PM_RUNTIME #ifndef CONFIG_PM_RUNTIME
clk_disable(sc->clk_bus[sc->cur_clk]); clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
#endif #endif
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
if (sc->clk_bus[ptr]) { if (sc->clk_bus[ptr]) {
@ -762,7 +763,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
} }
err_no_busclks: err_no_busclks:
clk_disable(sc->clk_io); clk_disable_unprepare(sc->clk_io);
clk_put(sc->clk_io); clk_put(sc->clk_io);
err_io_clk: err_io_clk:
@ -794,7 +795,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
gpio_free(sc->ext_cd_gpio); gpio_free(sc->ext_cd_gpio);
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
clk_enable(sc->clk_io); if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
clk_prepare_enable(sc->clk_io);
#endif #endif
sdhci_remove_host(host, 1); sdhci_remove_host(host, 1);
@ -802,14 +804,14 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
#ifndef CONFIG_PM_RUNTIME #ifndef CONFIG_PM_RUNTIME
clk_disable(sc->clk_bus[sc->cur_clk]); clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
#endif #endif
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
if (sc->clk_bus[ptr]) { if (sc->clk_bus[ptr]) {
clk_put(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]);
} }
} }
clk_disable(sc->clk_io); clk_disable_unprepare(sc->clk_io);
clk_put(sc->clk_io); clk_put(sc->clk_io);
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
@ -849,8 +851,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev)
ret = sdhci_runtime_suspend_host(host); ret = sdhci_runtime_suspend_host(host);
clk_disable(ourhost->clk_bus[ourhost->cur_clk]); clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
clk_disable(busclk); clk_disable_unprepare(busclk);
return ret; return ret;
} }
@ -861,8 +863,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev)
struct clk *busclk = ourhost->clk_io; struct clk *busclk = ourhost->clk_io;
int ret; int ret;
clk_enable(busclk); clk_prepare_enable(busclk);
clk_enable(ourhost->clk_bus[ourhost->cur_clk]); clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);
ret = sdhci_runtime_resume_host(host); ret = sdhci_runtime_resume_host(host);
return ret; return ret;
} }

View File

@ -1315,8 +1315,10 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
*/ */
if ((host->flags & SDHCI_NEEDS_RETUNING) && if ((host->flags & SDHCI_NEEDS_RETUNING) &&
!(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
/* eMMC uses cmd21 while sd and sdio use cmd19 */ if (mmc->card) {
tuning_opcode = mmc->card->type == MMC_TYPE_MMC ? /* eMMC uses cmd21 but sd and sdio use cmd19 */
tuning_opcode =
mmc->card->type == MMC_TYPE_MMC ?
MMC_SEND_TUNING_BLOCK_HS200 : MMC_SEND_TUNING_BLOCK_HS200 :
MMC_SEND_TUNING_BLOCK; MMC_SEND_TUNING_BLOCK;
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
@ -1326,6 +1328,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
/* Restore original mmc_request structure */ /* Restore original mmc_request structure */
host->mrq = mrq; host->mrq = mrq;
} }
}
if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
sdhci_send_command(host, mrq->sbc); sdhci_send_command(host, mrq->sbc);
@ -2837,6 +2840,9 @@ int sdhci_add_host(struct sdhci_host *host)
if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
mmc->caps |= MMC_CAP_4_BIT_DATA; mmc->caps |= MMC_CAP_4_BIT_DATA;
if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
mmc->caps &= ~MMC_CAP_CMD23;
if (caps[0] & SDHCI_CAN_DO_HISPD) if (caps[0] & SDHCI_CAN_DO_HISPD)
mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
@ -2846,10 +2852,13 @@ int sdhci_add_host(struct sdhci_host *host)
/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc");
if (IS_ERR(host->vqmmc)) { if (IS_ERR_OR_NULL(host->vqmmc)) {
pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc)); if (PTR_ERR(host->vqmmc) < 0) {
pr_info("%s: no vqmmc regulator found\n",
mmc_hostname(mmc));
host->vqmmc = NULL; host->vqmmc = NULL;
} }
}
else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000)) else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))
regulator_enable(host->vqmmc); regulator_enable(host->vqmmc);
else else
@ -2904,9 +2913,12 @@ int sdhci_add_host(struct sdhci_host *host)
ocr_avail = 0; ocr_avail = 0;
host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
if (IS_ERR(host->vmmc)) { if (IS_ERR_OR_NULL(host->vmmc)) {
pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); if (PTR_ERR(host->vmmc) < 0) {
pr_info("%s: no vmmc regulator found\n",
mmc_hostname(mmc));
host->vmmc = NULL; host->vmmc = NULL;
}
} else } else
regulator_enable(host->vmmc); regulator_enable(host->vmmc);

View File

@ -278,6 +278,7 @@ struct sdhci_ops {
void (*hw_reset)(struct sdhci_host *host); void (*hw_reset)(struct sdhci_host *host);
void (*platform_suspend)(struct sdhci_host *host); void (*platform_suspend)(struct sdhci_host *host);
void (*platform_resume)(struct sdhci_host *host); void (*platform_resume)(struct sdhci_host *host);
void (*platform_init)(struct sdhci_host *host);
}; };
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS

View File

@ -1466,9 +1466,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
clk_disable(host->hclk);
mmc_free_host(host->mmc); mmc_free_host(host->mmc);
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
clk_disable(host->hclk);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return 0; return 0;

Some files were not shown because too many files have changed in this diff Show More