Commit 2e1e9212 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (29 commits)
  sh: enable maple_keyb in dreamcast_defconfig.
  SH2(A) cache update
  nommu: Provide vmalloc_exec().
  add addrespace definition for sh2a.
  sh: Kill off ARCH_SUPPORTS_AOUT and remnants of a.out support.
  sh: define GENERIC_HARDIRQS_NO__DO_IRQ.
  sh: define GENERIC_LOCKBREAK.
  sh: Save NUMA node data in vmcore for crash dumps.
  sh: module_alloc() should be using vmalloc_exec().
  sh: Fix up __bug_table handling in module loader.
  sh: Add documentation and integrate into docbook build.
  sh: Fix up broken kerneldoc comments.
  maple: Kill useless private_data pointer.
  maple: Clean up maple_driver_register/unregister routines.
  input: Clean up maple keyboard driver
  maple: allow removal and reinsertion of keyboard driver module
  sh: /proc/asids depends on MMU.
  arch/sh/boards/mach-se/7343/irq.c: removed duplicated #include
  arch/sh/boards/board-ap325rxa.c: removed duplicated #include
  sh/boards/Makefile typo fix
  ...
parents 2acb802b f5663f5b
...@@ -12,7 +12,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ ...@@ -12,7 +12,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
mac80211.xml debugobjects.xml mac80211.xml debugobjects.xml sh.xml
### ###
# The build process is as follows (targets): # The build process is as follows (targets):
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="sh-drivers">
<bookinfo>
<title>SuperH Interfaces Guide</title>
<authorgroup>
<author>
<firstname>Paul</firstname>
<surname>Mundt</surname>
<affiliation>
<address>
<email>lethal@linux-sh.org</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2008</year>
<holder>Paul Mundt</holder>
</copyright>
<copyright>
<year>2008</year>
<holder>Renesas Technology Corp.</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
</para>
<para>
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="mm">
<title>Memory Management</title>
<sect1 id="sh4">
<title>SH-4</title>
<sect2 id="sq">
<title>Store Queue API</title>
!Earch/sh/kernel/cpu/sh4/sq.c
</sect2>
</sect1>
<sect1 id="sh5">
<title>SH-5</title>
<sect2 id="tlb">
<title>TLB Interfaces</title>
!Iarch/sh/mm/tlb-sh5.c
!Iarch/sh/include/asm/tlb_64.h
</sect2>
</sect1>
</chapter>
<chapter id="clk">
<title>Clock Framework Extensions</title>
!Iarch/sh/include/asm/clock.h
</chapter>
<chapter id="mach">
<title>Machine Specific Interfaces</title>
<sect1 id="dreamcast">
<title>mach-dreamcast</title>
!Iarch/sh/boards/mach-dreamcast/rtc.c
</sect1>
<sect1 id="x3proto">
<title>mach-x3proto</title>
!Earch/sh/boards/mach-x3proto/ilsel.c
</sect1>
</chapter>
<chapter id="busses">
<title>Busses</title>
<sect1 id="superhyway">
<title>SuperHyway</title>
!Edrivers/sh/superhyway/superhyway.c
</sect1>
<sect1 id="maple">
<title>Maple</title>
!Edrivers/sh/maple/maple.c
</sect1>
</chapter>
</book>
...@@ -48,6 +48,9 @@ config GENERIC_HWEIGHT ...@@ -48,6 +48,9 @@ config GENERIC_HWEIGHT
config GENERIC_HARDIRQS config GENERIC_HARDIRQS
def_bool y def_bool y
config GENERIC_HARDIRQS_NO__DO_IRQ
def_bool y
config GENERIC_IRQ_PROBE config GENERIC_IRQ_PROBE
def_bool y def_bool y
...@@ -63,6 +66,10 @@ config GENERIC_TIME ...@@ -63,6 +66,10 @@ config GENERIC_TIME
config GENERIC_CLOCKEVENTS config GENERIC_CLOCKEVENTS
def_bool n def_bool n
config GENERIC_LOCKBREAK
def_bool y
depends on SMP && PREEMPT
config SYS_SUPPORTS_PM config SYS_SUPPORTS_PM
bool bool
...@@ -94,9 +101,6 @@ config ARCH_HAS_ILOG2_U64 ...@@ -94,9 +101,6 @@ config ARCH_HAS_ILOG2_U64
config ARCH_NO_VIRT_TO_BUS config ARCH_NO_VIRT_TO_BUS
def_bool y def_bool y
config ARCH_SUPPORTS_AOUT
def_bool y
config IO_TRAPPED config IO_TRAPPED
bool bool
...@@ -483,6 +487,23 @@ config CRASH_DUMP ...@@ -483,6 +487,23 @@ config CRASH_DUMP
For more details see Documentation/kdump/kdump.txt For more details see Documentation/kdump/kdump.txt
config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode"
depends on PROC_FS
default y
help
This kernel feature is useful for number crunching applications
that may need to compute untrusted bytecode during their
execution. By using pipes or other transports made available to
the process as file descriptors supporting the read/write
syscalls, it's possible to isolate those applications in
their own address space using seccomp. Once seccomp is
enabled via prctl, it cannot be disabled and the task is only
allowed to execute a few safe syscalls defined by each seccomp
mode.
If unsure, say N.
config SMP config SMP
bool "Symmetric multi-processing support" bool "Symmetric multi-processing support"
depends on SYS_SUPPORTS_SMP depends on SYS_SUPPORTS_SMP
......
...@@ -182,7 +182,7 @@ if SUPERH64 ...@@ -182,7 +182,7 @@ if SUPERH64
config SH64_PROC_ASIDS config SH64_PROC_ASIDS
bool "Debug: report ASIDs through /proc/asids" bool "Debug: report ASIDs through /proc/asids"
depends on PROC_FS depends on PROC_FS && MMU
config SH64_SR_WATCH config SH64_SR_WATCH
bool "Debug: set SR.WATCH to enable hardware watchpoints and trace" bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
......
...@@ -95,8 +95,6 @@ head-y := arch/sh/kernel/init_task.o ...@@ -95,8 +95,6 @@ head-y := arch/sh/kernel/init_task.o
head-$(CONFIG_SUPERH32) += arch/sh/kernel/head_32.o head-$(CONFIG_SUPERH32) += arch/sh/kernel/head_32.o
head-$(CONFIG_SUPERH64) += arch/sh/kernel/head_64.o head-$(CONFIG_SUPERH64) += arch/sh/kernel/head_64.o
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
core-y += arch/sh/kernel/ arch/sh/mm/ arch/sh/boards/ core-y += arch/sh/kernel/ arch/sh/mm/ arch/sh/boards/
core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/ core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/
...@@ -145,10 +143,6 @@ cpuincdir-$(CONFIG_CPU_SH4) += cpu-sh4 ...@@ -145,10 +143,6 @@ cpuincdir-$(CONFIG_CPU_SH4) += cpu-sh4
cpuincdir-$(CONFIG_CPU_SH5) += cpu-sh5 cpuincdir-$(CONFIG_CPU_SH5) += cpu-sh5
cpuincdir-y += cpu-common # Must be last cpuincdir-y += cpu-common # Must be last
libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y)
libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y)
libs-y += $(LIBGCC)
drivers-y += arch/sh/drivers/ drivers-y += arch/sh/drivers/
drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/ drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/
...@@ -161,10 +155,16 @@ KBUILD_CFLAGS += -pipe $(cflags-y) ...@@ -161,10 +155,16 @@ KBUILD_CFLAGS += -pipe $(cflags-y)
KBUILD_CPPFLAGS += $(cflags-y) KBUILD_CPPFLAGS += $(cflags-y)
KBUILD_AFLAGS += $(cflags-y) KBUILD_AFLAGS += $(cflags-y)
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y)
libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y)
libs-y += $(LIBGCC)
PHONY += maketools FORCE PHONY += maketools FORCE
maketools: include/linux/version.h FORCE maketools: include/linux/version.h FORCE
$(Q)$(MAKE) $(build)=arch/sh/tools arch/sh/include/asm/machtypes.h $(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
all: $(KBUILD_IMAGE) all: $(KBUILD_IMAGE)
...@@ -215,4 +215,4 @@ arch/sh/lib64/syscalltab.h: arch/sh/kernel/syscalls_64.S ...@@ -215,4 +215,4 @@ arch/sh/lib64/syscalltab.h: arch/sh/kernel/syscalls_64.S
$(call filechk,gen-syscalltab) $(call filechk,gen-syscalltab)
CLEAN_FILES += arch/sh/lib64/syscalltab.h \ CLEAN_FILES += arch/sh/lib64/syscalltab.h \
arch/sh/include/asm/machtypes.h include/asm-sh/machtypes.h
...@@ -5,4 +5,4 @@ obj-$(CONFIG_SH_AP325RXA) += board-ap325rxa.o ...@@ -5,4 +5,4 @@ obj-$(CONFIG_SH_AP325RXA) += board-ap325rxa.o
obj-$(CONFIG_SH_MAGIC_PANEL_R2) += board-magicpanelr2.o obj-$(CONFIG_SH_MAGIC_PANEL_R2) += board-magicpanelr2.o
obj-$(CONFIG_SH_RSK7203) += board-rsk7203.o obj-$(CONFIG_SH_RSK7203) += board-rsk7203.o
obj-$(CONFIG_SH_SH7785LCR) += board-sh7785lcr.o obj-$(CONFIG_SH_SH7785LCR) += board-sh7785lcr.o
obj-$(CONFIG_SH_SHMIN) += board-shmin..o obj-$(CONFIG_SH_SHMIN) += board-shmin.o
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/smc911x.h> #include <linux/smc911x.h>
#include <media/soc_camera_platform.h> #include <media/soc_camera_platform.h>
#include <media/sh_mobile_ceu.h> #include <media/sh_mobile_ceu.h>
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h> #include <linux/io.h>
#include <mach-se/mach/se7343.h> #include <mach-se/mach/se7343.h>
......
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.26 # Linux kernel version: 2.6.27-rc1
# Wed Jul 30 01:34:24 2008 # Mon Aug 4 16:49:13 2008
# #
CONFIG_SUPERH=y CONFIG_SUPERH=y
CONFIG_SUPERH32=y CONFIG_SUPERH32=y
...@@ -11,6 +11,7 @@ CONFIG_GENERIC_BUG=y ...@@ -11,6 +11,7 @@ CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y CONFIG_GENERIC_TIME=y
...@@ -21,7 +22,6 @@ CONFIG_LOCKDEP_SUPPORT=y ...@@ -21,7 +22,6 @@ CONFIG_LOCKDEP_SUPPORT=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
# #
...@@ -87,6 +87,7 @@ CONFIG_HAVE_OPROFILE=y ...@@ -87,6 +87,7 @@ CONFIG_HAVE_OPROFILE=y
# CONFIG_USE_GENERIC_SMP_HELPERS is not set # CONFIG_USE_GENERIC_SMP_HELPERS is not set
CONFIG_HAVE_CLK=y CONFIG_HAVE_CLK=y
CONFIG_PROC_PAGE_MONITOR=y CONFIG_PROC_PAGE_MONITOR=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set # CONFIG_TINY_SHMEM is not set
...@@ -284,6 +285,7 @@ CONFIG_HZ=250 ...@@ -284,6 +285,7 @@ CONFIG_HZ=250
# CONFIG_SCHED_HRTICK is not set # CONFIG_SCHED_HRTICK is not set
# CONFIG_KEXEC is not set # CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set # CONFIG_CRASH_DUMP is not set
CONFIG_SECCOMP=y
# CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y CONFIG_PREEMPT=y
...@@ -317,10 +319,6 @@ CONFIG_PCI_LEGACY=y ...@@ -317,10 +319,6 @@ CONFIG_PCI_LEGACY=y
# #
CONFIG_BINFMT_ELF=y CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set # CONFIG_BINFMT_MISC is not set
#
# Networking
#
CONFIG_NET=y CONFIG_NET=y
# #
...@@ -555,7 +553,7 @@ CONFIG_INPUT_KEYBOARD=y ...@@ -555,7 +553,7 @@ CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set # CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_MAPLE is not set CONFIG_KEYBOARD_MAPLE=y
# CONFIG_KEYBOARD_SH_KEYSC is not set # CONFIG_KEYBOARD_SH_KEYSC is not set
CONFIG_INPUT_MOUSE=y CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not set # CONFIG_MOUSE_PS2 is not set
......
#ifndef __ASM_SH_A_OUT_H
#define __ASM_SH_A_OUT_H
struct exec
{
unsigned long a_info; /* Use macros N_MAGIC, etc for access */
unsigned a_text; /* length of text, in bytes */
unsigned a_data; /* length of data, in bytes */
unsigned a_bss; /* length of uninitialized data area for file, in bytes */
unsigned a_syms; /* length of symbol table data in file, in bytes */
unsigned a_entry; /* start address */
unsigned a_trsize; /* length of relocation info for text, in bytes */
unsigned a_drsize; /* length of relocation info for data, in bytes */
};
#define N_TRSIZE(a) ((a).a_trsize)
#define N_DRSIZE(a) ((a).a_drsize)
#define N_SYMSIZE(a) ((a).a_syms)
#endif /* __ASM_SH_A_OUT_H */
...@@ -104,6 +104,15 @@ struct pt_dspregs { ...@@ -104,6 +104,15 @@ struct pt_dspregs {
extern void show_regs(struct pt_regs *); extern void show_regs(struct pt_regs *);
/*
* These are defined as per linux/ptrace.h.
*/
struct task_struct;
#define arch_has_single_step() (1)
extern void user_enable_single_step(struct task_struct *);
extern void user_disable_single_step(struct task_struct *);
#ifdef CONFIG_SH_DSP #ifdef CONFIG_SH_DSP
#define task_pt_regs(task) \ #define task_pt_regs(task) \
((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \ ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
......
#ifndef __ASM_SECCOMP_H
#include <linux/unistd.h>
#define __NR_seccomp_read __NR_read
#define __NR_seccomp_write __NR_write
#define __NR_seccomp_exit __NR_exit
#define __NR_seccomp_sigreturn __NR_rt_sigreturn
#endif /* __ASM_SECCOMP_H */
...@@ -117,24 +117,45 @@ static inline struct thread_info *current_thread_info(void) ...@@ -117,24 +117,45 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ #define TIF_NEED_RESCHED 2 /* rescheduling necessary */
#define TIF_RESTORE_SIGMASK 3 /* restore signal mask in do_signal() */ #define TIF_RESTORE_SIGMASK 3 /* restore signal mask in do_signal() */
#define TIF_SINGLESTEP 4 /* singlestepping active */ #define TIF_SINGLESTEP 4 /* singlestepping active */
#define TIF_SYSCALL_AUDIT 5 #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
#define TIF_SECCOMP 6 /* secure computing */
#define TIF_NOTIFY_RESUME 7 /* callback before returning to user */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 18 #define TIF_MEMDIE 18
#define TIF_FREEZE 19 #define TIF_FREEZE 19 /* Freezing for suspend */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_USEDFPU (1<<TIF_USEDFPU) #define _TIF_SECCOMP (1 << TIF_SECCOMP)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_FREEZE (1<<TIF_FREEZE) #define _TIF_USEDFPU (1 << TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_WORK_MASK 0x000000FE /* work to do on interrupt/exception return */ #define _TIF_FREEZE (1 << TIF_FREEZE)
#define _TIF_ALLWORK_MASK 0x000000FF /* work to do on any return to u-space */
/*
* _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within a byte, or we
* blow the tst immediate size constraints and need to fix up
* arch/sh/kernel/entry-common.S.
*/
/* work to do in syscall trace */
#define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
_TIF_SYSCALL_AUDIT | _TIF_SECCOMP)
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \
_TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \
_TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \
_TIF_NOTIFY_RESUME)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
_TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP))
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -21,11 +21,9 @@ ...@@ -21,11 +21,9 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
/** /**
* for_each_dtlb_entry * for_each_dtlb_entry - Iterate over free (non-wired) DTLB entries
* *
* @tlb: TLB entry * @tlb: TLB entry
*
* Iterate over free (non-wired) DTLB entries
*/ */
#define for_each_dtlb_entry(tlb) \ #define for_each_dtlb_entry(tlb) \
for (tlb = cpu_data->dtlb.first; \ for (tlb = cpu_data->dtlb.first; \
...@@ -33,11 +31,9 @@ ...@@ -33,11 +31,9 @@
tlb += cpu_data->dtlb.step) tlb += cpu_data->dtlb.step)
/** /**
* for_each_itlb_entry * for_each_itlb_entry - Iterate over free (non-wired) ITLB entries
* *
* @tlb: TLB entry * @tlb: TLB entry
*
* Iterate over free (non-wired) ITLB entries
*/ */
#define for_each_itlb_entry(tlb) \ #define for_each_itlb_entry(tlb) \
for (tlb = cpu_data->itlb.first; \ for (tlb = cpu_data->itlb.first; \
...@@ -45,11 +41,9 @@ ...@@ -45,11 +41,9 @@
tlb += cpu_data->itlb.step) tlb += cpu_data->itlb.step)
/** /**
* __flush_tlb_slot * __flush_tlb_slot - Flushes TLB slot @slot.
* *
* @slot: Address of TLB slot. * @slot: Address of TLB slot.
*
* Flushes TLB slot @slot.
*/ */
static inline void __flush_tlb_slot(unsigned long long slot) static inline void __flush_tlb_slot(unsigned long long slot)
{ {
......
...@@ -21,11 +21,11 @@ ...@@ -21,11 +21,11 @@
#define CCR 0xffffffec #define CCR 0xffffffec
#define CCR_CACHE_CE 0x01 /* Cache enable */ #define CCR_CACHE_CE 0x01 /* Cache enable */
#define CCR_CACHE_WT 0x06 /* CCR[bit1=1,bit2=1] */ #define CCR_CACHE_WT 0x02 /* CCR[bit1=1,bit2=1] */
/* 0x00000000-0x7fffffff: Write-through */ /* 0x00000000-0x7fffffff: Write-through */
/* 0x80000000-0x9fffffff: Write-back */ /* 0x80000000-0x9fffffff: Write-back */
/* 0xc0000000-0xdfffffff: Write-through */ /* 0xc0000000-0xdfffffff: Write-through */
#define CCR_CACHE_CB 0x00 /* CCR[bit1=0,bit2=0] */ #define CCR_CACHE_CB 0x04 /* CCR[bit1=0,bit2=0] */
/* 0x00000000-0x7fffffff: Write-back */ /* 0x00000000-0x7fffffff: Write-back */
/* 0x80000000-0x9fffffff: Write-through */ /* 0x80000000-0x9fffffff: Write-through */
/* 0xc0000000-0xdfffffff: Write-back */ /* 0xc0000000-0xdfffffff: Write-back */
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#define CCR_CACHE_ENABLE CCR_CACHE_CE #define CCR_CACHE_ENABLE CCR_CACHE_CE
#define CCR_CACHE_INVALIDATE CCR_CACHE_CF #define CCR_CACHE_INVALIDATE CCR_CACHE_CF
#define CACHE_PHYSADDR_MASK 0x1ffffc00
#endif #endif
#endif /* __ASM_CPU_SH2_CACHE_H */ #endif /* __ASM_CPU_SH2_CACHE_H */
#ifndef __ASM_SH_CPU_SH2A_ADDRSPACE_H
#define __ASM_SH_CPU_SH2A_ADDRSPACE_H
#define P0SEG 0x00000000
#define P1SEG 0x00000000
#define P2SEG 0x20000000
#define P3SEG 0x40000000
#define P4SEG 0x60000000
#endif /* __ASM_SH_CPU_SH2A_ADDRSPACE_H */
...@@ -36,5 +36,8 @@ ...@@ -36,5 +36,8 @@
#define CCR_CACHE_ENABLE (CCR_CACHE_OCE | CCR_CACHE_ICE) #define CCR_CACHE_ENABLE (CCR_CACHE_OCE | CCR_CACHE_ICE)
#define CCR_CACHE_INVALIDATE (CCR_CACHE_OCI | CCR_CACHE_ICI) #define CCR_CACHE_INVALIDATE (CCR_CACHE_OCI | CCR_CACHE_ICI)
#define CCR_ICACHE_INVALIDATE CCR_CACHE_ICI
#define CCR_OCACHE_INVALIDATE CCR_CACHE_OCI
#define CACHE_PHYSADDR_MASK 0x1ffffc00
#endif /* __ASM_CPU_SH2A_CACHE_H */ #endif /* __ASM_CPU_SH2A_CACHE_H */
#ifndef __ASM_CPU_SH2A_CACHEFLUSH_H
#define __ASM_CPU_SH2A_CACHEFLUSH_H
/*
* Cache flushing:
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
* - flush_cache_dup mm(mm) handles cache flushing when forking
* - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
*
* - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
* - flush_icache_range(start, end) flushes(invalidates) a range for icache
* - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
*
* Caches are indexed (effectively) by physical address on SH-2, so
* we don't need them.
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
void flush_icache_range(unsigned long start, unsigned long end);
#define flush_icache_page(vma,pg) do { } while (0)
#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
#define flush_cache_sigtramp(vaddr) do { } while (0)
#define p3_cache_init() do { } while (0)
#endif /* __ASM_CPU_SH2A_CACHEFLUSH_H */
...@@ -199,7 +199,7 @@ EXPORT_SYMBOL(sq_remap); ...@@ -199,7 +199,7 @@ EXPORT_SYMBOL(sq_remap);
/** /**
* sq_unmap - Unmap a Store Queue allocation * sq_unmap - Unmap a Store Queue allocation
* @map: Pre-allocated Store Queue mapping. * @vaddr: Pre-allocated Store Queue mapping.
* *
* Unmaps the store queue allocation @map that was previously created by * Unmaps the store queue allocation @map that was previously created by
* sq_remap(). Also frees up the pte that was previously inserted into * sq_remap(). Also frees up the pte that was previously inserted into
......
...@@ -987,11 +987,11 @@ work_resched: ...@@ -987,11 +987,11 @@ work_resched:
work_notifysig: work_notifysig:
gettr tr1, LINK gettr tr1, LINK
movi do_signal, r6 movi do_notify_resume, r6
ptabs r6, tr0 ptabs r6, tr0
or SP, ZERO, r2 or SP, ZERO, r2
or ZERO, ZERO, r3 or r7, ZERO, r3
blink tr0, LINK /* Call do_signal(regs, 0), return here */ blink tr0, LINK /* Call do_notify_resume(regs, current_thread_info->flags), return here */
restore_all: restore_all:
/* Do prefetches */ /* Do prefetches */
...@@ -1300,18 +1300,20 @@ syscall_allowed: ...@@ -1300,18 +1300,20 @@ syscall_allowed:
getcon KCR0, r2 getcon KCR0, r2
ld.l r2, TI_FLAGS, r4 ld.l r2, TI_FLAGS, r4
movi (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT), r6 movi _TIF_WORK_SYSCALL_MASK, r6
and r6, r4, r6 and r6, r4, r6
beq/l r6, ZERO, tr0 beq/l r6, ZERO, tr0
/* Trace it by calling syscall_trace before and after */ /* Trace it by calling syscall_trace before and after */
movi syscall_trace, r4 movi do_syscall_trace_enter, r4
or SP, ZERO, r2 or SP, ZERO, r2
or ZERO, ZERO, r3
ptabs r4, tr0 ptabs r4, tr0
blink tr0, LINK blink tr0, LINK
/* Reload syscall number as r5 is trashed by syscall_trace */ /* Save the retval */
st.q SP, FRAME_R(2), r2
/* Reload syscall number as r5 is trashed by do_syscall_trace_enter */
ld.q SP, FRAME_S(FSYSCALL_ID), r5 ld.q SP, FRAME_S(FSYSCALL_ID), r5
andi r5, 0x1ff, r5 andi r5, 0x1ff, r5
...@@ -1343,9 +1345,8 @@ syscall_ret_trace: ...@@ -1343,9 +1345,8 @@ syscall_ret_trace:
/* We get back here only if under trace */ /* We get back here only if under trace */
st.q SP, FRAME_R(9), r2 /* Save return value */ st.q SP, FRAME_R(9), r2 /* Save return value */
movi syscall_trace, LINK movi do_syscall_trace_leave, LINK
or SP, ZERO, r2 or SP, ZERO, r2
movi 1, r3
ptabs LINK, tr0 ptabs LINK, tr0
blink tr0, LINK blink tr0, LINK
......
...@@ -202,7 +202,7 @@ work_resched: ...@@ -202,7 +202,7 @@ work_resched:
syscall_exit_work: syscall_exit_work:
! r0: current_thread_info->flags ! r0: current_thread_info->flags
! r8: current_thread_info ! r8: current_thread_info
tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT, r0 tst #_TIF_WORK_SYSCALL_MASK, r0
bt/s work_pending bt/s work_pending
tst #_TIF_NEED_RESCHED, r0 tst #_TIF_NEED_RESCHED, r0
#ifdef CONFIG_TRACE_IRQFLAGS #ifdef CONFIG_TRACE_IRQFLAGS
...@@ -211,10 +211,8 @@ syscall_exit_work: ...@@ -211,10 +211,8 @@ syscall_exit_work:
nop nop
#endif #endif
sti sti
! XXX setup arguments...
mov r15, r4 mov r15, r4
mov #1, r5 mov.l 8f, r0 ! do_syscall_trace_leave
mov.l 4f, r0 ! do_syscall_trace
jsr @r0 jsr @r0
nop nop
bra resume_userspace bra resume_userspace
...@@ -223,12 +221,11 @@ syscall_exit_work: ...@@ -223,12 +221,11 @@ syscall_exit_work:
.align 2 .align 2
syscall_trace_entry: syscall_trace_entry:
! Yes it is traced. ! Yes it is traced.
! XXX setup arguments...
mov r15, r4 mov r15, r4
mov #0, r5 mov.l 7f, r11 ! Call do_syscall_trace_enter which notifies
mov.l 4f, r11 ! Call do_syscall_trace which notifies
jsr @r11 ! superior (will chomp R[0-7]) jsr @r11 ! superior (will chomp R[0-7])
nop nop
mov.l r0, @(OFF_R0,r15) ! Save return value
! Reload R0-R4 from kernel stack, where the ! Reload R0-R4 from kernel stack, where the
! parent may have modified them using ! parent may have modified them using
! ptrace(POKEUSR). (Note that R0-R2 are ! ptrace(POKEUSR). (Note that R0-R2 are
...@@ -351,7 +348,7 @@ ENTRY(system_call) ...@@ -351,7 +348,7 @@ ENTRY(system_call)
! !
get_current_thread_info r8, r10 get_current_thread_info r8, r10
mov.l @(TI_FLAGS,r8), r8 mov.l @(TI_FLAGS,r8), r8
mov #(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT), r10 mov #_TIF_WORK_SYSCALL_MASK, r10
tst r10, r8 tst r10, r8
bf syscall_trace_entry bf syscall_trace_entry
! !
...@@ -389,8 +386,9 @@ syscall_exit: ...@@ -389,8 +386,9 @@ syscall_exit:
#endif #endif
2: .long NR_syscalls 2: .long NR_syscalls
3: .long sys_call_table 3: .long sys_call_table
4: .long do_syscall_trace
#ifdef CONFIG_TRACE_IRQFLAGS #ifdef CONFIG_TRACE_IRQFLAGS
5: .long trace_hardirqs_on 5: .long trace_hardirqs_on
6: .long trace_hardirqs_off 6: .long trace_hardirqs_off
#endif #endif
7: .long do_syscall_trace_enter
8: .long do_syscall_trace_leave
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/numa.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
...@@ -104,3 +105,10 @@ void machine_kexec(struct kimage *image) ...@@ -104,3 +105,10 @@ void machine_kexec(struct kimage *image)
(*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg); (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg);
} }
void arch_crash_save_vmcoreinfo(void)
{
#ifdef CONFIG_NUMA
VMCOREINFO_SYMBOL(node_data);
VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
#endif
}
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/moduleloader.h> #include <linux/moduleloader.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/bug.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -36,7 +37,8 @@ void *module_alloc(unsigned long size) ...@@ -36,7 +37,8 @@ void *module_alloc(unsigned long size)
{ {
if (size == 0) if (size == 0)
return NULL; return NULL;
return vmalloc(size);
return vmalloc_exec(size);
} }
...@@ -145,9 +147,10 @@ int module_finalize(const Elf_Ehdr *hdr, ...@@ -145,9 +147,10 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs, const Elf_Shdr *sechdrs,
struct module *me) struct module *me)
{ {
return 0; return module_bug_finalize(hdr, sechdrs, me);
} }
void module_arch_cleanup(struct module *mod) void module_arch_cleanup(struct module *mod)
{ {
module_bug_cleanup(mod);
} }
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/tracehook.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -57,7 +59,23 @@ static inline int put_stack_long(struct task_struct *task, int offset, ...@@ -57,7 +59,23 @@ static inline int put_stack_long(struct task_struct *task, int offset,
return 0; return 0;
} }
static void ptrace_disable_singlestep(struct task_struct *child) void user_enable_single_step(struct task_struct *child)
{
struct pt_regs *regs = task_pt_regs(child);
long pc;
pc = get_stack_long(child, (long)&regs->pc);
/* Next scheduling will set up UBC */
if (child->thread.ubc_pc == 0)
ubc_usercnt += 1;
child->thread.ubc_pc = pc;
set_tsk_thread_flag(child, TIF_SINGLESTEP);
}
void user_disable_single_step(struct task_struct *child)
{ {
clear_tsk_thread_flag(child, TIF_SINGLESTEP); clear_tsk_thread_flag(child, TIF_SINGLESTEP);
...@@ -81,7 +99,7 @@ static void ptrace_disable_singlestep(struct task_struct *child) ...@@ -81,7 +99,7 @@ static void ptrace_disable_singlestep(struct task_struct *child)
*/ */
void ptrace_disable(struct task_struct *child) void ptrace_disable(struct task_struct *child)
{ {
ptrace_disable_singlestep(child); user_disable_single_step(child);
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request, long addr, long data)
...@@ -90,12 +108,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -90,12 +108,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
int ret; int ret;
switch (request) { switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:
ret = generic_ptrace_peekdata(child, addr, data);
break;
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: { case PTRACE_PEEKUSR: {
unsigned long tmp; unsigned long tmp;
...@@ -125,12 +137,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -125,12 +137,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
} }
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
ret = -EIO; ret = -EIO;
if ((addr & 3) || addr < 0 || if ((addr & 3) || addr < 0 ||
...@@ -151,67 +157,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -151,67 +157,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} }
break; break;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
ret = -EIO;
if (!valid_signal(data))
break;
if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
else
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
ptrace_disable_singlestep(child);
child->exit_code = data;
wake_up_process(child);
ret = 0;
break;
}
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
ret = 0;
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
ptrace_disable_singlestep(child);
child->exit_code = SIGKILL;
wake_up_process(child);
break;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
long pc;
struct pt_regs *regs = NULL;
ret = -EIO;
if (!valid_signal(data))
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
if ((child->ptrace & PT_DTRACE) == 0) {
/* Spurious delayed TF traps may occur */
child->ptrace |= PT_DTRACE;
}
pc = get_stack_long(child, (long)&regs->pc);
/* Next scheduling will set up UBC */
if (child->thread.ubc_pc == 0)
ubc_usercnt += 1;
child->thread.ubc_pc = pc;
set_tsk_thread_flag(child, TIF_SINGLESTEP);
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
ret = 0;
break;
}
#ifdef CONFIG_SH_DSP #ifdef CONFIG_SH_DSP
case PTRACE_GETDSPREGS: { case PTRACE_GETDSPREGS: {
unsigned long dp; unsigned long dp;
...@@ -272,39 +217,49 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -272,39 +217,49 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return ret; return ret;
} }
asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) static inline int audit_arch(void)
{ {
struct task_struct *tsk = current; int arch = EM_SH;
if (unlikely(current->audit_context) && entryexit) #ifdef CONFIG_CPU_LITTLE_ENDIAN
audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), arch |= __AUDIT_ARCH_LE;
regs->regs[0]); #endif
if (!test_thread_flag(TIF_SYSCALL_TRACE) && return arch;
!test_thread_flag(TIF_SINGLESTEP)) }
goto out;
if (!(tsk->ptrace & PT_PTRACED))
goto out;
/* the 0x80 provides a way for the tracing parent to distinguish asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
between a syscall stop and SIGTRAP delivery */ {
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && long ret = 0;
!test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
/* secure_computing(regs->regs[0]);
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the if (test_thread_flag(TIF_SYSCALL_TRACE) &&
* stopping signal is not SIGTRAP. -brl tracehook_report_syscall_entry(regs))
*/ /*
if (tsk->exit_code) { * Tracing decided this syscall should not happen.
send_sig(tsk->exit_code, tsk, 1); * We'll return a bogus call number to get an ENOSYS
tsk->exit_code = 0; * error, but leave the original number in regs->regs[0].
} */
ret = -1L;
out: if (unlikely(current->audit_context))
if (unlikely(current->audit_context) && !entryexit) audit_syscall_entry(audit_arch(), regs->regs[3],
audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[3],
regs->regs[4], regs->regs[5], regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]); regs->regs[6], regs->regs[7]);
return ret ?: regs->regs[0];
}
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
{
int step;
if (unlikely(current->audit_context))
audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
regs->regs[0]);
step = test_thread_flag(TIF_SINGLESTEP);
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall_exit(regs, step);
} }
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/tracehook.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
...@@ -120,18 +122,23 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) ...@@ -120,18 +122,23 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data)
return 0; return 0;
} }
void user_enable_single_step(struct task_struct *child)
{
struct pt_regs *regs = child->thread.uregs;
regs->sr |= SR_SSTEP; /* auto-resetting upon exception */
}
void user_disable_single_step(struct task_struct *child)
{
regs->sr &= ~SR_SSTEP;
}
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{ {
int ret; int ret;
switch (request) { switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:
ret = generic_ptrace_peekdata(child, addr, data);
break;
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: { case PTRACE_PEEKUSR: {
unsigned long tmp; unsigned long tmp;
...@@ -154,12 +161,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -154,12 +161,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
} }
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: case PTRACE_POKEUSR:
/* write the word at location addr in the USER area. We must /* write the word at location addr in the USER area. We must
disallow any changes to certain SR bits or u_fpvalid, since disallow any changes to certain SR bits or u_fpvalid, since
...@@ -191,58 +192,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -191,58 +192,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} }
break; break;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
ret = -EIO;
if (!valid_signal(data))
break;
if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
else
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
wake_up_process(child);
ret = 0;
break;
}
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
ret = 0;
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
child->exit_code = SIGKILL;
wake_up_process(child);
break;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
struct pt_regs *regs;
ret = -EIO;
if (!valid_signal(data))
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
if ((child->ptrace & PT_DTRACE) == 0) {
/* Spurious delayed TF traps may occur */
child->ptrace |= PT_DTRACE;
}
regs = child->thread.uregs;
regs->sr |= SR_SSTEP; /* auto-resetting upon exception */
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
ret = 0;
break;
}
default: default:
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
break; break;
...@@ -273,38 +222,51 @@ asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) ...@@ -273,38 +222,51 @@ asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
return sys_ptrace(request, pid, addr, data); return sys_ptrace(request, pid, addr, data);
} }
asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) static inline int audit_arch(void)
{ {
struct task_struct *tsk = current; int arch = EM_SH;
if (unlikely(current->audit_context) && entryexit) #ifdef CONFIG_64BIT
audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), arch |= __AUDIT_ARCH_64BIT;
regs->regs[9]); #endif
#ifdef CONFIG_CPU_LITTLE_ENDIAN
arch |= __AUDIT_ARCH_LE;
#endif
if (!test_thread_flag(TIF_SYSCALL_TRACE) && return arch;
!test_thread_flag(TIF_SINGLESTEP)) }
goto out;
if (!(tsk->ptrace & PT_PTRACED))
goto out;
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
!test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
if (tsk->exit_code) {
send_sig(tsk->exit_code, tsk, 1);
tsk->exit_code = 0;
}
out: asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs)
if (unlikely(current->audit_context) && !entryexit) {
audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[1], long long ret = 0;
secure_computing(regs->regs[9]);
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs))
/*
* Tracing decided this syscall should not happen.
* We'll return a bogus call number to get an ENOSYS
* error, but leave the original number in regs->regs[0].
*/
ret = -1LL;
if (unlikely(current->audit_context))
audit_syscall_entry(audit_arch(), regs->regs[1],
regs->regs[2], regs->regs[3], regs->regs[2], regs->regs[3],
regs->regs[4], regs->regs[5]); regs->regs[4], regs->regs[5]);
return ret ?: regs->regs[9];
}
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
{
if (unlikely(current->audit_context))
audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]),
regs->regs[9]);
if (test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall_exit(regs, 0);
} }
/* Called with interrupts disabled */ /* Called with interrupts disabled */
...@@ -338,5 +300,5 @@ asmlinkage void do_software_break_point(unsigned long long vec, ...@@ -338,5 +300,5 @@ asmlinkage void do_software_break_point(unsigned long long vec,
*/ */
void ptrace_disable(struct task_struct *child) void ptrace_disable(struct task_struct *child)
{ {
/* nothing to do.. */ user_disable_single_step(child);
} }
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/crash_dump.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -286,6 +287,25 @@ static void __init setup_memory(void) ...@@ -286,6 +287,25 @@ static void __init setup_memory(void)
extern void __init setup_memory(void); extern void __init setup_memory(void);
#endif #endif
/*
* Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
* is_kdump_kernel() to determine if we are booting after a panic. Hence
* ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
*/
#ifdef CONFIG_CRASH_DUMP
/* elfcorehdr= specifies the location of elf core header
* stored by the crashed kernel.
*/
static int __init parse_elfcorehdr(char *arg)
{
if (!arg)
return -EINVAL;
elfcorehdr_addr = memparse(arg, &arg);
return 0;
}
early_param("elfcorehdr", parse_elfcorehdr);
#endif
void __init setup_arch(char **cmdline_p) void __init setup_arch(char **cmdline_p)
{ {
enable_mmu(); enable_mmu();
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/binfmts.h> #include <linux/binfmts.h>
#include <linux/freezer.h> #include <linux/freezer.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/tracehook.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -507,14 +508,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -507,14 +508,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
switch (regs->regs[0]) { switch (regs->regs[0]) {
case -ERESTART_RESTARTBLOCK: case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND: case -ERESTARTNOHAND:
no_system_call_restart:
regs->regs[0] = -EINTR; regs->regs[0] = -EINTR;
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ka->sa.sa_flags & SA_RESTART))
regs->regs[0] = -EINTR; goto no_system_call_restart;
break;
}
/* fallthrough */ /* fallthrough */
case -ERESTARTNOINTR: case -ERESTARTNOINTR:
regs->regs[0] = save_r0; regs->regs[0] = save_r0;
...@@ -589,12 +589,15 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) ...@@ -589,12 +589,15 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
* clear the TIF_RESTORE_SIGMASK flag */ * clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK); clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
return; return;
} }
no_signal: no_signal:
/* Did we come from a system call? */ /* Did we come from a system call? */
if (regs->tra >= 0) { if (regs->tra >= 0) {
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
...@@ -618,9 +621,14 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) ...@@ -618,9 +621,14 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
} }
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
__u32 thread_info_flags) unsigned long thread_info_flags)
{ {
/* deal with pending signal delivery */ /* deal with pending signal delivery */
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs, save_r0); do_signal(regs, save_r0);
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
}
} }
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/tracehook.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
...@@ -42,7 +43,84 @@ ...@@ -42,7 +43,84 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); /*
* Note that 'init' is a special process: it doesn't get signals it doesn't
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*
* Note that we go through the signals twice: once to check the signals that
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
static int do_signal(struct pt_regs *regs, sigset_t *oldset)
{
siginfo_t info;
int signr;
struct k_sigaction ka;
/*
* We want the common case to go fast, which
* is why we may in certain cases get here from
* kernel mode. Just return without doing anything
* if so.
*/
if (!user_mode(regs))
return 1;
if (try_to_freeze())
goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, 0);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
handle_signal(signr, &info, &ka, oldset, regs);
/*
* If a signal was successfully delivered, the saved sigmask
* is in its frame, and we can clear the TIF_RESTORE_SIGMASK
* flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs, 0);
return 1;
}
no_signal:
/* Did we come from a system call? */
if (regs->syscall_nr >= 0) {
/* Restart the system call - no handlers present */
switch (regs->regs[REG_RET]) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
/* Decode Syscall # */
regs->regs[REG_RET] = regs->syscall_nr;
regs->pc -= 4;
break;
case -ERESTART_RESTARTBLOCK:
regs->regs[REG_RET] = __NR_restart_syscall;
regs->pc -= 4;
break;
}
}
/* No signal to deliver -- put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return 0;
}
/* /*
* Atomically swap in the new signal mask, and wait for a signal. * Atomically swap in the new signal mask, and wait for a signal.
...@@ -643,14 +721,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -643,14 +721,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
switch (regs->regs[REG_RET]) { switch (regs->regs[REG_RET]) {
case -ERESTART_RESTARTBLOCK: case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND: case -ERESTARTNOHAND:
no_system_call_restart:
regs->regs[REG_RET] = -EINTR; regs->regs[REG_RET] = -EINTR;
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ka->sa.sa_flags & SA_RESTART))
regs->regs[REG_RET] = -EINTR; goto no_system_call_restart;
break;
}
/* fallthrough */ /* fallthrough */
case -ERESTARTNOINTR: case -ERESTARTNOINTR:
/* Decode syscall # */ /* Decode syscall # */
...@@ -673,80 +750,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -673,80 +750,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
} }
/* asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
* Note that 'init' is a special process: it doesn't get signals it doesn't
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*
* Note that we go through the signals twice: once to check the signals that
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
int do_signal(struct pt_regs *regs, sigset_t *oldset)
{ {
siginfo_t info; if (thread_info_flags & _TIF_SIGPENDING)
int signr; do_signal(regs, 0);
struct k_sigaction ka;
/*
* We want the common case to go fast, which
* is why we may in certain cases get here from
* kernel mode. Just return without doing anything
* if so.
*/
if (!user_mode(regs))
return 1;
if (try_to_freeze())
goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, 0);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
handle_signal(signr, &info, &ka, oldset, regs);
/* if (thread_info_flags & _TIF_NOTIFY_RESUME) {
* If a signal was successfully delivered, the saved sigmask clear_thread_flag(TIF_NOTIFY_RESUME);
* is in its frame, and we can clear the TIF_RESTORE_SIGMASK tracehook_notify_resume(regs);
* flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
return 1;
} }
no_signal:
/* Did we come from a system call? */
if (regs->syscall_nr >= 0) {
/* Restart the system call - no handlers present */
switch (regs->regs[REG_RET]) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
/* Decode Syscall # */
regs->regs[REG_RET] = regs->syscall_nr;
regs->pc -= 4;
break;
case -ERESTART_RESTARTBLOCK:
regs->regs[REG_RET] = __NR_restart_syscall;
regs->pc -= 4;
break;
}
}
/* No signal to deliver -- put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return 0;
} }
...@@ -237,7 +237,6 @@ choice ...@@ -237,7 +237,6 @@ choice
config CACHE_WRITEBACK config CACHE_WRITEBACK
bool "Write-back" bool "Write-back"
depends on CPU_SH2A || CPU_SH3 || CPU_SH4 || CPU_SH5
config CACHE_WRITETHROUGH config CACHE_WRITETHROUGH
bool "Write-through" bool "Write-through"
......
...@@ -5,12 +5,15 @@ ...@@ -5,12 +5,15 @@
obj-y := init.o extable_32.o consistent.o obj-y := init.o extable_32.o consistent.o
ifndef CONFIG_CACHE_OFF ifndef CONFIG_CACHE_OFF
obj-$(CONFIG_CPU_SH2) += cache-sh2.o cache-$(CONFIG_CPU_SH2) := cache-sh2.o
obj-$(CONFIG_CPU_SH3) += cache-sh3.o cache-$(CONFIG_CPU_SH2A) := cache-sh2a.o
obj-$(CONFIG_CPU_SH4) += cache-sh4.o cache-$(CONFIG_CPU_SH3) := cache-sh3.o
obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o cache-$(CONFIG_CPU_SH4) := cache-sh4.o
cache-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
endif endif
obj-y += $(cache-y)
mmu-y := tlb-nommu.o pg-nommu.o mmu-y := tlb-nommu.o pg-nommu.o
mmu-$(CONFIG_MMU) := fault_32.o tlbflush_32.o ioremap_32.o mmu-$(CONFIG_MMU) := fault_32.o tlbflush_32.o ioremap_32.o
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* arch/sh/mm/cache-sh2.c * arch/sh/mm/cache-sh2.c
* *
* Copyright (C) 2002 Paul Mundt * Copyright (C) 2002 Paul Mundt
* Copyright (C) 2008 Yoshinori Sato
* *
* Released under the terms of the GNU GPL v2.0. * Released under the terms of the GNU GPL v2.0.
*/ */
...@@ -24,8 +25,15 @@ void __flush_wback_region(void *start, int size) ...@@ -24,8 +25,15 @@ void __flush_wback_region(void *start, int size)
end = ((unsigned long)start + size + L1_CACHE_BYTES-1) end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1); & ~(L1_CACHE_BYTES-1);
for (v = begin; v < end; v+=L1_CACHE_BYTES) { for (v = begin; v < end; v+=L1_CACHE_BYTES) {
/* FIXME cache purge */ unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0);
ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); int way;
for (way = 0; way < 4; way++) {
unsigned long data = ctrl_inl(addr | (way << 12));
if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
data &= ~SH_CACHE_UPDATED;
ctrl_outl(data, addr | (way << 12));
}
}
} }
} }
...@@ -37,21 +45,40 @@ void __flush_purge_region(void *start, int size) ...@@ -37,21 +45,40 @@ void __flush_purge_region(void *start, int size)
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1) end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1); & ~(L1_CACHE_BYTES-1);
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); for (v = begin; v < end; v+=L1_CACHE_BYTES)
} ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
} }
void __flush_invalidate_region(void *start, int size) void __flush_invalidate_region(void *start, int size)
{ {
#ifdef CONFIG_CACHE_WRITEBACK
/*
* SH-2 does not support individual line invalidation, only a
* global invalidate.
*/
unsigned long ccr;
unsigned long flags;
local_irq_save(flags);
jump_to_uncached();
ccr = ctrl_inl(CCR);
ccr |= CCR_CACHE_INVALIDATE;
ctrl_outl(ccr, CCR);
back_to_cached();
local_irq_restore(flags);
#else
unsigned long v; unsigned long v;
unsigned long begin, end; unsigned long begin, end;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1) end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1); & ~(L1_CACHE_BYTES-1);
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
}
}
for (v = begin; v < end; v+=L1_CACHE_BYTES)
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
#endif
}
/*
* arch/sh/mm/cache-sh2a.c
*
* Copyright (C) 2008 Yoshinori Sato
*
* Released under the terms of the GNU GPL v2.0.
*/
#include <linux/init.h>
#include <linux/mm.h>
#include <asm/cache.h>
#include <asm/addrspace.h>
#include <asm/processor.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
void __flush_wback_region(void *start, int size)
{
unsigned long v;
unsigned long begin, end;
unsigned long flags;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
local_irq_save(flags);
jump_to_uncached();
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0);
int way;
for (way = 0; way < 4; way++) {
unsigned long data = ctrl_inl(addr | (way << 11));
if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
data &= ~SH_CACHE_UPDATED;
ctrl_outl(data, addr | (way << 11));
}
}
}
back_to_cached();
local_irq_restore(flags);
}
void __flush_purge_region(void *start, int size)
{
unsigned long v;
unsigned long begin, end;
unsigned long flags;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
local_irq_save(flags);
jump_to_uncached();
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_OC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);
}
back_to_cached();
local_irq_restore(flags);
}
void __flush_invalidate_region(void *start, int size)
{
unsigned long v;
unsigned long begin, end;
unsigned long flags;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
local_irq_save(flags);
jump_to_uncached();
#ifdef CONFIG_CACHE_WRITEBACK
ctrl_outl(ctrl_inl(CCR) | CCR_OCACHE_INVALIDATE, CCR);
/* I-cache invalidate */
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_IC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);
}
#else
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_IC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_OC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);
}
#endif
back_to_cached();
local_irq_restore(flags);
}
/* WBack O-Cache and flush I-Cache */
void flush_icache_range(unsigned long start, unsigned long end)
{
unsigned long v;
unsigned long flags;
start = start & ~(L1_CACHE_BYTES-1);
end = (end + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1);
local_irq_save(flags);
jump_to_uncached();
for (v = start; v < end; v+=L1_CACHE_BYTES) {
unsigned long addr = (v & 0x000007f0);
int way;
/* O-Cache writeback */
for (way = 0; way < 4; way++) {
unsigned long data = ctrl_inl(CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
data &= ~SH_CACHE_UPDATED;
ctrl_outl(data, CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
}
}
/* I-Cache invalidate */
ctrl_outl(addr,
CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);
}
back_to_cached();
local_irq_restore(flags);
}
...@@ -15,9 +15,7 @@ ...@@ -15,9 +15,7 @@
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
/** /**
* sh64_tlb_init * sh64_tlb_init - Perform initial setup for the DTLB and ITLB.
*
* Perform initial setup for the DTLB and ITLB.
*/ */
int __init sh64_tlb_init(void) int __init sh64_tlb_init(void)
{ {
...@@ -46,9 +44,7 @@ int __init sh64_tlb_init(void) ...@@ -46,9 +44,7 @@ int __init sh64_tlb_init(void)
} }
/** /**
* sh64_next_free_dtlb_entry * sh64_next_free_dtlb_entry - Find the next available DTLB entry
*
* Find the next available DTLB entry
*/ */
unsigned long long sh64_next_free_dtlb_entry(void) unsigned long long sh64_next_free_dtlb_entry(void)
{ {
...@@ -56,9 +52,7 @@ unsigned long long sh64_next_free_dtlb_entry(void) ...@@ -56,9 +52,7 @@ unsigned long long sh64_next_free_dtlb_entry(void)
} }
/** /**
* sh64_get_wired_dtlb_entry * sh64_get_wired_dtlb_entry - Allocate a wired (locked-in) entry in the DTLB
*
* Allocate a wired (locked-in) entry in the DTLB
*/ */
unsigned long long sh64_get_wired_dtlb_entry(void) unsigned long long sh64_get_wired_dtlb_entry(void)
{ {
...@@ -71,12 +65,10 @@ unsigned long long sh64_get_wired_dtlb_entry(void) ...@@ -71,12 +65,10 @@ unsigned long long sh64_get_wired_dtlb_entry(void)
} }
/** /**
* sh64_put_wired_dtlb_entry * sh64_put_wired_dtlb_entry - Free a wired (locked-in) entry in the DTLB.
* *
* @entry: Address of TLB slot. * @entry: Address of TLB slot.
* *
* Free a wired (locked-in) entry in the DTLB.
*
* Works like a stack, last one to allocate must be first one to free. * Works like a stack, last one to allocate must be first one to free.
*/ */
int sh64_put_wired_dtlb_entry(unsigned long long entry) int sh64_put_wired_dtlb_entry(unsigned long long entry)
...@@ -115,7 +107,7 @@ int sh64_put_wired_dtlb_entry(unsigned long long entry) ...@@ -115,7 +107,7 @@ int sh64_put_wired_dtlb_entry(unsigned long long entry)
} }
/** /**
* sh64_setup_tlb_slot * sh64_setup_tlb_slot - Load up a translation in a wired slot.
* *
* @config_addr: Address of TLB slot. * @config_addr: Address of TLB slot.
* @eaddr: Virtual address. * @eaddr: Virtual address.
...@@ -154,7 +146,7 @@ inline void sh64_setup_tlb_slot(unsigned long long config_addr, ...@@ -154,7 +146,7 @@ inline void sh64_setup_tlb_slot(unsigned long long config_addr,
} }
/** /**
* sh64_teardown_tlb_slot * sh64_teardown_tlb_slot - Teardown a translation.
* *
* @config_addr: Address of TLB slot. * @config_addr: Address of TLB slot.
* *
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
# Shamelessly cloned from ARM. # Shamelessly cloned from ARM.
# #
arch/sh/include/asm/machtypes.h: $(src)/gen-mach-types $(src)/mach-types include/asm-sh/machtypes.h: $(src)/gen-mach-types $(src)/mach-types
@echo ' Generating $@' @echo ' Generating $@'
$(Q)if [ ! -d arch/sh/include/asm ]; then mkdir -p arch/sh/include/asm; fi $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; } $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* SEGA Dreamcast keyboard driver * SEGA Dreamcast keyboard driver
* Based on drivers/usb/usbkbd.c * Based on drivers/usb/usbkbd.c
* Copyright YAEGASHI Takeshi, 2001 * Copyright YAEGASHI Takeshi, 2001
* Porting to 2.6 Copyright Adrian McMenamin, 2007 * Porting to 2.6 Copyright Adrian McMenamin, 2007, 2008
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -45,39 +45,51 @@ struct dc_kbd { ...@@ -45,39 +45,51 @@ struct dc_kbd {
}; };
static const unsigned short dc_kbd_keycode[NR_SCANCODES] = { static const unsigned short dc_kbd_keycode[NR_SCANCODES] = {
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B, KEY_C, KEY_D, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B,
KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V,
KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, KEY_7, KEY_8, KEY_9, KEY_0, KEY_ENTER, KEY_ESC, KEY_BACKSPACE,
KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON,
KEY_DOT, KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT, KEY_SLASH,
KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6,
KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ,
KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE, KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP,
KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP, KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN,
KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2, KEY_UP, KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS,
KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT, KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2, KEY_KP3, KEY_KP4, KEY_KP5,
KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT, KEY_102ND,
KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15,
KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT, KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20, KEY_F21, KEY_F22,
KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE, KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT, KEY_STOP,
KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE,
KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA, KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG, KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_SCREENLOCK, KEY_REFRESH, KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT,
KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT,
KEY_RIGHTMETA, KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG,
KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE,
KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP,
KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP, KEY_SCREENLOCK, KEY_REFRESH,
KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED
}; };
static void dc_scan_kbd(struct dc_kbd *kbd) static void dc_scan_kbd(struct dc_kbd *kbd)
...@@ -127,12 +139,12 @@ static void dc_scan_kbd(struct dc_kbd *kbd) ...@@ -127,12 +139,12 @@ static void dc_scan_kbd(struct dc_kbd *kbd)
static void dc_kbd_callback(struct mapleq *mq) static void dc_kbd_callback(struct mapleq *mq)
{ {
struct maple_device *mapledev = mq->dev; struct maple_device *mapledev = mq->dev;
struct dc_kbd *kbd = mapledev->private_data; struct dc_kbd *kbd = maple_get_drvdata(mapledev);
unsigned long *buf = mq->recvbuf; unsigned long *buf = mq->recvbuf;
/* /*
* We should always be getting the lock because the only * We should always get the lock because the only
* time it may be locked if driver is in cleanup phase. * time it may be locked is if the driver is in the cleanup phase.
*/ */
if (likely(mutex_trylock(&maple_keyb_mutex))) { if (likely(mutex_trylock(&maple_keyb_mutex))) {
...@@ -145,106 +157,96 @@ static void dc_kbd_callback(struct mapleq *mq) ...@@ -145,106 +157,96 @@ static void dc_kbd_callback(struct mapleq *mq)
} }
} }
static int dc_kbd_connect(struct maple_device *mdev) static int probe_maple_kbd(struct device *dev)
{ {
struct maple_device *mdev = to_maple_dev(dev);
struct maple_driver *mdrv = to_maple_driver(dev->driver);
int i, error; int i, error;
struct dc_kbd *kbd; struct dc_kbd *kbd;
struct input_dev *dev; struct input_dev *idev;
if (!(mdev->function & MAPLE_FUNC_KEYBOARD)) if (!(mdev->function & MAPLE_FUNC_KEYBOARD))
return -EINVAL; return -EINVAL;
kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
dev = input_allocate_device(); idev = input_allocate_device();
if (!kbd || !dev) { if (!kbd || !idev) {
error = -ENOMEM; error = -ENOMEM;
goto fail; goto fail;
} }
mdev->private_data = kbd; kbd->dev = idev;
kbd->dev = dev;
memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode)); memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode));
dev->name = mdev->product_name; idev->name = mdev->product_name;
dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
dev->keycode = kbd->keycode; idev->keycode = kbd->keycode;
dev->keycodesize = sizeof (unsigned short); idev->keycodesize = sizeof(unsigned short);
dev->keycodemax = ARRAY_SIZE(kbd->keycode); idev->keycodemax = ARRAY_SIZE(kbd->keycode);
dev->id.bustype = BUS_HOST; idev->id.bustype = BUS_HOST;
dev->dev.parent = &mdev->dev; idev->dev.parent = &mdev->dev;
for (i = 0; i < NR_SCANCODES; i++) for (i = 0; i < NR_SCANCODES; i++)
__set_bit(dc_kbd_keycode[i], dev->keybit); __set_bit(dc_kbd_keycode[i], idev->keybit);
__clear_bit(KEY_RESERVED, dev->keybit); __clear_bit(KEY_RESERVED, idev->keybit);
input_set_capability(dev, EV_MSC, MSC_SCAN); input_set_capability(idev, EV_MSC, MSC_SCAN);
input_set_drvdata(dev, kbd); input_set_drvdata(idev, kbd);
error = input_register_device(dev); error = input_register_device(idev);
if (error) if (error)
goto fail; goto fail;
/* Maple polling is locked to VBLANK - which may be just 50/s */ /* Maple polling is locked to VBLANK - which may be just 50/s */
maple_getcond_callback(mdev, dc_kbd_callback, HZ/50, MAPLE_FUNC_KEYBOARD); maple_getcond_callback(mdev, dc_kbd_callback, HZ/50,
return 0; MAPLE_FUNC_KEYBOARD);
fail: mdev->driver = mdrv;
input_free_device(dev);
maple_set_drvdata(mdev, kbd);
return error;
fail:
input_free_device(idev);
kfree(kbd); kfree(kbd);
mdev->private_data = NULL; maple_set_drvdata(mdev, NULL);
return error; return error;
} }
static void dc_kbd_disconnect(struct maple_device *mdev) static int remove_maple_kbd(struct device *dev)
{ {
struct dc_kbd *kbd; struct maple_device *mdev = to_maple_dev(dev);
struct dc_kbd *kbd = maple_get_drvdata(mdev);
mutex_lock(&maple_keyb_mutex); mutex_lock(&maple_keyb_mutex);
kbd = mdev->private_data;
mdev->private_data = NULL;
input_unregister_device(kbd->dev); input_unregister_device(kbd->dev);
kfree(kbd); kfree(kbd);
mutex_unlock(&maple_keyb_mutex); maple_set_drvdata(mdev, NULL);
}
/* allow the keyboard to be used */
static int probe_maple_kbd(struct device *dev)
{
struct maple_device *mdev = to_maple_dev(dev);
struct maple_driver *mdrv = to_maple_driver(dev->driver);
int error;
error = dc_kbd_connect(mdev);
if (error)
return error;
mdev->driver = mdrv;
mdev->registered = 1;
mutex_unlock(&maple_keyb_mutex);
return 0; return 0;
} }
static struct maple_driver dc_kbd_driver = { static struct maple_driver dc_kbd_driver = {
.function = MAPLE_FUNC_KEYBOARD, .function = MAPLE_FUNC_KEYBOARD,
.connect = dc_kbd_connect,
.disconnect = dc_kbd_disconnect,
.drv = { .drv = {
.name = "Dreamcast_keyboard", .name = "Dreamcast_keyboard",
.probe = probe_maple_kbd, .probe = probe_maple_kbd,
}, .remove = remove_maple_kbd,
},
}; };
static int __init dc_kbd_init(void) static int __init dc_kbd_init(void)
{ {
return maple_driver_register(&dc_kbd_driver.drv); return maple_driver_register(&dc_kbd_driver);
} }
static void __exit dc_kbd_exit(void) static void __exit dc_kbd_exit(void)
{ {
driver_unregister(&dc_kbd_driver.drv); maple_driver_unregister(&dc_kbd_driver);
} }
module_init(dc_kbd_init); module_init(dc_kbd_init);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/se.h> #include <mach-se/mach/se.h>
#include <asm/machvec.h> #include <asm/machvec.h>
#ifdef CONFIG_SH_STANDARD_BIOS #ifdef CONFIG_SH_STANDARD_BIOS
#include <asm/sh_bios.h> #include <asm/sh_bios.h>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Core maple bus functionality * Core maple bus functionality
* *
* Copyright (C) 2007, 2008 Adrian McMenamin * Copyright (C) 2007, 2008 Adrian McMenamin
* Copyright (C) 2001 - 2008 Paul Mundt
* *
* Based on 2.4 code by: * Based on 2.4 code by:
* *
...@@ -31,7 +32,7 @@ ...@@ -31,7 +32,7 @@
#include <mach/dma.h> #include <mach/dma.h>
#include <mach/sysasic.h> #include <mach/sysasic.h>
MODULE_AUTHOR("Yaegshi Takeshi, Paul Mundt, M.R. Brown, Adrian McMenamin"); MODULE_AUTHOR("Yaegashi Takeshi, Paul Mundt, M. R. Brown, Adrian McMenamin");
MODULE_DESCRIPTION("Maple bus driver for Dreamcast"); MODULE_DESCRIPTION("Maple bus driver for Dreamcast");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}"); MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}");
...@@ -65,19 +66,36 @@ static bool checked[4]; ...@@ -65,19 +66,36 @@ static bool checked[4];
static struct maple_device *baseunits[4]; static struct maple_device *baseunits[4];
/** /**
* maple_driver_register - register a device driver * maple_driver_register - register a maple driver
* automatically makes the driver bus a maple bus * @drv: maple driver to be registered.
* @drv: the driver to be registered *
* Registers the passed in @drv, while updating the bus type.
* Devices with matching function IDs will be automatically probed.
*/ */
int maple_driver_register(struct device_driver *drv) int maple_driver_register(struct maple_driver *drv)
{ {
if (!drv) if (!drv)
return -EINVAL; return -EINVAL;
drv->bus = &maple_bus_type;
return driver_register(drv); drv->drv.bus = &maple_bus_type;
return driver_register(&drv->drv);
} }
EXPORT_SYMBOL_GPL(maple_driver_register); EXPORT_SYMBOL_GPL(maple_driver_register);
/**
* maple_driver_unregister - unregister a maple driver.
* @drv: maple driver to unregister.
*
* Cleans up after maple_driver_register(). To be invoked in the exit
* path of any module drivers.
*/
void maple_driver_unregister(struct maple_driver *drv)
{
driver_unregister(&drv->drv);
}
EXPORT_SYMBOL_GPL(maple_driver_unregister);
/* set hardware registers to enable next round of dma */ /* set hardware registers to enable next round of dma */
static void maplebus_dma_reset(void) static void maplebus_dma_reset(void)
{ {
...@@ -129,13 +147,13 @@ static void maple_release_device(struct device *dev) ...@@ -129,13 +147,13 @@ static void maple_release_device(struct device *dev)
kfree(mdev); kfree(mdev);
} }
/* /**
* maple_add_packet - add a single instruction to the queue * maple_add_packet - add a single instruction to the queue
* @mdev - maple device * @mdev: maple device
* @function - function on device being queried * @function: function on device being queried
* @command - maple command to add * @command: maple command to add
* @length - length of command string (in 32 bit words) * @length: length of command string (in 32 bit words)
* @data - remainder of command string * @data: remainder of command string
*/ */
int maple_add_packet(struct maple_device *mdev, u32 function, u32 command, int maple_add_packet(struct maple_device *mdev, u32 function, u32 command,
size_t length, void *data) size_t length, void *data)
...@@ -176,14 +194,15 @@ int maple_add_packet(struct maple_device *mdev, u32 function, u32 command, ...@@ -176,14 +194,15 @@ int maple_add_packet(struct maple_device *mdev, u32 function, u32 command,
} }
EXPORT_SYMBOL_GPL(maple_add_packet); EXPORT_SYMBOL_GPL(maple_add_packet);
/* /**
* maple_add_packet_sleeps - add a single instruction to the queue * maple_add_packet_sleeps - add a single instruction to the queue
* - waits for lock to be free * @mdev: maple device
* @mdev - maple device * @function: function on device being queried
* @function - function on device being queried * @command: maple command to add
* @command - maple command to add * @length: length of command string (in 32 bit words)
* @length - length of command string (in 32 bit words) * @data: remainder of command string
* @data - remainder of command string *
* Same as maple_add_packet(), but waits for the lock to become free.
*/ */
int maple_add_packet_sleeps(struct maple_device *mdev, u32 function, int maple_add_packet_sleeps(struct maple_device *mdev, u32 function,
u32 command, size_t length, void *data) u32 command, size_t length, void *data)
...@@ -724,11 +743,9 @@ static int maple_get_dma_buffer(void) ...@@ -724,11 +743,9 @@ static int maple_get_dma_buffer(void)
static int match_maple_bus_driver(struct device *devptr, static int match_maple_bus_driver(struct device *devptr,
struct device_driver *drvptr) struct device_driver *drvptr)
{ {
struct maple_driver *maple_drv; struct maple_driver *maple_drv = to_maple_driver(drvptr);
struct maple_device *maple_dev; struct maple_device *maple_dev = to_maple_dev(devptr);
maple_drv = container_of(drvptr, struct maple_driver, drv);
maple_dev = container_of(devptr, struct maple_device, dev);
/* Trap empty port case */ /* Trap empty port case */
if (maple_dev->devinfo.function == 0xFFFFFFFF) if (maple_dev->devinfo.function == 0xFFFFFFFF)
return 0; return 0;
......
...@@ -51,7 +51,6 @@ struct maple_devinfo { ...@@ -51,7 +51,6 @@ struct maple_devinfo {
struct maple_device { struct maple_device {
struct maple_driver *driver; struct maple_driver *driver;
struct mapleq *mq; struct mapleq *mq;
void *private_data;
void (*callback) (struct mapleq * mq); void (*callback) (struct mapleq * mq);
unsigned long when, interval, function; unsigned long when, interval, function;
struct maple_devinfo devinfo; struct maple_devinfo devinfo;
...@@ -70,7 +69,9 @@ void maple_getcond_callback(struct maple_device *dev, ...@@ -70,7 +69,9 @@ void maple_getcond_callback(struct maple_device *dev,
void (*callback) (struct mapleq * mq), void (*callback) (struct mapleq * mq),
unsigned long interval, unsigned long interval,
unsigned long function); unsigned long function);
int maple_driver_register(struct device_driver *drv); int maple_driver_register(struct maple_driver *);
void maple_driver_unregister(struct maple_driver *);
int maple_add_packet_sleeps(struct maple_device *mdev, u32 function, int maple_add_packet_sleeps(struct maple_device *mdev, u32 function,
u32 command, u32 length, void *data); u32 command, u32 length, void *data);
void maple_clear_dev(struct maple_device *mdev); void maple_clear_dev(struct maple_device *mdev);
...@@ -78,4 +79,7 @@ void maple_clear_dev(struct maple_device *mdev); ...@@ -78,4 +79,7 @@ void maple_clear_dev(struct maple_device *mdev);
#define to_maple_dev(n) container_of(n, struct maple_device, dev) #define to_maple_dev(n) container_of(n, struct maple_device, dev)
#define to_maple_driver(n) container_of(n, struct maple_driver, drv) #define to_maple_driver(n) container_of(n, struct maple_driver, drv)
#define maple_get_drvdata(d) dev_get_drvdata(&(d)->dev)
#define maple_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p))
#endif /* __LINUX_MAPLE_H */ #endif /* __LINUX_MAPLE_H */
...@@ -266,6 +266,27 @@ void *vmalloc_node(unsigned long size, int node) ...@@ -266,6 +266,27 @@ void *vmalloc_node(unsigned long size, int node)
} }
EXPORT_SYMBOL(vmalloc_node); EXPORT_SYMBOL(vmalloc_node);
#ifndef PAGE_KERNEL_EXEC
# define PAGE_KERNEL_EXEC PAGE_KERNEL
#endif
/**
* vmalloc_exec - allocate virtually contiguous, executable memory
* @size: allocation size
*
* Kernel-internal function to allocate enough pages to cover @size
* the page level allocator and map them into contiguous and
* executable kernel virtual space.
*
* For tight control over page level allocator and protection flags
* use __vmalloc() instead.
*/
void *vmalloc_exec(unsigned long size)
{
return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC);
}
/** /**
* vmalloc_32 - allocate virtually contiguous memory (32bit addressable) * vmalloc_32 - allocate virtually contiguous memory (32bit addressable)
* @size: allocation size * @size: allocation size
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment