Merge branch 'fixes' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
Pull ARM fixes from Russell King: "Some ARM fixes, the biggest of which is the fix for the signal return codes; this came up due to an interaction between the V7M nommu changes and the BE8 changes. Dave Martin spotted that the kexec trampoline wasn't being correctly copied (in a way which allows Thumb-2 to work). I've also fixed a number of breakages on footbridge platforms as I've upgraded one of my machines to v3.12... one which had a 1200 day uptime" * 'fixes' of git://ftp.arm.linux.org.uk/~rmk/linux-arm: ARM: 7907/1: lib: delay-loop: Add align directive to fix BogoMIPS calculation ARM: 7897/1: kexec: Use the right ISA for relocate_new_kernel ARM: 7895/1: signal: fix armv7-m build issue in sigreturn_codes.S ARM: footbridge: fix EBSA285 LEDs ARM: footbridge: fix VGA initialisation ARM: fix booting low-vectors machines ARM: dma-mapping: check DMA mask against available memory
This commit is contained in:
commit
1d07489aac
|
@ -61,7 +61,7 @@ extern void __pgd_error(const char *file, int line, pgd_t);
|
||||||
* mapping to be mapped at. This is particularly important for
|
* mapping to be mapped at. This is particularly important for
|
||||||
* non-high vector CPUs.
|
* non-high vector CPUs.
|
||||||
*/
|
*/
|
||||||
#define FIRST_USER_ADDRESS PAGE_SIZE
|
#define FIRST_USER_ADDRESS (PAGE_SIZE * 2)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use TASK_SIZE as the ceiling argument for free_pgtables() and
|
* Use TASK_SIZE as the ceiling argument for free_pgtables() and
|
||||||
|
|
|
@ -14,11 +14,12 @@
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/fncpy.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/smp_plat.h>
|
#include <asm/smp_plat.h>
|
||||||
#include <asm/system_misc.h>
|
#include <asm/system_misc.h>
|
||||||
|
|
||||||
extern const unsigned char relocate_new_kernel[];
|
extern void relocate_new_kernel(void);
|
||||||
extern const unsigned int relocate_new_kernel_size;
|
extern const unsigned int relocate_new_kernel_size;
|
||||||
|
|
||||||
extern unsigned long kexec_start_address;
|
extern unsigned long kexec_start_address;
|
||||||
|
@ -142,6 +143,8 @@ void machine_kexec(struct kimage *image)
|
||||||
{
|
{
|
||||||
unsigned long page_list;
|
unsigned long page_list;
|
||||||
unsigned long reboot_code_buffer_phys;
|
unsigned long reboot_code_buffer_phys;
|
||||||
|
unsigned long reboot_entry = (unsigned long)relocate_new_kernel;
|
||||||
|
unsigned long reboot_entry_phys;
|
||||||
void *reboot_code_buffer;
|
void *reboot_code_buffer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -168,16 +171,16 @@ void machine_kexec(struct kimage *image)
|
||||||
|
|
||||||
|
|
||||||
/* copy our kernel relocation code to the control code page */
|
/* copy our kernel relocation code to the control code page */
|
||||||
memcpy(reboot_code_buffer,
|
reboot_entry = fncpy(reboot_code_buffer,
|
||||||
relocate_new_kernel, relocate_new_kernel_size);
|
reboot_entry,
|
||||||
|
relocate_new_kernel_size);
|
||||||
|
reboot_entry_phys = (unsigned long)reboot_entry +
|
||||||
|
(reboot_code_buffer_phys - (unsigned long)reboot_code_buffer);
|
||||||
|
|
||||||
|
|
||||||
flush_icache_range((unsigned long) reboot_code_buffer,
|
|
||||||
(unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
|
|
||||||
printk(KERN_INFO "Bye!\n");
|
printk(KERN_INFO "Bye!\n");
|
||||||
|
|
||||||
if (kexec_reinit)
|
if (kexec_reinit)
|
||||||
kexec_reinit();
|
kexec_reinit();
|
||||||
|
|
||||||
soft_restart(reboot_code_buffer_phys);
|
soft_restart(reboot_entry_phys);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
* relocate_kernel.S - put the kernel image in place to boot
|
* relocate_kernel.S - put the kernel image in place to boot
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/linkage.h>
|
||||||
#include <asm/kexec.h>
|
#include <asm/kexec.h>
|
||||||
|
|
||||||
.globl relocate_new_kernel
|
.align 3 /* not needed for this code, but keeps fncpy() happy */
|
||||||
relocate_new_kernel:
|
|
||||||
|
ENTRY(relocate_new_kernel)
|
||||||
|
|
||||||
ldr r0,kexec_indirection_page
|
ldr r0,kexec_indirection_page
|
||||||
ldr r1,kexec_start_address
|
ldr r1,kexec_start_address
|
||||||
|
@ -79,6 +81,8 @@ kexec_mach_type:
|
||||||
kexec_boot_atags:
|
kexec_boot_atags:
|
||||||
.long 0x0
|
.long 0x0
|
||||||
|
|
||||||
|
ENDPROC(relocate_new_kernel)
|
||||||
|
|
||||||
relocate_new_kernel_end:
|
relocate_new_kernel_end:
|
||||||
|
|
||||||
.globl relocate_new_kernel_size
|
.globl relocate_new_kernel_size
|
||||||
|
|
|
@ -30,6 +30,27 @@
|
||||||
* snippets.
|
* snippets.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In CPU_THUMBONLY case kernel arm opcodes are not allowed.
|
||||||
|
* Note in this case codes skips those instructions but it uses .org
|
||||||
|
* directive to keep correct layout of sigreturn_codes array.
|
||||||
|
*/
|
||||||
|
#ifndef CONFIG_CPU_THUMBONLY
|
||||||
|
#define ARM_OK(code...) code
|
||||||
|
#else
|
||||||
|
#define ARM_OK(code...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.macro arm_slot n
|
||||||
|
.org sigreturn_codes + 12 * (\n)
|
||||||
|
ARM_OK( .arm )
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro thumb_slot n
|
||||||
|
.org sigreturn_codes + 12 * (\n) + 8
|
||||||
|
.thumb
|
||||||
|
.endm
|
||||||
|
|
||||||
#if __LINUX_ARM_ARCH__ <= 4
|
#if __LINUX_ARM_ARCH__ <= 4
|
||||||
/*
|
/*
|
||||||
* Note we manually set minimally required arch that supports
|
* Note we manually set minimally required arch that supports
|
||||||
|
@ -45,26 +66,27 @@
|
||||||
.global sigreturn_codes
|
.global sigreturn_codes
|
||||||
.type sigreturn_codes, #object
|
.type sigreturn_codes, #object
|
||||||
|
|
||||||
.arm
|
.align
|
||||||
|
|
||||||
sigreturn_codes:
|
sigreturn_codes:
|
||||||
|
|
||||||
/* ARM sigreturn syscall code snippet */
|
/* ARM sigreturn syscall code snippet */
|
||||||
mov r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)
|
arm_slot 0
|
||||||
swi #(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)
|
ARM_OK( mov r7, #(__NR_sigreturn - __NR_SYSCALL_BASE) )
|
||||||
|
ARM_OK( swi #(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE) )
|
||||||
|
|
||||||
/* Thumb sigreturn syscall code snippet */
|
/* Thumb sigreturn syscall code snippet */
|
||||||
.thumb
|
thumb_slot 0
|
||||||
movs r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)
|
movs r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)
|
||||||
swi #0
|
swi #0
|
||||||
|
|
||||||
/* ARM sigreturn_rt syscall code snippet */
|
/* ARM sigreturn_rt syscall code snippet */
|
||||||
.arm
|
arm_slot 1
|
||||||
mov r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
|
ARM_OK( mov r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE) )
|
||||||
swi #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)
|
ARM_OK( swi #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE) )
|
||||||
|
|
||||||
/* Thumb sigreturn_rt syscall code snippet */
|
/* Thumb sigreturn_rt syscall code snippet */
|
||||||
.thumb
|
thumb_slot 1
|
||||||
movs r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
|
movs r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
|
||||||
swi #0
|
swi #0
|
||||||
|
|
||||||
|
@ -74,7 +96,7 @@ sigreturn_codes:
|
||||||
* it is thumb case or not, so we need additional
|
* it is thumb case or not, so we need additional
|
||||||
* word after real last entry.
|
* word after real last entry.
|
||||||
*/
|
*/
|
||||||
.arm
|
arm_slot 2
|
||||||
.space 4
|
.space 4
|
||||||
|
|
||||||
.size sigreturn_codes, . - sigreturn_codes
|
.size sigreturn_codes, . - sigreturn_codes
|
||||||
|
|
|
@ -40,6 +40,7 @@ ENTRY(__loop_const_udelay) @ 0 <= r0 <= 0x7fffff06
|
||||||
/*
|
/*
|
||||||
* loops = r0 * HZ * loops_per_jiffy / 1000000
|
* loops = r0 * HZ * loops_per_jiffy / 1000000
|
||||||
*/
|
*/
|
||||||
|
.align 3
|
||||||
|
|
||||||
@ Delay routine
|
@ Delay routine
|
||||||
ENTRY(__loop_delay)
|
ENTRY(__loop_delay)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
#include <video/vga.h>
|
||||||
|
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
@ -196,6 +197,8 @@ void __init footbridge_map_io(void)
|
||||||
iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
|
iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
|
||||||
pci_map_io_early(__phys_to_pfn(DC21285_PCI_IO));
|
pci_map_io_early(__phys_to_pfn(DC21285_PCI_IO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vga_base = PCIMEM_BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void footbridge_restart(enum reboot_mode mode, const char *cmd)
|
void footbridge_restart(enum reboot_mode mode, const char *cmd)
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <video/vga.h>
|
|
||||||
|
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/mach/pci.h>
|
#include <asm/mach/pci.h>
|
||||||
|
@ -291,7 +290,6 @@ void __init dc21285_preinit(void)
|
||||||
int cfn_mode;
|
int cfn_mode;
|
||||||
|
|
||||||
pcibios_min_mem = 0x81000000;
|
pcibios_min_mem = 0x81000000;
|
||||||
vga_base = PCIMEM_BASE;
|
|
||||||
|
|
||||||
mem_size = (unsigned int)high_memory - PAGE_OFFSET;
|
mem_size = (unsigned int)high_memory - PAGE_OFFSET;
|
||||||
for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
|
for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
|
||||||
|
|
|
@ -30,21 +30,24 @@ static const struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *trigger;
|
const char *trigger;
|
||||||
} ebsa285_leds[] = {
|
} ebsa285_leds[] = {
|
||||||
{ "ebsa285:amber", "heartbeat", },
|
{ "ebsa285:amber", "cpu0", },
|
||||||
{ "ebsa285:green", "cpu0", },
|
{ "ebsa285:green", "heartbeat", },
|
||||||
{ "ebsa285:red",},
|
{ "ebsa285:red",},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static unsigned char hw_led_state;
|
||||||
|
|
||||||
static void ebsa285_led_set(struct led_classdev *cdev,
|
static void ebsa285_led_set(struct led_classdev *cdev,
|
||||||
enum led_brightness b)
|
enum led_brightness b)
|
||||||
{
|
{
|
||||||
struct ebsa285_led *led = container_of(cdev,
|
struct ebsa285_led *led = container_of(cdev,
|
||||||
struct ebsa285_led, cdev);
|
struct ebsa285_led, cdev);
|
||||||
|
|
||||||
if (b != LED_OFF)
|
if (b == LED_OFF)
|
||||||
*XBUS_LEDS |= led->mask;
|
hw_led_state |= led->mask;
|
||||||
else
|
else
|
||||||
*XBUS_LEDS &= ~led->mask;
|
hw_led_state &= ~led->mask;
|
||||||
|
*XBUS_LEDS = hw_led_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
|
static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
|
||||||
|
@ -52,18 +55,19 @@ static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
|
||||||
struct ebsa285_led *led = container_of(cdev,
|
struct ebsa285_led *led = container_of(cdev,
|
||||||
struct ebsa285_led, cdev);
|
struct ebsa285_led, cdev);
|
||||||
|
|
||||||
return (*XBUS_LEDS & led->mask) ? LED_FULL : LED_OFF;
|
return hw_led_state & led->mask ? LED_OFF : LED_FULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init ebsa285_leds_init(void)
|
static int __init ebsa285_leds_init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (machine_is_ebsa285())
|
if (!machine_is_ebsa285())
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* 3 LEDS All ON */
|
/* 3 LEDS all off */
|
||||||
*XBUS_LEDS |= XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
|
hw_led_state = XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
|
||||||
|
*XBUS_LEDS = hw_led_state;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) {
|
for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) {
|
||||||
struct ebsa285_led *led;
|
struct ebsa285_led *led;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
*
|
*
|
||||||
* DMA uncached mapping support.
|
* DMA uncached mapping support.
|
||||||
*/
|
*/
|
||||||
|
#include <linux/bootmem.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/gfp.h>
|
#include <linux/gfp.h>
|
||||||
|
@ -162,6 +163,8 @@ static u64 get_coherent_dma_mask(struct device *dev)
|
||||||
u64 mask = (u64)DMA_BIT_MASK(32);
|
u64 mask = (u64)DMA_BIT_MASK(32);
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
|
unsigned long max_dma_pfn;
|
||||||
|
|
||||||
mask = dev->coherent_dma_mask;
|
mask = dev->coherent_dma_mask;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -173,6 +176,8 @@ static u64 get_coherent_dma_mask(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
max_dma_pfn = min(max_pfn, arm_dma_pfn_limit);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the mask allows for more memory than we can address,
|
* If the mask allows for more memory than we can address,
|
||||||
* and we actually have that much memory, then fail the
|
* and we actually have that much memory, then fail the
|
||||||
|
@ -180,7 +185,7 @@ static u64 get_coherent_dma_mask(struct device *dev)
|
||||||
*/
|
*/
|
||||||
if (sizeof(mask) != sizeof(dma_addr_t) &&
|
if (sizeof(mask) != sizeof(dma_addr_t) &&
|
||||||
mask > (dma_addr_t)~0 &&
|
mask > (dma_addr_t)~0 &&
|
||||||
dma_to_pfn(dev, ~0) > arm_dma_pfn_limit) {
|
dma_to_pfn(dev, ~0) > max_dma_pfn) {
|
||||||
dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
|
dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
|
||||||
mask);
|
mask);
|
||||||
dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n");
|
dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n");
|
||||||
|
@ -192,7 +197,7 @@ static u64 get_coherent_dma_mask(struct device *dev)
|
||||||
* fits within the allowable addresses which we can
|
* fits within the allowable addresses which we can
|
||||||
* allocate.
|
* allocate.
|
||||||
*/
|
*/
|
||||||
if (dma_to_pfn(dev, mask) < arm_dma_pfn_limit) {
|
if (dma_to_pfn(dev, mask) < max_dma_pfn) {
|
||||||
dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n",
|
dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n",
|
||||||
mask,
|
mask,
|
||||||
dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1,
|
dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1,
|
||||||
|
|
|
@ -146,7 +146,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||||
|
|
||||||
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
|
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
|
||||||
info.length = len;
|
info.length = len;
|
||||||
info.low_limit = PAGE_SIZE;
|
info.low_limit = FIRST_USER_ADDRESS;
|
||||||
info.high_limit = mm->mmap_base;
|
info.high_limit = mm->mmap_base;
|
||||||
info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
|
info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
|
||||||
info.align_offset = pgoff << PAGE_SHIFT;
|
info.align_offset = pgoff << PAGE_SHIFT;
|
||||||
|
|
|
@ -87,7 +87,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||||
init_pud = pud_offset(init_pgd, 0);
|
init_pud = pud_offset(init_pgd, 0);
|
||||||
init_pmd = pmd_offset(init_pud, 0);
|
init_pmd = pmd_offset(init_pud, 0);
|
||||||
init_pte = pte_offset_map(init_pmd, 0);
|
init_pte = pte_offset_map(init_pmd, 0);
|
||||||
set_pte_ext(new_pte, *init_pte, 0);
|
set_pte_ext(new_pte + 0, init_pte[0], 0);
|
||||||
|
set_pte_ext(new_pte + 1, init_pte[1], 0);
|
||||||
pte_unmap(init_pte);
|
pte_unmap(init_pte);
|
||||||
pte_unmap(new_pte);
|
pte_unmap(new_pte);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue