Skip to content

Commit

Permalink
Merge master.kernel.org:/home/rmk/linux-2.6-arm
Browse files Browse the repository at this point in the history
  • Loading branch information
Linus Torvalds committed Jun 28, 2005
2 parents adb2705 + 5027397 commit 7e568e6
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 4 deletions.
5 changes: 5 additions & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,11 @@ config NO_IDLE_HZ
Alternatively, if you want dynamic tick automatically enabled
during boot, pass "dyntick=enable" via the kernel command string.

Please note that dynamic tick may affect the accuracy of
timekeeping on some platforms depending on the implementation.
Currently at least OMAP platform is known to have accurate
timekeeping with dynamic tick.

config ARCH_DISCONTIGMEM_ENABLE
bool
default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
Expand Down
7 changes: 4 additions & 3 deletions arch/arm/mach-s3c2410/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@
* 04-Nov-2004 Ben Dooks
* Fix standard IRQ wake for EINT0..4 and RTC
*
* 22-Feb-2004 Ben Dooks
* 22-Feb-2005 Ben Dooks
* Fixed edge-triggering on ADC IRQ
*
* 28-Jun-2005 Ben Dooks
* Mark IRQ_LCD valid
*/

#include <linux/init.h>
Expand Down Expand Up @@ -366,7 +369,6 @@ static struct irqchip s3c_irq_eint0t4 = {
#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0))
#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))

static inline void
s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
Expand Down Expand Up @@ -716,7 +718,6 @@ void __init s3c24xx_init_irq(void)
case IRQ_UART0:
case IRQ_UART1:
case IRQ_UART2:
case IRQ_LCD:
case IRQ_ADCPARENT:
set_irq_chip(irqno, &s3c_irq_level_chip);
set_irq_handler(irqno, do_level_IRQ);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/oprofile/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
oprofilefs.o oprofile_stats.o \
timer_int.o )

oprofile-y := $(DRIVER_OBJS) init.o
oprofile-y := $(DRIVER_OBJS) init.o backtrace.o
oprofile-$(CONFIG_CPU_XSCALE) += common.o op_model_xscale.o

144 changes: 144 additions & 0 deletions arch/arm/oprofile/backtrace.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Arm specific backtracing code for oprofile
*
* Copyright 2005 Openedhand Ltd.
*
* Author: Richard Purdie <[email protected]>
*
* Based on i386 oprofile backtrace code by John Levon, David Smith
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/

#include <linux/oprofile.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/ptrace.h>
#include <asm/uaccess.h>


/*
* The registers we're interested in are at the end of the variable
* length saved register structure. The fp points at the end of this
* structure so the address of this struct is:
* (struct frame_tail *)(xxx->fp)-1
*/
struct frame_tail {
struct frame_tail *fp;
unsigned long sp;
unsigned long lr;
} __attribute__((packed));


#ifdef CONFIG_FRAME_POINTER
static struct frame_tail* kernel_backtrace(struct frame_tail *tail)
{
oprofile_add_trace(tail->lr);

/* frame pointers should strictly progress back up the stack
* (towards higher addresses) */
if (tail >= tail->fp)
return NULL;

return tail->fp-1;
}
#endif

static struct frame_tail* user_backtrace(struct frame_tail *tail)
{
struct frame_tail buftail;

/* hardware pte might not be valid due to dirty/accessed bit emulation
* so we use copy_from_user and benefit from exception fixups */
if (copy_from_user(&buftail, tail, sizeof(struct frame_tail)))
return NULL;

oprofile_add_trace(buftail.lr);

/* frame pointers should strictly progress back up the stack
* (towards higher addresses) */
if (tail >= buftail.fp)
return NULL;

return buftail.fp-1;
}

/* Compare two addresses and see if they're on the same page */
#define CMP_ADDR_EQUAL(x,y,offset) ((((unsigned long) x) >> PAGE_SHIFT) \
== ((((unsigned long) y) + offset) >> PAGE_SHIFT))

/* check that the page(s) containing the frame tail are present */
static int pages_present(struct frame_tail *tail)
{
struct mm_struct * mm = current->mm;

if (!check_user_page_readable(mm, (unsigned long)tail))
return 0;

if (CMP_ADDR_EQUAL(tail, tail, 8))
return 1;

if (!check_user_page_readable(mm, ((unsigned long)tail) + 8))
return 0;

return 1;
}

/*
* | | /\ Higher addresses
* | |
* --------------- stack base (address of current_thread_info)
* | thread info |
* . .
* | stack |
* --------------- saved regs->ARM_fp value if valid (frame_tail address)
* . .
* --------------- struct pt_regs stored on stack (struct pt_regs *)
* | |
* . .
* | |
* --------------- %esp
* | |
* | | \/ Lower addresses
*
* Thus, &pt_regs <-> stack base restricts the valid(ish) fp values
*/
static int valid_kernel_stack(struct frame_tail *tail, struct pt_regs *regs)
{
unsigned long tailaddr = (unsigned long)tail;
unsigned long stack = (unsigned long)regs;
unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE;

return (tailaddr > stack) && (tailaddr < stack_base);
}

void arm_backtrace(struct pt_regs const *regs, unsigned int depth)
{
struct frame_tail *tail;
unsigned long last_address = 0;

tail = ((struct frame_tail *) regs->ARM_fp) - 1;

if (!user_mode(regs)) {

#ifdef CONFIG_FRAME_POINTER
while (depth-- && tail && valid_kernel_stack(tail, regs)) {
tail = kernel_backtrace(tail);
}
#endif
return;
}

while (depth-- && tail && !((unsigned long) tail & 3)) {
if ((!CMP_ADDR_EQUAL(last_address, tail, 0)
|| !CMP_ADDR_EQUAL(last_address, tail, 8))
&& !pages_present(tail))
return;
last_address = (unsigned long) tail;
tail = user_backtrace(tail);
}
}

2 changes: 2 additions & 0 deletions arch/arm/oprofile/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
ret = pmu_init(ops, &op_xscale_spec);
#endif

ops->backtrace = arm_backtrace;

return ret;
}

Expand Down
2 changes: 2 additions & 0 deletions arch/arm/oprofile/op_arm_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ struct op_arm_model_spec {
extern struct op_arm_model_spec op_xscale_spec;
#endif

extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth);

extern int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec);
extern void pmu_exit(void);
#endif /* OP_ARM_MODEL_H */
49 changes: 49 additions & 0 deletions include/asm-arm/arch-s3c2410/audio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* linux/include/asm-arm/arch-s3c2410/audio.h
*
* (c) 2004-2005 Simtec Electronics
* http://www.simtec.co.uk/products/SWLINUX/
* Ben Dooks <[email protected]>
*
* S3C24XX - Audio platfrom_device info
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Changelog:
* 20-Nov-2004 BJD Created file
* 07-Mar-2005 BJD Added suspend/resume calls
*/

#ifndef __ASM_ARCH_AUDIO_H
#define __ASM_ARCH_AUDIO_H __FILE__

/* struct s3c24xx_iis_ops
*
* called from the s3c24xx audio core to deal with the architecture
* or the codec's setup and control.
*
* the pointer to itself is passed through in case the caller wants to
* embed this in an larger structure for easy reference to it's context.
*/

struct s3c24xx_iis_ops {
struct module *owner;

int (*startup)(struct s3c24xx_iis_ops *me);
void (*shutdown)(struct s3c24xx_iis_ops *me);
int (*suspend)(struct s3c24xx_iis_ops *me);
int (*resume)(struct s3c24xx_iis_ops *me);

int (*open)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm);
int (*close)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm);
int (*prepare)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm, snd_pcm_runtime_t *rt);
};

struct s3c24xx_platdata_iis {
const char *codec_clk;
struct s3c24xx_iis_ops *ops;
int (*match_dev)(struct device *dev);
};

#endif /* __ASM_ARCH_AUDIO_H */

0 comments on commit 7e568e6

Please sign in to comment.